新しいディストリビューションにアップグレードした後、スクリプト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
失敗する状況を見ることができます。
username2
1つの解決策は、グループのメンバーになることです。ただし、これにより書き込み権限がtty
付与されます。username2
どのtty、これは望ましくないかもしれません。
username2
別の回避策は、使用する代わりにアカウントにログインして、所有する新しく割り当てられた疑似端末を指すことsu
です。これは実用的ではないかもしれません。/dev/stdout
username2
別の回避策は、スクリプトを参照しないように変更することです/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/stdout
et 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`