
スクリプトのフラグメントがあります:
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
。