私はTシャツの経験があまりないので、これは非常に基本的なものではないことを願っています。
回答のいずれかを確認した後この問題奇妙な動作が発生しましたtee
。
最初の行と見つかった行を出力するには、次のコマンドを使用できます。
ps aux | tee >(head -n1) | grep syslog
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
syslog 806 0.0 0.0 34600 824 ? Sl Sep07 0:00 rsyslogd -c4
しかし、最初にこれを(zshで)実行したときにgrepの結果の下に列ヘッダーがある結果の順序が間違っていたので(しかし、この問題は再び発生しませんでした)、コマンドを置き換えました。
ps aux | tee >(grep syslog) | head -n1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
最初の行だけが印刷され、他のものは印刷されません! teeを使ってgrepにリダイレクトできますか?それとも間違った方法でやっていますか?
2番目のコマンドは実際にこの質問を入力したときにもう一度動作し、さらに5回実行したところ、1行の結果が返されました。これは私のシステムですか? (私はtmuxでzshを実行しています)。
最後に、最初のコマンド「grep syslog」が結果として表示されないのはなぜですか?
ここで制御するにはgrepなしtee
ps aux | grep syslog
syslog 806 0.0 0.0 34600 824 ? Sl Sep07 0:00 rsyslogd -c4
henry 2290 0.0 0.1 95220 3092 ? Ssl Sep07 3:12 /usr/bin/pulseaudio --start --log-target=syslog
henry 15924 0.0 0.0 3128 824 pts/4 S+ 13:44 0:00 grep syslog
修正する: headはコマンド全体を切り捨てたように見えます(以下の回答を参照)、次のコマンドは次を返します。
ps aux | tee >(grep syslog) | head -n1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
syslog 806
答え1
$ ps aux | tee >(head -n1) | grep syslog
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
syslog 806 0.0 0.0 34600 824 ? Sl Sep07 0:00 rsyslogd -c4
grep
コマンドはhead
ほぼ同じ時間に始まり、両方がアイドル状態のときに同じ入力データを受け取りますが、通常、データが利用可能なときに受信されます。たとえば、次の問題が原因で「非同期」出力が発生する可能性があります。
多重化されたデータは、
tee
実際には他のプロセスの前に1つのプロセスに転送され、ほとんどの実装によって異なりますtee
。単純なtee
実装では、read
一定量の入力を受け取り、write
それを2回提供します。一度は標準出力として、一度は引数として提供します。これは、これらのターゲットの1つが最初にデータを取得することを意味します。ただし、パイプはバッファリングされます。これらのバッファーはそれぞれ 1 つ減らす可能性が高くなりますが、大きくすることもできます。これにより、
grep
他のコマンドがhead
データ(例:pedライン)を受信する前に、受信コマンドの1つが必要なすべての出力(例:pedライン)を表示できます。すべて。ただし、これらのコマンドの1つはデータを受信しますが、時間内に何も実行できず、他のコマンドがより多くのデータを受信してすばやく処理することもできます。
たとえば、データが一度に 1 行ずつ送信されても、何を
head
すべきかわからない場合(またはカーネルスケジューリングのために遅延する場合)、チャンスが発生する前に結果が表示されることがあります。デモンストレーションするには、遅延を追加してみてください。これにより、ほぼ確実に出力が最初に印刷されます。grep
head
grep
head
ps aux | tee >(sleep 1; head -n1) | grep syslog
grep
$ ps aux | tee >(grep syslog) | head -n1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
head
私は入力の最初の行を受け取り、標準入力を閉じて終了するので、ここでは通常1行しか得られないと思います。tee
stdoutが閉じられていることを確認すると、独自のstdin(の出力)を閉じてps
終了します。これは実装によって異なります。
実際にps
送信される唯一のデータは最初の行(もちろん制御されるため)であり、head
標準入力記述子の前後の別の行にすることもできます。head
tee
2行目に現れる不一致は、タイミングによって発生します。head
stdinは閉じていますが、ps
データは転送され続けます。両方のイベントが正しく同期されていないため、含まれている行がまだパラメータ(コマンド)syslog
になる可能性があります。これは上記の説明と同様である。tee
grep
stdin / exitを閉じる前にすべての入力を待つコマンドを使用すると、この問題を完全に回避できます。たとえば、awk
代わりにを使用するhead
と、すべての行を読み取って処理します(出力が発生しなくても)。
ps aux | tee >(grep syslog) | awk 'NR == 1'
ただし、上記のように、行はまだ順番に表示されない場合があります。
ps aux | tee >(grep syslog) | (sleep 1; awk 'NR == 1')
あまりにも詳細な情報ではないことを願っていますが、同時に互いに対話する多くのことが起こっています。別のプロセスは同期せずに同時に実行されるため、特定の実行に対する操作が異なる場合があります。時々、基本プロセスを詳しく見て、その理由を説明するのに役立ちます。
答え2
grep syslog
時期によって異なるため、必ず表示されるわけではありません。シェルパイプを使用すると、ほぼ同時にコマンドを実行します。しかし、ここで重要なのは「ほぼ」という言葉です。 grepを開始する前にすべてのプロセスのチェックが完了した後、リストps
には表示されません。システム負荷などに応じてランダムな結果が得られます。
Tシャツでも同様のことが起こります。サブシェルのバックグラウンドで実行され、grepの前後にトリガーできます。これが出力順序が一貫していない理由です。
ティーの問題は奇妙に動作します。これは一般的な方法では使用されないためです。これは引数なしで実行されます。つまり、標準入力から標準出力にデータをコピーする必要があることを意味します。ただし、標準出力はヘッダー(最初の場合)またはgrep(2番目の場合)を実行するサブシェルにリダイレクトされます。ただし、次のコマンドにもパイプされます。この場合、何が起こるかは実際には実装に依存していると思います。たとえば、私のbash 4.2.28では、サブシェルのstdinには何も記録されません。 zshは、試すたびに必要な方法で安定して動作します(psの最初の行と検索された行を印刷します)。
答え3
少しハッキング的ですが、ここで私が使用するシェル関数の形の解決策がありますpsgrep()
。
ヘッダー行ps
をにリダイレクトSTDERR
してからgrep
リダイレクトしますが、それ自体で発生する「ノイズ」行を防ぐには、STDOUT
まずgrep
コマンド自体を削除します。grep
psgrep() { ps aux | tee >(head -1>&2) | grep -v " grep $@" | grep "$@" -i --color=auto; }