他のコマンドを実行するコマンドの標準があり、シェル構造をどのようにリダイレクトと見なすことができますか?

他のコマンドを実行するコマンドの標準があり、シェル構造をどのようにリダイレクトと見なすことができますか?

次のコマンドの機能を実行する簡単な方法はありますか?

watch foo 2>/dev/null | tr ' ' '-'
strace foo 2>/dev/null | tr ' ' '-'
something_else foo 2>/dev/null | tr ' ' '-'    

物事がどのように行動するべきかについての共有された期待はありますかsomething_else?これらのコマンド(どのプログラムの出力がリダイレクトされるかなど)を明確にすることができるシェル構造はありますか?

答え1

コマンド自体はリダイレクトを処理しません。シェルがコマンドを実行する新しいプロセスを作成すると、シェルは指示に従ってIOを設定します。コマンド自体は実行されるので、気にする必要はありません。

あなたのsomething_elseコマンドは通常どおり出力をstdoutとstderrに送ります。

答え2

簡単に言うと:

some_elseがどのように機能するのかという共通の期待はありますか?

はい、常設命令です。シェルは2つのコマンドを理解していません。これはコマンドと引数です(command1 command2たとえば、有効なバイナリの名前かもしれません)。/binこれはcommand1後でシェルではなくシステムコールを介して command2実行されます。exec()

これらのコマンド(どのプログラムの出力がリダイレクトされるかなど)を明確にすることができるシェル構造はありますか?

いいえ、someting_else特別な治療を受けません。前述のように、コマンドと引数以外の構造はありません。この問題に対する混乱は次のようなものにあるようです。両方 straceシェルによって実行されると仮定しますが、foo実際には親 - サブプロセスチェーンです。

シェルがコマンドとリダイレクトを処理する方法

Bourne(たとえば、、、bashdashなどkshのシェルは、すべてコマンド解決方法についてPOSIXの規則に従います。POSIXの指定: ""単純なコマンド"は任意の順序でオプションの変数の割り当てとリダイレクトのシーケンスであり、オプションでワードとリダイレクトが続き、制御演算子で終了します。これはテーブルとして作成できます。

[VAR=foo BAR=baz] command1 [arg1, arg2...] [ n>m ]

一般的な規則は、ほとんどの非割り当て単語を保存するコマンドにリダイレクトが適用されることです。あなたの例ではstraceコマンドですがfoo引数ですstrace。リダイレクトは引数ではなくコマンドに対してのみ機能します。つまり、シェルによって実行さstraceれず、この場合は子プロセスによって実行されます。今回もパラメータ付きのコマンドとして扱われます。foostracefoostracesomethingelsefoo

ファイル記述子

組み込まれていないコマンドに関する限り、そのコマンドはシェルの子プロセスであり、子プロセスはシェルのファイル記述子を継承するため、通常はリダイレクトを管理しません。 「事前にパッケージ化された」宛先を受け取るので、strace現時点では2>/dev/nullそうです。ファイル記述子2が実際に何であるかは気にしません(ソースコードレベルを積極的に確認しない限り)。strace出力はまだファイル記述子2に書き込まれますが、シェルはそのファイル記述子を/dev/null

strace stat noexist 2>stracelog.txtファイル記述子は継承されるため、両方のエラーストリームでこのような操作を実行してstrace同じstatファイルに移動する理由も説明されています。対照的に、一部のコマンドでは、ターゲットをオプションの1つとして明示的に指定できます。したがって、ファイルに出力のみがありますstrace -o tracelog.txt stat noexist 2>stracelog.txt。ファイル記述子が継承されてもフラグはの属性であり、ファイル記述子が継承されても出力はコマンドによって管理されます。statstracelog.txt-ostrace

これはまた少しヒントを提供します。理論的には、コマンドは「リダイレクト」することができます。つまり、ファイル記述子はシステムコールを介して既存のファイル記述子にコピーされますdup2()。これはシェルで使用されるメカニズムとまったく同じですが、リダイレクトシンボルの用語>タイプに関する限り、これはまだシェル制御下にあるため、親シェルによってのみ解釈できます。

なぜ2>/dev/nullですか?

通常、診断出力がに送信されることが知られていますstderr。実際には、そのトピックに関する2つの素晴らしい記事がすでにあります。

watchあなたの例の規則に従ってくださいstrace。それがすべてです。2>/dev/nullそのようなコマンドの出力を隠すように指定する要件自体はありません。

たとえば、引数として渡されるコマンドのリダイレクトを実際に指定するには、straceそのコマンドの周囲にシェルが必要です。例えば、

strace -f bash -c 'stat /etc/passwd nonexisting 2>/dev/null'

フラグを使用するときは注意してください-f。コマンドに適用されたシステムコールを追跡することに焦点を当てると、statフラグなしではその呼び出しを見ることができないからです-f

関連情報