2009-04-03 6 views
2

Supposons que j'ai un script bash (foo.sh) que sous une forme très simplifiée, se présente comme suit:Suppress Avis de zigzags commandement d'être tué

echo "hello" 
sleep 100 & 
ps ax | grep sleep | grep -v grep | awk '{ print $1 } ' | xargs kill -9 
echo "bye" 

La troisième ligne imite pkill, que je ne suis pas avoir par défaut sur Mac OS X, mais vous pouvez penser à la même chose que pkill. Cependant, quand je lance ce script, je reçois la sortie suivante:

hello 
foo: line 4: 54851 Killed     sleep 100 
bye 

Comment puis-je supprimer la ligne au milieu de sorte que tout ce que je vois est hello et bye?

+0

On suppose que vous connaissez déjà le $! paramètre? – ashawley

+0

Non, je ne le fais pas, et Google n'est pas utile avec ça. Qu'est-ce que cela donne? –

Répondre

3

Que diriez-vous de renoncer? Cela fonctionne principalement pour moi sur Bash sur Linux.

echo "hello" 
sleep 100 & 
disown 
ps ax | grep sleep | grep -v grep | awk '{ print $1 } ' | xargs kill -9 
echo "bye" 

Edit: Assorti code de l'affiche mieux.

+0

Bien sûr, si vous faites cela, vous perdez le contrôle du travail, donc vous ne pouvez pas tuer% 1 ou quoi que ce soit plus tard. Je ne suis pas sûr si vous pouvez vous en sortir, mais dans la plupart des cas vous le pouvez probablement. Ces jours-ci, si vous êtes dans le contrôle du travail de fantaisie, vous serez en Perl ou autre chose. – JasonSmith

+0

Super, ça a l'air de le faire! Je vais regarder dans les implications de perdre le contrôle du travail avec mon application, mais ça devrait aller. Merci! –

1

Le message est réel. Le code a également tué le processus grep. Exécutez ps ax | grep sleep et vous devriez voir votre processus grep dans la liste.

Ce que je fais habituellement dans ce cas est ps ax | grep sleep | grep -v grep

EDIT: Ceci est une réponse à la forme de la question plus où l'auteur a omis l'exclusion de grep pour la séquence kill. J'espère avoir encore un représentant pour répondre à la première moitié.

+0

Oui, je suis au courant de cela, et ça me va. Mais ce que je cherche est un moyen de supprimer les messages sur les deuxième et troisième lignes. Merci quand même! –

+0

Oui, j'avais fait le changement pour inclure votre suggestion d'omettre grep de la liste des choses à tuer, mais ce n'était pas le point de la question. Je cherchais juste un moyen de supprimer la sortie, ne pas omettre "grep sleep" de la liste. –

-1

Avez-vous essayé de désactiver le contrôle du travail? C'est un shell non-interactif, donc je suppose que c'est désactivé par défaut, mais ça ne fait pas de mal d'essayer ... Il est régulé par la variable shell -m (monitor).

14

Alors que disown peut avoir l'effet secondaire de faire taire le message; C'est ainsi que vous démarrez le processus de manière à ce que le message soit réellement réduit au silence sans avoir à abandonner le contrôle du processus.

{ command & } 2>/dev/null 

Si vous voulez toujours propre stderr de la commande (réduire au silence tout le message du shell sur stderr), vous devez envoyer le processus stderr au réel stderr:

{ command 2>&3 & } 3>&2 2>/dev/null 

Pour en savoir plus sur la façon dont redirection fonctionne:

Et en passant; don't use kill -9.

Je me sens aussi obligé de commenter votre:

ps ax | grep sleep | grep -v grep | awk '{ print $1 } ' | xargs kill -9 

Cela scortch les yeux de tout utilisateur UNIX/Linux avec un indice.De plus, chaque fois que vous parez ps, une fée meurt. Pour ce faire:

kill $! 

Même les outils tels que pgrep sont essentiellement brisés par la conception. Alors qu'ils font un meilleur travail de processus correspondant, les défauts fondamentaux sont toujours là:

  • Race: Au moment où vous obtenez une sortie PID et l'analyser en arrière et l'utiliser pour autre chose, le PID peut-être déjà disparu ou même remplacé par un processus complètement indépendant.
  • Responsabilité: Dans le modèle de processus UNIX, il incombe à un parent de gérer son enfant, personne d'autre ne devrait le faire. Un parent devrait conserver le PID de son enfant s'il veut être capable de le signaler et seul le parent peut le faire de façon fiable. Les noyaux UNIX ont été conçus en supposant que les programmes utilisateurs adhéreront à ce modèle, sans le violer.
+0

Super, merci pour les liens! Je les vérifie maintenant, mais votre premier extrait de code ne produit pas la sortie prévue (du moins pas sur OSX). Le second fonctionne comme prévu cependant. –

+0

@lhunath - Je pensais que 'pgrep' /' pkill' * étaient les remplacements habiles pour analyser 'ps'. Pourriez-vous élaborer davantage sur ce qui est "brisé" à leur sujet? J'apprécie les distinctions entre différentes approches et serais intéressé par des détails sur celui-ci. – RubyTuesdayDONO

+0

@RubyTuesdayDONO ajouté à la réponse. – lhunath

0

Encore une autre façon de désactiver les messages de fin de contrat de travail est de mettre votre commande à backgrounded dans une sh -c 'cmd &' construction. Et comme déjà indiqué, il n'y a pas besoin d'imiter pkill; vous pouvez stocker la valeur de $! dans une autre variable à la place.

echo "hello" 
sleep_pid=`sh -c 'sleep 30 & echo ${!}' | head -1` 
#sleep_pid=`sh -c '(exec 1>&-; exec sleep 30) & echo ${!}'` 
echo kill $sleep_pid 
kill $sleep_pid 
echo "bye" 
+0

cela ne fonctionne pas au moins pour le bas 4.1.5 (1) et le tiret 0.5.5.1: la coque externe attend que le sommeil se termine –

Questions connexes