パイプライン全体に SIGKILL を送信するにはどうすればよいでしょうか?

パイプライン全体に SIGKILL を送信するにはどうすればよいでしょうか?
while true; do 
    # process substitution instead of usual pipeline to avoid waiting for all programs
    handle_input_with_timeout < <( prog1 | prog2 | prog3 )
    echo "Data stopped flowing. Trying again"
    # perminate stuck programs in previous pipeline, then try again
    sleep 5
done

スタックして再試行に必要なリソースを保持する可能性のある prog1、prog2、prog3 を確実に削除するにはどうすればよいでしょうか?

これは Bash だけで実行できますか、それとも cgroups を使用する必要がありますか?

答え1

これはプロセスグループで実行できます(推奨)ここ) をクリックしてsetsid新しいものを開始します:

while true; do 

    handle_input_with_timeout < <( setsid bash -c '
          printf -- "-$$" > /tmp/saved_process_group.pid
          prog1 | prog2 | prog3
          ')
    echo "Data stopped flowing. Trying again"
    kill -9 $(< /tmp/saved_process_group.pid )

    sleep 5
done

答え2

timeoutinclude は次の場所で使用できますGNU's coreutils:

timeout <time in second> bash -c "prog1 | prog2 | prog3"

例:

timeout 5 bash -c "pwd | sleep 10"

time動作を確認するには以下を使用します:

$ time timeout 5 bash -c "pwd | sleep 10"

real    0m5.003s
user    0m0.000s
sys     0m0.000s

答え3

誤ったパイプラインを制御する 1 つの方法は、しばらくしてからパイプライン プロセスの数をカウントすることです。プロセスが終了していない場合は、それらを削除して再起動します。

このサンプルコードではaskを使用しますバッシュプロセスID($$変数)の場合は、グレップスクリプトのすべてのサブプロセスを検索します。つまり、pgrepすべてのワークフロープロセスIDがわかります。存在する場合は、対応するキル再起動する前にそれらを潰すコマンド。

さらに、私たちは日付システムがいつ何をしているかを示すわかりやすいログ ファイルを出力するコマンドです。

ソース:https://github.com/shavenwarthog/johntellsall/tree/master/karma/kill-pipeline


#!/bin/bash

# pipeline.sh -- start workflow; restart if jammed

while true; do

    date '+%X workflow starting'
    (sleep 30; echo gin) &
    (sleep 30; echo tonic) &

    date '+%X waiting for workflow to complete'
    sleep 5

    # count number of child procs (ie: workflow procs)
    # If there are any, kill them then restart.
    if pgrep -cP $$ > /dev/null ; then 
        date '+%X workflow jammed -- restarting; trying again'
        pkill -P $$
        sleep 2
        continue
    fi

    date '+%X workflow done!'
    break

done

テスト走行:

ワークフロー制御スクリプトを開始する

$ ./pipeline.sh &

[1] 21291

02:06:39 PM workflow starting

02:06:39 PM waiting for workflow to complete

パイプライン スクリプトは数秒間待機しますが、ワークフロー プロセスは「スリープ 30」で開始されるため、まだ実行中です。

パイプラインはワークフローが詰まっていることを検出し、再起動する前にエラーを報告してワークフローを強制終了します。

02:06:44 PM workflow jammed -- restarting; trying again

./pipeline.sh: line 27: 21293 Terminated ( sleep 30; echo gin )

./pipeline.sh: line 27: 21294 Terminated ( sleep 30; echo tonic )

02:06:46 PM workflow starting

02:06:46 PM waiting for workflow to complete

パイプラインは現在、ワークフローが完了するのを待機しています。ここでは、ワーカーを強制終了してパイプラインを手動で完了させます。

$ pkill -f sleep

./pipeline.sh: line 27: 21363 Terminated sleep 30

./pipeline.sh: line 27: 21365 Terminated sleep 5

./pipeline.sh: line 27: 21364 Terminated sleep 30

tonic

パイプライン スクリプトは、すべてのワーカーが完了したことを認識し、パイプラインが完了します。終了ログ メッセージを作成して終了します。

02:07:16 PM workflow done!

[1]+ Done ./pipeline.sh

関連情報