数週間前、私は何かを見ました。奇妙な答えこの問題について」(方法)バックグラウンドで自動的に作業を開始しますか?".この回避策は間違っているようです(私の答えを比較してください)シェルがバックグラウンドで自動的に作業を開始するようですが。
I.質問:シェル標準エラーを実際にリダイレクトできますか?
提案された解決策についての説明はなく、分析でも明確な答えを提供しません。
下からコードの断片を見ることができます。
# Run the command given by "$@" in the background
silent_background() {
if [[ -n $BASH_VERSION ]]; then
{ 2>&3 "$@"& } 3>&2 2>/dev/null
fi
}
問題のコマンドはです{ 2>&3 "$@"& } 3>&2 2>/dev/null
。
1) 分析
コマンドグループ()は、1つのコマンド()に{ ... }
2つのリダイレクト(および)を指定します。3>&2
コマンドは、リダイレクト()を含む非同期リスト()です。2>/dev/null
# Run the command given by "$@" in the background
cmd&
2>&3
POSIX仕様
各リダイレクトは、そのリダイレクトを明示的にオーバーライドしない複合コマンドのすべてのコマンドに適用する必要があります。
標準エラーリダイレクトは、非同期2>/dev/null
リストに関連付けられたリダイレクトに上書きされます2>&3
。
特定のケース
最初の場合は標準エラーがにリダイレクトされ/dev/null
、2番目の場合は標準エラーが次にリダイレクトされます。注文するまだ端末に接続されています。
prompt% { grep warning system.log& } 2>/dev/null
prompt% { 2>&3 grep warning system.log& } 3>&2 2>/dev/null
grep: system.log: No such file or directory
以下でも同様のケースを見ることができます。最初のケースでは、標準出力注文するまだ端末に接続されています。 2番目のケースでは、標準出力がリダイレクトされます。注文する修正済み:>echo.txt
上書きしました>print.txt
。
prompt% { >&3 echo some data...& } 3>&1 >echo.txt
[1] 3842
some data...
prompt% file echo.txt
echo.txt: empty
prompt% { >&3 echo some data...& } 3>print.txt >echo.txt
[1] 2765
prompt% file echo.txt
echo.txt: empty
prompt% cat print.txt
some data...
ii) 観察
前述のように、コマンドはバックグラウンドで自動的に開始されるようです。より正確に[1] 3842
は、たとえば、バックグラウンドジョブに関する通知は表示されません。
以前の分析では、リダイレクトがキャンセルされる可能性があるため、重複していることがわかりました。
{ redir_3 cmd& } redir_1 redir_2
cmd&
.
iii) 説明
上記の構成は、副作用のために通知を隠すようです。
このようなことがどのように起こるかを説明できますか?
2. 仮説
Ilkkachuの回答とコメント少し進歩を許してください。各プロセスには独自のファイル記述子があります。
- シェルメッセージは、シェル標準エラー時に送信される可能性があります。
別のコンテキスト:サブシェルで実行される非同期のリストです。コマンドはg
存在しません。
prompt% ( g& )
g: command not found
非同期コマンド、括弧で囲まれたコマンド...は、シェル環境と重複するサブシェル環境で実行されます。
子シェルは、親シェルから標準エラーストリームの値を継承します。
したがって、前者の場合、標準エラーストリームを端末に渡す必要があります。ただし、ジョブ通知は表示されず、シェル標準エラーにはシェルエラーメッセージが表示されることがあります。
ベストアンサー1
最も重要な点を見逃しています。シェルリダイレクトは左から右に適用されます。
存在する:
{ 2>&3 "$@"& } 3>&2 2>/dev/null
完全なコマンドグループは次のように実行されます。
- ファイル記述子3 =>標準エラー、つまり端末この時に。
- ファイル記述子2(標準エラー)=> /dev/null
したがって、グループ内のコマンドが実行されるとき:
- 標準エラー=>ファイル記述子3、端末を指しています。
したがって、"$@"&
標準エラーで印刷される項目がある場合、出力は端末に印刷されます。
特定のケースの場合:
{ grep warning system.log& } 2>/dev/null
{ grep warning system.log& }
標準エラーへのポインタとして実行されます/dev/null
。grep
リダイレクトをオーバーライドしないため、標準エラーはと同じで{...}
リダイレクトされ、/dev/null
端末に出力は提供されません。
存在する:
{ 2>&3 grep warning system.log& } 3>&2 2>/dev/null
grep
標準エラーは、上記のように端末を指すファイル記述子3にリダイレクトされるため、出力を端末に送信できます。