新しいリリースバージョンにアップグレードした後、私のbash
スクリプトが次のエラーを吐き出します。
bash: /dev/stderr: Permission denied
以前のバージョンでは、Bashはそれらのファイル名を内部で認識します(そのため、この質問は this one の複製ではありません)。 正しいことをする(tm)しかし、これは現在動作を停止しています。スクリプトを再度正常に実行するにはどうすればよいですか?
スクリプトを実行しているユーザーをグループtty
に追加しようとしましたが、これは(ログアウトして再度ログインした後でも)違いはありません。
私はこれをコマンドラインで問題なく再現できます:
$ echo test > /dev/stdout
bash: /dev/stdout: Permission denied
$ echo test > /dev/stderr
bash: /dev/stderr: Permission denied
$ ls -l /dev/stdout /dev/stderr
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 May 13 02:04 /dev/stdout -> /proc/self/fd/1
$ ls -lL /dev/stdout /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stderr
crw--w---- 1 username tty 136, 1 May 13 05:01 /dev/stdout
$ echo $BASH_VERSION
4.2.24(1)-release
古いシステム(Ubuntu 10.04)の場合:
$ echo $BASH_VERSION
4.1.5(1)-release
これは全体的に bashの問題ではないと思います。
コメントで、あなたは実行後にこのエラーを見たと言った
Sudo su username2
username
としてログインした場合。問題を引き起こしているのはsu
です。
/dev/stdout
は/proc/self/fd/1
へのシンボリックリンクで、たとえば/dev/pts/1
へのシンボリックリンクです。 /dev/pts/1
は疑似端末であり、username
が所有および書き込みが可能です。その所有権はusername
がログインしたときに付与されました。Sudo su username2
を使用した場合、/dev/pts/1
の所有権は変更されず、username2
には書き込み権限がありません。
これはバグだと私は主張します。 /dev/stdout
should事実上、標準出力ストリームのエイリアスですが、ここではecho hello
は機能するがecho hello > /dev/stdout
が失敗する状況を確認します。
回避策の1つは、username2
をグループtty
のメンバーにすることですが、これにより、username2
にany ttyへの書き込み権限が付与されます。これはおそらく望ましくありません。
もう1つの回避策は、su
を使用するのではなくusername2
アカウントにログインして、/dev/stdout
がusername2
が所有する新しく割り当てられた疑似端末を指すようにすることです。これは実用的ではないかもしれません。
別の回避策は、スクリプトが/dev/stdout
および/dev/stderr
を参照しないように変更することです。たとえば、これを置き換えます。
echo OUT > /dev/stdout
echo ERR > /dev/stderr
これで:
echo OUT
echo ERR 1>&2
私のシステム、Ubuntu 12.04、bash 4.2.24でこれが表示されます-私のシステムのbashドキュメント(info bash
)は、/dev/stdout
と/dev/stderr
が特別に扱われると述べていますがリダイレクトで使用されます。ただし、bashがこれらの名前を特別に処理しなくても、標準のI/Oストリームの同等物として機能するはずです。 (POSIXは/dev/std{in,out,err}
について言及していないため、これがバグであると主張するのは難しいかもしれません。)
古いバージョンのbashを見ると、ドキュメントは、ファイルが存在するかどうかにかかわらず、/dev/stdout
などが特別に扱われることを示唆しています。この機能はbash 2.04で導入され、そのバージョンのNEWS
ファイルは次のように述べています。
リダイレクトコードは、ファイルシステムに存在するかどうかに関係なく、/ dev/fd/N、/ dev/stdin、/ dev/stdout、/ dev/stderrなどのいくつかのファイル名を特別に処理するようになりました。
しかし、ソースコード(redir.c
)を調べると、特別な処理が有効になっていることがわかりますonlyシンボルHAVE_DEV_STDIN
が定義されている場合(これは、bashがソースから構築)。
私の知る限り、no bashのリリースバージョンでは、一部のディストリビューションでパッチが適用されていない限り、/dev/stdout
などの特別な処理が無条件に行われています。
別の回避策(私は試していません)は bash sources を取得し、redir.c
を変更して特別な/dev/*
の処理を無条件にし、再構築したバージョンを使用することです。システムに付属しているものよりも。しかし、これはおそらくやり過ぎです。
SUMMARY:
あなたのOSは、私のように、/dev/stdout
と/dev/stderr
の所有権と権限を正しく処理していません。 bash 想定されるは、これらの名前をリダイレクトで特別に扱いますが、実際には、ファイルが存在しない場合にのみ扱います。 /dev/stdout
と/dev/stderr
が正しく機能していれば問題ありません。この問題は、別のアカウントにsu
を実行したとき、または同様のことをしたときにのみ発生します。単にアカウントにログインすると、権限は正しくなります。
実際、これの理由は、udevがttyデバイスのアクセス権を0620に明確に設定し、suが所有権もアクセス権も変更しないためです。私の見解では、これは/ dev/std *を移植不可能にする状況にあります。
簡単な解決策は、「mesg y」を/ etc/profile(または、使用したいトップレベルのプロファイル)に入れることです。これにより、ttyデバイスのアクセス権が0622に変更されます。 udevルールを変更するよりも。
長い間Linuxユーザーとして、私は最近、新しいUbuntu 64ビット12.04 LTSシステムをセットアップしましたが、bashスクリプトが機能しない理由について不思議に思いました—許可が拒否されました—その後、このスレッドを見つけました。新しいOSの問題が原因である可能性があると思いました。
結局のところ、私が愚かにUIツールを使用して/home
ディレクトリにアクセス許可を設定していたことがわかり、問題はdrive-relatedでした。確かに、/opt
にtemp
ディレクトリを作成しましたが、そこからスクリプトを実行しても問題ありません。 /home
ドライブの権限を修正すると、すべてが正常に戻りました。
1つの小さな謎が解決しました。 ため息