シェルスクリプトにこのようなものがあるとしましょう。
command1 | command2
command2
これで終了時にどのように終了することができますかcommand1
?
編集する:
command2
これは通常、標準入力から読み取ろうとするとデフォルトで発生し、ゼロを返します。具体的な例はありますか?
ここにあります:echo test | xmobar
xmobar
これも代用として使ってもいいと思います。
#!/bin/sh
while :; do :; done
答え1
このコメントパイプのもう一方の端が閉じたときにプログラムがどのように終了するか(または終了しないか)説明します。
パイプを閉じても何も
command1
知らせません。パイプを読み、空にし、EOFを得るcommand2
までcommand2
何も起こりません。それにもかかわらず、まだやることが残っていれば終了する必要はありません。同様に、command2
最初に終了するとcommand1
パイプに書き込まれるまで検索されず、この時点でSIGPIPE
それをキャプチャすると他の操作も続行できます。
だからこれは自動的に起こることができます。今あなたの質問は次のとおりです
command1 | command2
[未知または不要な場合]終了時に
command2
終了するにはどうすればよいですか?command1
command2
シェルが別々のプロセスグループでパイプを実行している場合は、グループ全体を終了してみてください。たとえば、Bashはジョブ制御が有効になっている場合(set -m
)この操作を実行します。対話型シェル(サポートされているシステム)ではデフォルトで有効になっていますが、スクリプトでは有効になっていません。
サンプルコード:
#!/bin/bash
set -m
( command1; kill -s INT 0 ) | command2
パイプライン全体は、最初の部分のPIDと同じプロセスグループID(PGID)を持つ別々のプロセスグループで実行されます。この場合はサブシェルです。kill 0
自分のプロセスグループにシグナルを送信します。これは終了後に信号を送信しますcommand2
。command1
メモ:
- これはBashに
kill
組み込まれているため、このkill
例ではPIDとPGIDが割り当てられた別々のプロセスはありません。したがって、上記の「自己プロセスグループ」という文は厳密ではなく、「サブシェルのプロセスグループ」でなければなりません。これはまだ私たちが使用したい正確なプロセスグループです。組み込みkill
でも/bin/kill
使用可能でも、どちらか一方が可能です。 command2
独自のプロセスグループを変更できます。その場合、このソリューションは機能しません。command2
その信号を無視したり、ほぼすべての方法で処理することが可能です。あなたのニーズに合った信号を選択してください。kill
終了後すぐに電話することは時期尚早かもしれませんcommand1
。command2
生成されたすべてのデータを読み取って処理する前に終了することができます。command1
おそらくすべてのデータを処理したいと思います。command2
動作によっては、遅延が役立つ場合がありますkill
(例sleep 2; kill …
:)。 (汎用)Linuxはそうではありません。リアルタイムオペレーティングシステムしたがって、状況が深刻になると、固定遅延が短すぎる可能性があります。