web-dev-qa-db-fra.com

Comment supprimer le message terminé après avoir tué dans bash?

Comment pouvez-vous supprimer le message Terminated qui apparaît après avoir tué un processus dans un script bash?

J'ai essayé set +bm, mais cela ne fonctionne pas.

Je sais qu'une autre solution consiste à appeler exec 2> /dev/null, mais est-ce fiable? Comment puis-je le réinitialiser pour pouvoir continuer à voir stderr?

51
user14437

La réponse courte est que vous ne pouvez pas. Bash imprime toujours l'état des travaux de premier plan. L'indicateur de surveillance s'applique uniquement aux travaux d'arrière-plan et uniquement aux shells interactifs, pas aux scripts.

voir notify_of_job_status () dans jobs.c.

Comme vous le dites, vous pouvez rediriger afin que l'erreur standard pointe vers/dev/null, mais vous ratez tout autre message d'erreur. Vous pouvez le rendre temporaire en effectuant la redirection dans un sous-shell qui exécute le script. Cela laisse seul l'environnement d'origine.

(script 2> /dev/null)

qui perdra tous les messages d'erreur, mais uniquement à partir de ce script, et non à partir d'autres éléments exécutés dans ce shell.

Vous pouvez enregistrer et restaurer l'erreur standard, en redirigeant un nouveau descripteur de fichier pour y pointer:

exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
script             # run script with redirected stderr
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

Mais je ne recommanderais pas cela - le seul avantage du premier est qu'il enregistre une invocation sous-Shell, tout en étant plus compliqué et, peut-être même en modifiant le comportement du script, si le script modifie les descripteurs de fichier.


MODIFIER:

Pour une réponse plus appropriée, vérifiez la réponse donnée par Mark Edgar

16
wnoise

Pour mettre le message sous silence, vous devez rediriger stderr au moment où le message est généré . Étant donné que la commande kill envoie un signal et n'attend pas que le processus cible réponde, la redirection stderr de la commande kill ne vous permet pas bien. La commande bash wait a été spécialement conçue à cet effet.

Voici un exemple très simple qui tue la commande d'arrière-plan la plus récente. ( En savoir plus sur $! Ici. )

kill $!
wait $! 2>/dev/null

Étant donné que kill et wait acceptent plusieurs pids, vous pouvez également effectuer des éliminations groupées. Voici un exemple qui tue tous les processus d'arrière-plan (du processus/script actuel bien sûr).

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null

J'ai été conduit ici depuis bash: tuer silencieusement le processus de fonction d'arrière-plan .

121
Mark Edgar

Inspiré par réponse de MarcH . J'utilisais kill -INT comme il le suggère avec un certain succès, mais j'ai remarqué que cela ne tuait pas certains processus. Après avoir testé d'autres signaux, je vois que SIGPIPE tuera également sans message.

kill -PIPE

ou simplement

kill -13
16
Steven Penny

Solution: utilisez SIGINT (ne fonctionne que dans les shells non interactifs)

Démo:

cat > silent.sh <<"EOF"
sleep 100 &
kill -INT $!
sleep 1
EOF

sh silent.sh

http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798

8
MarcH

Peut-être détacher le processus du processus Shell actuel en appelant disown?

4
Matthias Kestenholz

Est-ce ce que nous recherchons tous?

Non désiré:

$ sleep 3 &
[1] 234
<pressing enter a few times....>
$
$
[1]+  Done                    sleep 3
$

Voulait:

$ (set +m; sleep 3 &)
<again, pressing enter several times....>
$
$
$
$
$

Comme vous pouvez le voir, aucun message de fin de travail. Fonctionne également pour moi dans les scripts bash, également pour les processus d'arrière-plan supprimés.

'set + m' désactive le contrôle des travaux (voir 'help set') pour le shell actuel. Donc, si vous entrez votre commande dans un sous-shell (comme cela est fait ici entre parenthèses), vous n'influencerez pas les paramètres de contrôle des travaux du shell actuel. Le seul inconvénient est que vous devez récupérer le pid de votre processus d'arrière-plan dans le shell actuel si vous voulez vérifier s'il s'est terminé ou évaluer le code retour.

1
Ralph

Cela fonctionne également pour killall (pour ceux qui le préfèrent):

killall -s SIGINT (yourprogram) 

supprime le message ... J'exécutais mpg123 en arrière-plan. Il ne pouvait être tué qu'en silence en envoyant un ctrl-c (SIGINT) au lieu d'un SIGTERM (par défaut).

1

Une autre façon de désactiver les notifications de tâche consiste à placer votre commande en arrière-plan dans un sh -c 'cmd &' construire.

#!/bin/bash
# ...
pid="`sh -c 'sleep 30 & echo ${!}' | head -1`"
kill "$pid"
# ...

# or put several cmds in sh -c '...' construct
sh -c '
sleep 30 &
pid="${!}"
sleep 5 
kill "${pid}"
'
1
phily

Facile:

{ kill $! } 2>/dev/null

Avantage? peut utiliser n'importe quel signal

ex:

{ kill -9 $PID } 2>/dev/null
0
user2429558

disown a fait exactement la bonne chose pour moi - l'exec 3> & 2 est risqué pour beaucoup de raisons - set + bm ne semble pas fonctionner dans un script, seulement à l'invite de commande

0
clemep

J'ai trouvé que le fait de placer la commande kill dans une fonction, puis de mettre en arrière-plan la fonction, supprime la sortie de terminaison

function killCmd() {
    kill $1
}

killCmd $somePID &
0
Al Joslin

A réussi à ajouter "jobs 2>&1 >/dev/null 'au script, je ne sais pas si cela aidera le script de quelqu'un d'autre, mais voici un exemple.

    while true; do echo $RANDOM; done | while read line
    do
    echo Random is $line the last jobid is $(jobs -lp)
    jobs 2>&1 >/dev/null
    sleep 3
    done
0
J-o-h-n-