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

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

新しいディストリビューションにアップグレードした後、スクリプトbashでエラーが発生し始めました。

bash: /dev/stderr: Permission denied

以前のバージョンでは、Bash内部認定このファイル名(したがって、この質問は重複しません。これ)と正しいことをしなさい(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

答え1

私の考えではこれではないと思います。完全バッシュの問題。

コメントでこれを行った後、このエラーが発生したと言われました。

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 しなければならない実際、これは標準出力ストリームのエイリアスですが、ここではecho hello正常に動作しますがecho hello > /dev/stdout失敗する状況を見ることができます。

username21つの解決策は、グループのメンバーになることです。ただし、これにより書き込み権限がtty付与されます。username2どのtty、これは望ましくないかもしれません。

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

別の回避策は、スクリプトを参照しないように変更することです/dev/stdout/dev/stderrたとえば、次のようになります。

echo OUT > /dev/stdout
echo ERR > /dev/stderr

だから:

echo OUT
echo ERR 1>&2

info bash私のシステムのbashドキュメントにそのようなものがあり、/dev/stdoutリダイレクト/dev/stderrに使用されるときに特別な処理があるにもかかわらず、私のシステムであるUbuntu 12.04、bash 4.2.24でこの現象が発生します。ただし、Bashがこれらの名前を特に処理していなくても、標準I / Oストリームの同等の名前として使用する必要があります。 (POSIXではこれについて言及していないので、/dev/std{in,out,err}バグと言うのは難しいです。)

以前のバージョンのbashを見ると、文書によると、ファイルが存在するかどうかにかかわらず、/dev/stdoutet alが特別に扱われることを示唆しています。この機能はbash 2.04で導入され、NEWSそのバージョンのドキュメントは次のとおりです。

リダイレクトコードは、ファイルシステムに存在するかどうかにかかわらず、/dev/fd/N、/dev/stdin、/dev/stdout、/dev/stderrなど、複数のファイル名を具体的に処理します。

ところで、ソースコード( )を確認すると、redir.c特別なハンドリングが有効になっていることがわかります。ただシンボルが定義されているかどうかHAVE_DEV_STDIN(bashがソースから構築されたときに決定されます)

私が知る限り、いいえBashのディストリビューションバージョンには、すでに/dev/stdoutいくつかのディストリビューションでパッチを適用していない限り、et alのための無条件の特別な処理機能があります。

だから(私が試していない)もう一つの解決策はバッシュソースredir.c、特別な処理が無条件に行われるように修正し、/dev/*システムに付属のバージョンの代わりに再構築したバージョンを使用してください。ただし、これは過剰になる可能性があります。

要約:

/dev/stdout私のようなあなたのオペレーティングシステムは、との所有権と権限を正しく処理しません/dev/stderr。強く打つおそらくこれらの名前はリダイレクトで特に処理されますが、実際にはファイルが存在しない場合にのみ実行されます。/dev/stdoutいつ正常に動作するかは重要ではありません/dev/stderr。この問題は、su別のアカウントを使用するか、1つのアカウントにログインしたばかりの権限が正しい場合にのみ発生します。

答え2

同じ行をユーザーがそのまま表示できるコンソール(またはリダイレクトされた場合はログファイル)に移動したいので、そしてこれを解析するフィルタにsomecommand | tee /dev/stderr | myfilter

sudoこの問題は、ユーザーが -ing 後にスクリプトを実行しようとしたときに発生します。

解決策/dev/stderrは書き込み可能であることを確認することです。

  • 無関係sudoまたは
  • 標準エラーがファイルにリダイレクトされる場合

だからこれが私がしたことです:

if [ -w /dev/stderr ]
then
        STDERR=/dev/stderr
else
        STDERR=/dev/tty # The only reason is that stderr is a link to console
fi
...
somecommand | tee $STDERR | myfilter

答え3

実際、その理由は、udevがttyデバイスで権限を0620に具体的に設定し、suは所有権や権限を変更せず、変更してはいけないからです。私の考えでは、これが/dev/std*を移植できない状況に直面させると思います。

簡単な解決策は、「mesg y」を/ etc / profile(または使用したいトップレベルプロファイル)に配置することです。これにより、ttyデバイスの権限が0622に変更されます。私はこれがあまり好きではありませんが、udevルールを変更するよりも優れています。

答え4

これは理想的ではありませんが、問題が発生した後に問題を解決するには、次の手順を実行します。

sudo chown -v $USER `tty`

関連情報