web-dev-qa-db-ja.com

bash:/ dev / stderr:権限が拒否されました

新しいリリースバージョンにアップグレードした後、私の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
21
0xC0000022L

これは全体的に 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/stdoutshould事実上、標準出力ストリームのエイリアスですが、ここではecho helloは機能するがecho hello > /dev/stdoutが失敗する状況を確認します。

回避策の1つは、username2をグループttyのメンバーにすることですが、これにより、username2any ttyへの書き込み権限が付与されます。これはおそらく望ましくありません。

もう1つの回避策は、suを使用するのではなくusername2アカウントにログインして、/dev/stdoutusername2が所有する新しく割り当てられた疑似端末を指すようにすることです。これは実用的ではないかもしれません。

別の回避策は、スクリプトが/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を実行したとき、または同様のことをしたときにのみ発生します。単にアカウントにログインすると、権限は正しくなります。

43
Keith Thompson

実際、これの理由は、udevがttyデバイスのアクセス権を0620に明確に設定し、suが所有権もアクセス権も変更しないためです。私の見解では、これは/ dev/std *を移植不可能にする状況にあります。

簡単な解決策は、「mesg y」を/ etc/profile(または、使用したいトップレベルのプロファイル)に入れることです。これにより、ttyデバイスのアクセス権が0622に変更されます。 udevルールを変更するよりも。

1
Wheely

長い間Linuxユーザーとして、私は最近、新しいUbuntu 64ビット12.04 LTSシステムをセットアップしましたが、bashスクリプトが機能しない理由について不思議に思いました—許可が拒否されました—その後、このスレッドを見つけました。新しいOSの問題が原因である可能性があると思いました。

結局のところ、私が愚かにUIツールを使用して/homeディレクトリにアクセス許可を設定していたことがわかり、問題はdrive-relatedでした。確かに、/opttempディレクトリを作成しましたが、そこからスクリプトを実行しても問題ありません。 /homeドライブの権限を修正すると、すべてが正常に戻りました。

1つの小さな謎が解決しました。 ため息

0
Ichiro Furusato