私がやりたいことを示す小さなスクリプトがあります。
#!/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