バックグラウンドパイプラインの前のコマンドのPID

バックグラウンドパイプラインの前のコマンドのPID

スクリプトのフラグメントがあります:

MyCoolCommand 2>&1 | tail -n 256 > "report.out" &
cool_pid=$!  # FIXME

バグがあります -cool_pidの PID ですtail。パイプラインはバックグラウンドで実行されています。cool_pidの PIDを に保存するにはどうMyCoolCommandすればよいですか? シェルは /bin/sh です。古いプレーンな /bin/sh では不可能な場合は、実現方法があれば Bash に切り替える準備ができています。

答え1

Bash ではプロセス置換を使用できます:

MyCoolCommand > >(tail -n 256 > report.out) 2>&1 &
cool_pid=$!

データは元のコマンドと同様に から に流れますが、MyCoolCommand希望どおりのものになります。tail$!

ノート:

  • 2>&1後にする必要がある>
  • MyCoolCommandシェルは終了直後にジョブが完了したとみなしますが、tailまだ実行中かもしれないスクリプトがwaitジョブの途中で終了し、その後report.outさらに処理する場合、ファイルはまだ準備できていない可能性があることに注意してください。比較すると、スクリプトはMyCoolCommand | tail … &完了したと見なされます。両方プロセスが終了します。

この問題はプレーンな形式で解決できますshが、手動での配管が必要になります。

mkfifo myfifo
<myfifo tail -n 256 >report.out &
MyCoolCommand >myfifo 2>&1 &
cool_pid=$!
rm myfifo

ノート:

  • FIFO がまだ使用されているときに削除するのは安全です。ディレクトリからリンクが解除されているにもかかわらず、プログラムはそれを使い続けます。OS は、FIFO が使用されなくなったときにのみ、それを本当に破壊します。新しいファイルmyfifo(作成された場合) は、古いファイルがまだ使用されている場合でも、古いファイルとは何の関係もありません (名前を除く)。

  • 指定されたファイルmyfifoが既に現在の作業ディレクトリにあり (スクリプトの別のインスタンスが並行して実行されているか、または何らかの理由で)、使用中である場合、スクリプトは誤動作する可能性があります。適切な対処法は、 で一時ディレクトリを作成しmktemp -d、そこに FIFO を配置することです。mktempは移植性がありません。

  • この方法では、PIDを保存できますMyCoolCommand そしての PID を独立して指定しますtail

関連情報