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?

Était-ce utile?

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top