linux - terminator rename tab




bash: Hintergrundfunktionsprozess stillschweigend beenden (6)

Dies ist eine Lösung, die ich für ein ähnliches Problem entwickelt habe (wollte einen Zeitstempel während lang andauernder Prozesse anzeigen). Dies implementiert eine Killsub-Funktion, mit der Sie jede Untershell ruhig beenden können, solange Sie die PID kennen. Beachten Sie, dass die Trap-Anweisungen wichtig sind: Wenn das Skript unterbrochen wird, wird die Subshell nicht weiter ausgeführt.

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

#Kills the sub process quietly
function killsub() 
{

    kill -9 ${1} 2>/dev/null
    wait ${1} 2>/dev/null

}

foo &
foo_pid=$!

#Add a trap incase of unexpected interruptions
trap 'killsub ${foo_pid}; exit' INT TERM EXIT

boring_and_long_command

#Kill foo after finished
killsub ${foo_pid}

#Reset trap
trap - INT TERM EXIT

Muschelgurus,

Ich habe ein Bash-Shell-Skript, in dem ich eine Hintergrundfunktion starte, sagen wir foo() , um einen Fortschrittsbalken für einen langweiligen und langen Befehl anzuzeigen:

foo()
{
    while [ 1 ]
    do
        #massively cool progress bar display code
        sleep 1
    done
}

foo &
foo_pid=$!

boring_and_long_command
kill $foo_pid >/dev/null 2>&1
sleep 10

Jetzt, wenn foo stirbt, sehe ich den folgenden Text:

/home/user/script: line XXX: 30290 Killed                  foo

Dadurch wird die Großartigkeit meines ansonsten coolen Fortschrittsbalkens komplett zerstört.

Wie werde ich diese Nachricht los?


Dieser "Hack" scheint zu funktionieren:

# Some trickery to hide killed message
exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
kill $foo_pid >/dev/null 2>&1
sleep 1            # sleep to wait for process to die
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

und es wurde von here inspiriert. Die Weltordnung wurde wiederhergestellt.


Eine weitere Möglichkeit, Jobbenachrichtigungen zu deaktivieren, besteht darin, den Befehl in ein sh -c 'cmd &' Konstrukt zu setzen.

#!/bin/bash

foo()
{
   while [ 1 ]
   do
       sleep 1
   done
}

#foo &
#foo_pid=$!

export -f foo
foo_pid=`sh -c 'foo & echo ${!}' | head -1`

# if shell does not support exporting functions (export -f foo)
#arg1='foo() { while [ 1 ]; do sleep 1; done; }'
#foo_pid=`sh -c 'eval "$1"; foo & echo ${!}' _ "$arg1" | head -1`


sleep 3
echo kill ${foo_pid}
kill ${foo_pid}
sleep 3
exit

Fügen Sie am Anfang der Funktion hinzu:

trap 'exit 0' TERM

In Bezug auf "warten": das ist die beste Antwort, denke ich. Ein Beispiel dafür, wie das aussieht / funktioniert, finden Sie unter https://.com/a/10200191/1208218 .


Versuchen Sie, Ihre Zeile kill $foo_pid >/dev/null 2>&1 durch die Zeile zu ersetzen:

(kill $foo_pid 2>&1) >/dev/null

Aktualisierung :

Diese Antwort ist nicht korrekt für den von @ mklement0 in seinem Kommentar erklärten Grund:

Der Grund, warum diese Antwort bei Hintergrundjobs nicht wirksam ist, ist, dass Bash selbst asynchron nach dem Beenden des Befehls kill eine Statusmeldung über den getöteten Job ausgibt, die Sie nicht direkt unterdrücken können - es sei denn, Sie verwenden wait, wie in der angenommenen Antwort.





scripting