やりたいことを説明する小さなスクリプトがあります
#!/bin/bash
> z
tail -f z | grep 'd' &
echo $!
$!
は、grepプロセスのPIDを提供します。 grepプロセスを強制終了すると同時に、tailプロセスを強制終了できるようにしたいと考えています。やっているkill "pid of grep"
doesはテールプロセスを強制終了しません。また、killall grep
。 killall tail
しかし、これは危険だと思います。
コマンドを括弧で囲みます。
_( tail -f z | grep 'd' ) &
kill -- -$!
_
これにより、サブプロセス全体が強制終了されます。
ここでは、killする負のPIDを指定することにより、プロセスグループ全体をkillします。 _man 1 kill
_を参照してください。
負のPID値を使用して、プロセスグループ全体を選択できます。 psコマンド出力のPGID列を参照してください。
または_man 2 kill
_:
Pidが-1未満の場合、sigは、IDが-pidであるプロセスグループ内のすべてのプロセスに送信されます。
ただし、_kill -PID
_が機能するのは ジョブ制御が有効になっている場合のみbash
の場合(対話型シェルのデフォルト)。そうでない場合、サブプロセスには専用のプロセスグループがなく、killコマンドはkill: (-PID) - No such process
で失敗します
これを回避するには、bash
(_set -m
_)でジョブ制御をアクティブにするか、_pkill -P $!
_を使用します
xhienne's answer 非インタラクティブ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
_
私はこれを試してみましたが、うまくいきませんでした
( 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