74 votes

bash: tue silencieusement le processus de fonction d'arrière-plan

gourous de coquille,

J'ai un script shell bash, dans lequel je lance une fonction d'arrière-plan, disons foo (), pour afficher une barre de progression pour une commande longue et ennuyeuse:

 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
 

maintenant, quand foo meurt, je vois le texte suivant:

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

Cela détruit totalement l'impressionnant affichage de ma barre de progression, autrement très cool. Comment puis-je me débarrasser de ce message?

tia, prmatta

81voto

Mark Edgar Points 1335
 kill $foo_pid
wait $foo_pid 2>/dev/null
 

BTW, je ne connais pas votre barre de progression extrêmement cool, mais avez-vous vu Pipe Viewer (pv)? http://www.ivarch.com/programs/pv.shtml

36voto

pix Points 1343

Je viens de le découvrir moi-même et je me suis rendu compte que le "reniement" est ce que nous recherchons.

 foo &
foo_pid=$!
disown

boring_and_long_command
kill $foo_pid
sleep 10
 

Le message de mort est en cours d'impression car le processus figure toujours dans la liste des "jobs" surveillés. La commande disown supprimera le processus généré le plus récemment de cette liste afin qu'aucun message de débogage ne soit généré lors de sa suppression, même avec SIGKILL (-9).

6voto

skwllsp Points 9661

Essayez de remplacer votre ligne kill $foo_pid >/dev/null 2>&1 par la ligne:

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

5voto

bbbco Points 886

C'est une solution que j'ai trouvée pour un problème similaire (je voulais afficher un horodatage pendant les processus de longue durée). Cela implémente une fonction killsub qui vous permet de tuer tranquillement n'importe quel sous-shell tant que vous connaissez le pid. Notez que les instructions d'interruption sont importantes à inclure: dans le cas où le script est interrompu, le sous-shell ne continuera pas à s'exécuter.

 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
 

5voto

prmatta Points 1189

Ce "hack" semble fonctionner:

 # 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
 

et il a été inspiré d' ici . L'ordre mondial a été rétabli.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X