34
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

シェルでパイプ元のプロセスを殺したい

Last updated at Posted at 2015-05-25

問題

結果から言えばバカバカしいけどシェル関係初心者の自分はかなりハマったのでメモ。

(tcpdump | awk '{print $1}') &
curl -s http://example.com > /dev/null
kill $!

cURLリクエストが終わった時に tcpdump を殺したい!$!で殺せるのは()を司るサブシェルだけだし…さてどうする?

解決策

プロセス単位ではなくジョブ単位で殺す

俺、なんでサブシェル上で動かしてるんだ!? ってことで原点回帰します。

  • %%は同一シェルプロセス内で最後に実行したバックグラウンドジョブを意味する
tcpdump | awk '{print $1}' &
curl -s http://example.com > /dev/null
kill %%

ジョブとプロセスは1対1にしかならないと勝手に思い込んでいたけど、このようにサブシェルに載せる必要もなく2プロセスを1ジョブにまとめることが出来る。また、ジョブに対してのkillは、ジョブに含まれるプロセス全てに対するkillとして実行されるようだ。

…ただ、先頭プロセス以外の死に方が若干変わってしまう点にだけ注意。役目を終えて自然死するのではなく、強制的に殺されてしまっている。

先頭プロセス以外をファイルディスクリプタ化したサブシェルで走らせる

あとから気づいたのでこの方法も追記。ただしshの標準機能ではない。bashとzshでは動作確認。

  • $!は同一シェルプロセス内で最後に実行したバックグラウンドプロセスを意味する
  • >( )にてサブシェルをファイルディスクリプタ化することが出来る
tcpdump > >(awk '{print $1}') &
curl -s http://example.com > /dev/null
kill $!

この方法であれば、$!は先頭のプロセスIDのまま保持される。先頭プロセス以外を自然死させることが出来るのも特徴。

備考

逆方向バージョン<( )もある模様。

cat < <(echo ヌッ!)
while read i; do
    printf "野獣「%s!」\n" $i
done < <(
    for i in ヌッ オオン アオン; do
        echo $i
    done
)
34
35
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?