Comment supprimer le message Terminated après avoir tué en Bash?
Question
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 connais une autre solution qui consiste à appeler exec 2 > / dev / null
, mais est-ce que
fiable? Comment le réinitialiser pour pouvoir continuer à voir stderr?
La solution
La réponse courte est que vous ne pouvez pas. Bash imprime toujours le statut des tâches de premier plan. L'indicateur de surveillance s'applique uniquement aux tâches en arrière-plan, et uniquement aux interpréteurs de commandes interactifs, pas aux scripts.
voir notify_of_job_status () dans jobs.c.
Comme vous le dites, vous pouvez rediriger si une erreur standard pointe vers / dev / null, mais vous ratez tous les autres messages d'erreur. Vous pouvez le rendre temporaire en effectuant la redirection dans un sous-shell qui exécute le script. Cela laisse l'environnement d'origine seul.
(script 2> /dev/null)
qui perdra tous les messages d'erreur, mais uniquement à partir de ce script, pas à partir de quoi que ce soit d'autre exécuté dans ce shell.
Vous pouvez enregistrer et restaurer l'erreur standard en redirigeant un nouveau descripteur de fichiers vers celui-ci:
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 ceci. Le seul avantage du premier est qu'il enregistre une invocation de sous-shell, tout en étant plus compliqué et, éventuellement, en modifiant le comportement du script, si le script modifie les descripteurs de fichier. .
EDIT:
Pour une réponse plus appropriée, vérifiez la réponse donnée par Mark Edgar
Autres conseils
Pour rendre le message silencieux, vous devez rediriger stderr
au moment de la génération du message . Parce que la commande kill
envoie un signal et n'attend pas le processus cible pour répondre, la redirection de stderr
de la commande kill
ne sert à rien. La wait
intégrée à Bash a été créée spécifiquement à cet effet.
Voici un exemple très simple qui élimine 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 procéder à la suppression par lots. Voici un exemple qui supprime tous les processus d’arrière-plan (bien sûr du processus / script en cours).
kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null
J'ai été dirigé ici depuis bash: élimine silencieusement le processus de la fonction d'arrière-plan .
Inspiré par la 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 supprimait pas certains processus. Après avoir testé d'autres signaux, je constate que SIGPIPE
va également tuer sans message.
kill -PIPE
ou simplement
kill -13
Solution: utilisez SIGINT (fonctionne uniquement 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
Peut-être séparer le processus du processus shell en appelant disown
?
Est-ce ce que nous recherchons tous?
Non recherché:
$ sleep 3 &
[1] 234
<pressing enter a few times....>
$
$
[1]+ Done sleep 3
$
Recherché:
$ (set +m; sleep 3 &)
<again, pressing enter several times....>
$
$
$
$
$
Comme vous pouvez le constater, aucun message ne met fin au travail. Fonctionne aussi dans les scripts bash, y compris pour les processus en arrière-plan arrêtés.
'set + m' désactive le contrôle du travail (voir 'help set') pour le shell actuel. Ainsi, si vous entrez votre commande dans un sous-shell (comme indiqué ici entre parenthèses), vous n'influencerez pas les paramètres de contrôle des tâches du shell actuel. Le seul inconvénient est que vous devez obtenir le pid de votre processus d'arrière-plan dans le shell actuel si vous souhaitez vérifier s'il est terminé ou évaluer le code de retour.
Un autre moyen de désactiver les notifications de travail consiste à placer votre commande en arrière-plan dans une construction sh -c 'cmd &';
.
#!/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}"
'
Ceci fonctionne aussi 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 peut être tué qu'en envoyant un ctrl-c (SIGINT) au lieu d’un SIGTERM (valeur par défaut).
disown a fait exactement ce qu'il fallait pour moi - l'exec 3 & 2 & # 160; s est risqué pour de nombreuses raisons - set + bm ne semblait pas fonctionner dans un script, mais uniquement à l'invite de commande
Vous avez réussi à ajouter au script les balises < jobs 2 > & amp; 1 > / dev / null
]. p>
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
J'ai constaté que le fait de placer la commande kill dans une fonction puis de la mettre en arrière-plan supprime la sortie de terminaison
function killCmd() {
kill $1
}
killCmd $somePID &
Simple:
{ kill $! } 2>/dev/null
Avantage? peut utiliser n'importe quel signal
ex:
{ kill -9 $PID } 2>/dev/null