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
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.
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"
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
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.
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