Wie sende ich SIGKILLs an die gesamte Pipeline?

Wie sende ich SIGKILLs an die gesamte Pipeline?
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

Wie kann man zuverlässig die Programme prog1, prog2 und prog3 loswerden, die hängen bleiben und die für einen erneuten Versuch erforderlichen Ressourcen beanspruchen können?

Kann dies nur in Bash durchgeführt werden oder muss ich cgroups verwenden?

Antwort1

Dies kann mit Prozessgruppen erfolgen (empfohlenHier) und setsidum ein Neues zu beginnen:

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

Antwort2

Sie können timeoutinclude in verwenden GNU's coreutils:

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

Beispiel:

timeout 5 bash -c "pwd | sleep 10"

timeUm sicherzustellen, dass es funktioniert, verwenden Sie :

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

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

Antwort3

Eine Methode zur Kontrolle einer fehlerhaften Pipeline besteht darin, nach einer Weile die Anzahl der Pipeline-Prozesse zu zählen. Wenn sie noch nicht fertig sind, löschen Sie sie und starten Sie sie neu.

In diesem Beispielcode verwenden wir askSchlagfür die Prozess-ID (die $$Variable) und verwenden Sie dannpgrepum alle Unterprozesse des Skripts zu finden. Das heißt, pgrepes gibt uns alle Workflow-Prozess-IDs. Wenn es welche gibt, verwenden wir die entsprechendenpkillBefehl, um sie vor einem Neustart zu beseitigen.

Darüber hinaus nutzen wir dieDatumBefehl zum Ausgeben einer hübschen Protokolldatei, die zeigt, was das System zu welchem ​​Zeitpunkt tut.

Quelle: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

Testlauf:

Starten des Workflow-Steuerungsskripts

$ ./pipeline.sh &

[1] 21291

02:06:39 PM workflow starting

02:06:39 PM waiting for workflow to complete

Die Pipeline-Skripte warten einige Sekunden, aber die Workflow-Prozesse laufen noch, da sie mit „sleep 30“ beginnen.

Die Pipeline erkennt, dass der Workflow blockiert ist, beschwert sich darüber und beendet ihn vor einem Neustart.

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

Die Pipeline wartet nun auf den Abschluss des Workflows. Hier schummeln wir und vervollständigen die Pipeline manuell, indem wir die Worker beenden.

$ 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

Das Pipeline-Skript erkennt nun, dass alle Worker fertig sind, also ist die Pipeline fertig. Es erstellt eine abschließende Protokollmeldung und wird dann beendet.

02:07:16 PM workflow done!

[1]+ Done ./pipeline.sh

verwandte Informationen