如何向整個管道發送 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 中完成還是需要使用 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

控制錯誤管道的一種技術是在一段時間後計算管道進程的數量。如果它們還沒有完成,則將其關閉並重新啟動。

在這個範例程式碼中我們使用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

管道腳本等待幾秒鐘,但工作流程過程仍在運行,因為它們以“sleep 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

相關內容