Je veux écrire dans un script bash un morceau de code qui vérifie si un programme est déjà en cours d'exécution. J'ai les informations suivantes pour rechercher si la barre est en cours d'exécution
foo=`ps -ef | grep bar | grep -v grep`
Le
grep -v grep
une partie est de s'assurer que la "barre grep" n'est pas prise en compte dans les résultats ps
Lorsque la barre ne fonctionne pas, foo est correctement vide. Mais mon problème réside dans le fait que le script a
set -e
qui est un indicateur pour terminer le script si une commande renvoie une erreur. Il s'avère que lorsque la barre n'est pas en cours d'exécution, "grep -v grep" ne correspond à rien et grep renvoie une erreur. J'ai essayé d'utiliser -q ou -s mais en vain.
Y a-t-il une solution à cela? THX
Sûr:
ps -ef | grep bar | { grep -v grep || true; }
Ou même:
ps -ef | grep bar | grep -v grep | cat
Une bonne astuce pour éviter grep -v grep
est-ce:
ps -ef | grep '[b]ar'
Cette expression régulière ne correspond qu'à la chaîne "bar". Cependant, dans la sortie ps
, la chaîne "bar" n'apparaît pas avec le processus grep.
Dans les jours qui m'ont précédé sur pgrep
, j'ai écrit cette fonction pour automatiser la commande ci-dessus:
psg () {
local -a patterns=()
(( $# == 0 )) && set -- $USER
for arg do
patterns+=("-e" "[${arg:0:1}]${arg:1}")
done
ps -ef | grep "${patterns[@]}"
}
Alors,
psg foo bar
se transforme en
ps -ef | grep -e '[f]oo' -e '[b]ar'
Pourquoi demander à ps
de fournir des quantités massives de sortie avec -ef
si vous n'en jetez que 99%? ps
et surtout la version GNU est un couteau suisse de fonctionnalité pratique. Essayez ceci:
ps -C bar -o pid= 1>/dev/null
Je précise -o pid=
ici juste parce que, mais en fait c'est inutile puisque nous jetons toute la sortie de toute façon. Il serait cependant utile de connaître le PID en cours d'exécution.
ps
retournera automatiquement avec un état d'existence différent de zéro si -C
ne correspond à rien et avec zéro s'il correspond. Vous pouvez donc simplement dire ceci
ps -C bar 1>/dev/null && echo bar running || echo bar not running
Ou
if ps -C bar 1>/dev/null ; then
echo bar running
else
echo bar not running
fi
N'est-ce pas plus simple? Pas besoin de grep, pas deux ou même une fois.
Écrire
ps -ef | grep bar | { grep -v grep || test $? = 1; }
si vous utilisez set -e
.
Si vous utilisez l'option bash pipefail
(set -o pipefail
), N'oubliez pas d'appliquer la gestion des exceptions (||test
) à chaque grep
du pipeline:
ps -ef | { grep bar || test $? = 1; } | { grep -v grep || test $? = 1; }
Dans Scripts Shell je vous suggère d'utiliser la fonction utilitaire ”catch-1-grep“ (c1grep):
c1grep() { grep "$@" || test $? = 1; }
grep
Le statut de sortie de _ est 0, 1 ou 2: [1]
0
Signifie qu'une ligne est sélectionnée1
Signifie qu'aucune ligne n'a été sélectionnée2
Signifie qu'une erreur s'est produitegrep
peut également renvoyer d'autres codes s'il est interrompu par un signal (par exemple 130
pour SIGINT).
Puisque nous voulons uniquement ignorer le statut de sortie 1
, Nous utilisons test
pour supprimer ce statut de sortie spécifique.
grep
renvoie 0
, test
n'est pas exécuté.grep
renvoie 1
, test
est exécuté et renvoie 0
.grep
renvoie toute autre valeur, test
est exécutée et renvoie 1
.Dans le dernier cas, le script se fermera immédiatement en raison de set -e
Ou set -o pipefail
. Cependant, si vous ne vous souciez pas du tout des erreurs grep
, vous pouvez bien sûr écrire
ps -ef | grep bar | { grep -v grep || true; }
comme suggéré par Sean .
Dans les scripts Shell, si vous utilisez beaucoup grep
, je vous suggère de définir une fonction utilitaire:
# "catch exit status 1" grep wrapper
c1grep() { grep "$@" || test $? = 1; }
De cette façon, votre pipe redeviendra courte et simple, sans perdre les fonctionnalités de set -e
Et set -o pipefail
:
ps -ef | c1grep bar | c1grep -v grep
Pour info:
c1grep
Pour souligner qu'il attrape simplement le statut de sortie 1
, Rien d'autre.grep
à la place (grep() { env grep "$@" ...; }
), mais je préfère un nom moins confus et plus explicite, c1grep
.[1] grep
page de manuel
foo=`ps -ef | grep bar | grep -v grep` || true
Essayez de le faire:
ps auxw | grep -v grep | chat
cat renvoie toujours 0 et ignore le code de sortie de grep