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だけで実行できますか、またはcgroupを使用する必要がありますか?
答え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
timeout
次の内容を使用できます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