子パイプラインプロセスの親プロセスを終了します。

子パイプラインプロセスの親プロセスを終了します。

私がやりたいことを示す小さなスクリプトがあります。

#!/bin/bash
> z
tail -f z | grep 'd' &
echo $!

$!grepプロセスのPIDを提供します。 grepプロセスと同時にtailプロセスを終了できるようにしたいです。これにより、kill "pid of grep"tailプロセスは終了しません。でもなくkillall grep。使ってもいいけどkillall tail危険だと思います。

答え1

コマンドを括弧で囲みます。

( tail -f z | grep 'd' ) &
kill -- -$!

これにより、サブプロセス全体が終了します。

ここでは、終了する負のPIDを指定してプロセスグループ全体を終了します。バラよりman 1 kill

負のPID値は、プロセスグループ全体を選択するために使用できます。 psコマンド出力のPGID列を参照してください。

またはman 2 kill:

pidが-1未満の場合、IDが-pidのプロセスグループ内のすべてのプロセスにsigが送信されます。

しかし、kill -PIDそれだけで動作しますジョブ制御が有効な場合in bash(対話型シェルのデフォルト値)。そうしないと、子プロセスに専用のプロセスグループがなく、kill コマンドが失敗します。kill: (-PID) - No such process

この問題を解決するには、bash()set -mでジョブ制御を有効にするか、pkill -P $!

答え2

私はこれを試しましたが、私には効果がありません

( tail -f z | grep 'd' ) &
kill -- -$!

名前のないパイプの代わりに名前付きパイプを使用します。

rm -f tailfifo; mkfifo tailfifo
tail -n 0 -f mylog.log >tailfifo &
TAIL_PID=$!
grep --line-buffered someword <tailfifo >outputfile &
GREP_PID=$!
# .. ..
kill $TAIL_PID
kill $GREP_PID

答え3

時限の答え 非対話型sh(ダッシュ)では機能しません。を使用すると、()プロセスグループが作成されないため、sh -c '(sleep 6m | sleep 8m) & kill -- -$!'何の効果もありません。

ps --no-headers --format pgid:1 $! ただし、まだパイプライン全体のpgidを見つけて終了するために使用できます。

sleep 6m | sleep 8m &
pgid=`ps -ho $!`
kill -- -$pgid

さらに、()それをパイプラインで使用すると、シェルはプロセスグループを作成できなくなります。

pgid() {
    ps --no-headers --format pgid:1 $1
}

while true
do nc $ip $port
done | str2str -out tcpsvr://:5566 &
echo `pgid $!` == $$
wait

関連情報