Как отправить 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

Один из методов контроля за сбойным конвейером — подсчитать количество процессов конвейера через некоторое время. Если они не завершились, то закройте их и перезапустите.

В этом примере кода мы используем askБашдля идентификатора его процесса ( $$переменной), затем используйтепгрепчтобы найти все подпроцессы скрипта. То есть, pgrepсообщает нам все идентификаторы рабочих процессов. Если таковые имеются, то мы используем соответствующиеpkillкоманду раздавить их перед перезапуском.

Кроме того, мы используемдатакоманда для вывода наглядного файла журнала, показывающего, что и в какое время делает система.

источник: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»

Pipeline обнаруживает, что рабочий процесс застрял, выдает сообщение об ошибке и завершает работу перед перезапуском.

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

Pipeline теперь ожидает завершения рабочего процесса. Здесь мы схитрим и вручную завершим конвейер, убив рабочих.

$ 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

Связанный контент