ps
オプションが何であれ、結果をgrepしても、列が何であるps
かを示す出力の最初の行を取得できるように小さなラッパーを作成したいと思います。たとえば、の出力はps_wrapper -aux | grep thing
次のようになります。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
name 33925 1.0 0.0 9972 5528 pts/0 Ss 19:34 0:00 /bin/thing
私はそれがうまくいくかどうかを確認しようとし、tee
次のことを試しました。
function ps_wrapper {
tmpfile=$(mktemp)
ps $@ > $tmpfile
head -n 1 $tmpfile >> /dev/stdout
cat $tmpfile
}
しかし私は「手動で」書いたが/dev/stdout
まだgrep
。
ps
印刷される列は使用されているオプションによって変更される可能性があるため、実行中の実際のコマンドの最初の行を印刷したいと思います。
私はzshを使用していますが、より適切なものがあれば他のものを使用しても大丈夫です。
読んでくれてありがとう。
ベストアンサー1
一般的に「パイプをバイパス」することは不可能です。つまり、パイプなしで出力が行ける場所に出力を送ることです。ただし、パイプをバイパスし、端末など、選択した別の場所に出力をリダイレクトできます。特殊ファイルは/dev/tty
常に現在の端末を表します。
function ps_wrapper {
tmpfile=$(mktemp)
ps "$@" > $tmpfile
head -n 1 $tmpfile >/dev/tty
cat $tmpfile
rm $tmpfile
}
元の場所を「保存」して下に渡すと、パイプをバイパスすることもできます。ファイル記述子を通して。しかし、ps_wrapper
関数ではそれを行うことはできません。
function ps_wrapper {
tmpfile=$(mktemp)
ps "$@" > $tmpfile
head -n 1 $tmpfile >&3
cat $tmpfile
rm $tmpfile
}
{ ps_wrapper … | grep …; } 3>&1
一時ファイルの生成を防ぐ方法はいくつかあります。いくつか言及します。特に明記しない限り、この回答の解決策は次の場合にbashで動作します。変数とコマンドの置換の周りに二重引用符を追加する。
関数の呼び出し方法を変更したい場合は、head
パイプの右側から連続して両方を呼び出すことができます。最初の行を読んで印刷し、残りは後続のジョブのために残します。grep
head
ps … | { head -n 1; grep …; }
あなたはできますプロセスの交換そしてtee
またはzshにtee
似た機能組み込み( multios
)出力をコピーするには、あるストリームを選択したコマンドに送信head -n 1
し、別のストリームを選択したコマンドに送信します。ただし、各ストリームをコマンドにパイプすると、2つの間で競合が発生し、head
速度が十分に速くない場合、最初の行が一番上に表示されない可能性があります。かなり高速なので、頻繁に動作することがありますが、たとえばディスクキャッシュにhead
ありますが、そうでない場合は保証できません。grep
head
ps | tee >(head -n 1 >/dev/tty) | grep …
ps >(head -n 1 >/dev/tty) | grep … # zsh only, only if multios is not disabled
awkを使用して最初の行を表示してから、残りの行を渡すことができます。
function ps_wrapper {
ps "$@" | awk 'NR == 1 {print >"/dev/tty"} NR != 1 {print}'
}
説明する:
- awkは入力を1行ずつ処理します。
- 健康状態{パスワード}実装するパスワード満足のラインで健康状態。
NR
行番号です。- awkのリダイレクトはシェルとまったく同じではありませんが、十分に似ています。
print
引数なしで入力行を印刷します。
別のアプローチは、フィルタ機能を単一のコマンドで構築することです。引数に表示されないps
区切り文字として使用する文字列を選択します(例:)|
。
function pipe_preserving_first_line {
local lhs
lhs=()
while [[ $1 != '|' ]]; do
lhs+=($1)
shift
done
shift
"${lhs[@]}" | {
head -n 1;
"$@"
}
}
pipe_preserving_first_line ps u \| grep foo
たとえば、コマンド名でプロセスを一致させるには、ps
grepの代わりに一致関数を使用できます。-C
ps uww -C mycommand
grepを使用することに加えて、マッチングpgrep
ツールを使用することもできます。
ps -p $(pgrep -d, mycommand)