「出力」プロセスが終了すると、匿名パイプの終了

「出力」プロセスが終了すると、匿名パイプの終了

シェルスクリプトにこのようなものがあるとしましょう。

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終了するにはどうすればよいですか?command1command2

シェルが別々のプロセスグループでパイプを実行している場合は、グループ全体を終了してみてください。たとえば、Bashはジョブ制御が有効になっている場合(set -m)この操作を実行します。対話型シェル(サポートされているシステム)ではデフォルトで有効になっていますが、スクリプトでは有効になっていません。

サンプルコード:

#!/bin/bash
set -m
( command1; kill -s INT 0 ) | command2

パイプライン全体は、最初の部分のPIDと同じプロセスグループID(PGID)を持つ別々のプロセスグループで実行されます。この場合はサブシェルです。kill 0自分のプロセスグループにシグナルを送信します。これは終了後に信号を送信しますcommand2command1

メモ:

  • これはBashにkill組み込まれているため、このkill例ではPIDとPGIDが割り当てられた別々のプロセスはありません。したがって、上記の「自己プロセスグループ」という文は厳密ではなく、「サブシェルのプロセスグループ」でなければなりません。これはまだ私たちが使用したい正確なプロセスグループです。組み込みkillでも/bin/kill使用可能でも、どちらか一方が可能です。
  • command2独自のプロセスグループを変更できます。その場合、このソリューションは機能しません。
  • command2その信号を無視したり、ほぼすべての方法で処理することが可能です。あなたのニーズに合った信号を選択してください。
  • kill終了後すぐに電話することは時期尚早かもしれませんcommand1command2生成されたすべてのデータを読み取って処理する前に終了することができます。command1おそらくすべてのデータを処理したいと思います。command2動作によっては、遅延が役立つ場合がありますkill(例sleep 2; kill …:)。 (汎用)Linuxはそうではありません。リアルタイムオペレーティングシステムしたがって、状況が深刻になると、固定遅延が短すぎる可能性があります。

おすすめ記事