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?
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
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 .
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
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
Peut-être détacher le processus du processus Shell actuel en appelant disown
?
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.
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).
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}"
'
Facile:
{ kill $! } 2>/dev/null
Avantage? peut utiliser n'importe quel signal
ex:
{ kill -9 $PID } 2>/dev/null
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
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 &
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