Pourquoi "if $(ps aux / grep...)" réussit toujours dans Bash?

Pourquoi l'instruction if suivante réussit ?

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi
23
demandé sur Misha Moroshko 2012-01-23 03:01:27

5 réponses

Parce que le processus grep lui-même est renvoyé par ps. Vous pouvez "tromper" grep pour ne pas correspondre à lui - même en entourant l'un des caractères de recherche dans une classe de caractères [ ] qui ne change pas la fonctionnalité: Il suffit de faire:

if ps aux | grep -q "[b]la bla" ; then echo "found" ; fi

En outre, l'utilisation de la substitution de processus $() est inutile. Le if travaillera sur le succès de la dernière commande dans la chaîne de tuyaux, ce qui est ce que vous voulez.

Note : la raison pour laquelle l'astuce de la classe de caractères fonctionne est ps la sortie a toujours les crochets de classe de caractères, mais lorsque grep traite la chaîne de recherche, elle utilise les crochets comme syntaxe plutôt qu'une chaîne fixe pour correspondre.

32
répondu SiegeX 2012-01-22 23:31:18

Si vous grep la sortie de ps aux, vous obtiendrez toujours un processus en montrant votre commande précédente. Pour résoudre ce problème, vous pouvez diriger la sortie vers grep deux fois, une fois pour supprimer la ligne avec "grep", et encore pour le processus que vous recherchez.

ps aux | grep -v "grep" | grep "Finder"
8
répondu Sonic84 2012-08-08 15:28:09

Le processus 'grep' est déjà en cours d'exécution au moment où ps s'exécute, donc la sortie ps l'inclut.

Essayez d'utiliser pgrep à la place.

Pgrep est précisément à cet effet:

if pgrep "bla bla" ; then echo "found" ; fi

7
répondu laher 2012-01-23 03:42:48

Le {[3] } est un petit peu pertinent, et change un peu le sens. Bien que dans ce cas, parce qu'il n'y a jamais de sortie de grep -q, Vous pouvez à peu près vous en sortir avec le $(. Vous pouvez commencer avec quelque chose comme (comme souligné par d'autres):

if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi

De toute façon, vous avez commencé avec

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi

Avec $(, la commande à l'intérieur du $( ) est exécutée et la sortie de cette commande est utilisée comme ligne de commande pour la commande externe. Ces quatre expériences:

# if $(echo nonexistant ; true) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo nonexistant ; false) ; then echo "found" ; fi
nonexistant: command not found

# if $(echo  ; true) ; then echo "found" ; fi
found

# if $(echo  ; false) ; then echo "found" ; fi

Donc, selon cela, vous sortirez get found si ces deux conditions tiennent:

  • la commande à l'intérieur du $( ) n'a créé aucune sortie
  • et la commande a été réussie

Cela suggère que ps aux | grep -q "bla bla" a réussi et n'a créé aucune sortie. Il n'est pas surprenant que grep -q ne crée aucune sortie. C'est à ça que sert le -q. Donc, votre commande doit avoir eu un vrai statut, ce qui implique que le grep a réussi trouver une correspondance. Nous savons que grep trouvera toujours une correspondance dans ce cas, car la liste des processus de ps inclura grep lui-même; le grep se trouvera toujours.

2
répondu Aaron McDaid 2012-01-22 23:30:00

Vous devez filtrer le processus qui est grep ping pour 'bla bla':

$ if ps aux | grep -v 'grep' | grep -q 'bla bla'; then
    echo 'Found'
fi
1
répondu Johnsyweb 2012-01-22 23:10:03