bash:/ dev / stderr:許可が拒否されました


19

新しいリリースバージョンにアップグレードした後、bashスクリプトでエラーが発生し始めます。

bash: /dev/stderr: Permission denied

以前のバージョンでは、bashのだろう内部で認識(この質問が重複のない理由であるもののファイル名を、この1)と、正しいこと(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
ls -l /dev/stdout /dev/stderrand の出力は何ls -lL /dev/stdout /dev/stderrですか?
キーストンプソン

@キース:編集した質問をご覧ください。それは、Bashがこれの内部処理を完全に放棄したことを意味しますか?古いシステムでは、これらのシンボリックリンクは存在しませんでしたが、コードは問題なく機能しました。注、これは経由して、偽装実行しているsudo su username2 -...
0xC0000022L

どのbashバージョンを使用していますか?echo $BASH_VERSION
ジッピー

1
古いバージョンと新しいバージョンは何ですか(OSとbashの前後)?
キーストンプソン

回答:


41

これが完全にbashの問題だとは思わない。

コメントで、あなたはこの後にこのエラーを見たと言った

sudo su username2

としてログインしたときusername。それsuが問題を引き起こしているのです。

/dev/stdoutはへのシンボリックリンクです/proc/self/fd/1。これは、などへのシンボリックリンク/dev/pts/1です。/dev/pts/1、これは擬似端末であり、所有者であり、書き込み可能ですusernameusernameログインすると、その所有権が付与されます。の場合sudo su username2、の所有権は/dev/pts/1変更されusername2ず、書き込み権限もありません。

これはバグだと主張します。 実際には、標準出力ストリームのエイリアスである/dev/stdout 必要がありますが、ここではecho hello機能するがecho hello > /dev/stdout失敗する状況を確認します。

回避策の1つusername2は、groupのメンバーを作成することですが、これにより任意の tty への書き込み許可ttyが与えusername2られますが、これはおそらく望ましくありません。

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

彼らはを参照していないので、別の回避策は、あなたのスクリプトを変更することであろう/dev/stdout/dev/stderr。たとえば、これを置き換えます:

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

これで:

echo OUT
echo ERR 1>&2

私はbashの4.2.24で、私自身のシステムは、Ubuntu 12.04でこれを見る- bashのドキュメント(にもかかわらず、info bash私のシステムでは)と言う/dev/stdoutと、/dev/stderrリダイレクトに使用された場合、特別に扱われます。ただし、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た。

したがって、別の回避策(私は試していません)は、bashソースを取得し、変更することですredir.c、特別な/dev/*処理が無条件になるようし、システムに付属しているバージョンではなく、再構築したバージョンを使用します。ただし、これはおそらく過剰です。

要約:

お使いのOSは、鉱山のような、の所有権とアクセス権を処理していない/dev/stdout/dev/stderr、正しく。bashはおそらくリダイレクトに特別にこれらの名前を扱いますが、ファイルが存在しない場合にのみ、実際にはそう。それは問題ではなく/dev/stdout/dev/stderr正しく動作します。この問題はsu、別のアカウントにアクセスするか、同様のことを行う場合にのみ発生します。アカウントに単純にログインする場合、権限は正しいです。


TTYの所有権を変更する必要があります。それがConsoleKit(別名pam_ck_connector.so)です。
ミケル

実際、私は間違っている可能性があります。もっと掘る必要があります。
ミケル

私のシステムで/proc/self/fd/1は、パーミッションが更新されていますが、それはシンボリックリンクなので、それは無意味です。Fedoraでも起こりますが、これはConsoleKitを除外しているようです。
ミケル

1

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

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


「MSGのY」は動作しません
ルチアーノ

待ってください... Bashの検索は、Bashのmanページのリダイレクト使用される場合、いくつかのファイル名を特別に処理します
0xC0000022L

0

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

結局、私は愚かにもUIツールを使用して/homeディレクトリにアクセス許可を設定し、問題はドライブに関連していたことがわかりました。確かに、tempディレクトリを作成し/optましたが、そこからスクリプトが正常に実行されることがわかりました。修正したら/homeドライブのアクセス許可すべてが正常に戻りました。

1つの小さな謎が解決しました。はぁ


2
これは別のエラーである必要があります。/ homeで何かを変更しても、/ devには影響しません。
-ott--

-1

これは古い質問ですが、私はまだ非常に関連性があると思うので、ここで言及されていない解決策があります。

bashでこのようなコマンドを実行する 'su'スイッチアカウントでも問題が発生したため、この質問に出会いました。

echo test > /dev/stderr

私がやろうとしているのはstdoutをstderrにリダイレクトするだけなので、以下は同じことを達成し、 'su'スイッチアカウントでも機能します。

echo test 1>&2
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.