Réponses:
Pour vérifier l'existence d'un processus, utilisez
kill -0 $pid
Mais comme @unwind l'a dit, si vous voulez le tuer de toute façon,
kill $pid
ou vous aurez une condition de course.
Si vous souhaitez ignorer la sortie de texte de kill
et faire quelque chose en fonction du code de sortie, vous pouvez
if ! kill $pid > /dev/null 2>&1; then
echo "Could not send SIGTERM to process $pid" >&2
fi
kill
est quelque peu mal nommé en ce sens qu'il ne tue pas nécessairement le processus. Il envoie simplement un signal au processus. kill $PID
équivaut à kill -15 $PID
, qui envoie le signal 15, SIGTERM au processus, qui est une instruction pour terminer. Il n'y a pas de signal 0, c'est une valeur spéciale indiquant kill
simplement de vérifier si un signal pourrait être envoyé au processus, ce qui est dans la plupart des cas plus ou moins équivalent à vérifier s'il existe. Voir linux.die.net/man/2/kill et linux.die.net/man/7/signal
kill -0
, en fait, je dois faire ceci: kill -0 25667 ; echo $?
- et ensuite si j'obtiens un 0
retour, alors le processus avec ce PID peut être tué; et si le processus PID (disons) n'existe pas, le $?
sera 1
, indiquant un échec. Est-ce exact?
Le meilleur moyen est:
if ps -p $PID > /dev/null
then
echo "$PID is running"
# Do something knowing the pid exists, i.e. the process with $PID is running
fi
Le problème avec:
kill -0 $PID
est le code de sortie sera différent de zéro même si le pid est en cours d'exécution et que vous n'avez pas l'autorisation de le tuer. Par exemple:
kill -0 1
et
kill -0 $non-running-pid
ont un code de sortie indiscernable (non nul) pour un utilisateur normal, mais le processus d'initialisation (PID 1) est certainement en cours d'exécution.
Les réponses concernant les conditions de mise à mort et de race sont exactement correctes si le corps du test est un "kill". Je suis venu chercher le général " comment testez-vous l'existence d'un PID dans bash ".
La méthode / proc est intéressante, mais dans un certain sens brise l'esprit de l'abstraction de la commande "ps", c'est-à-dire que vous n'avez pas besoin d'aller chercher dans / proc parce que si Linus décide d'appeler le fichier "exe" autre chose?
-p
n'est pas nécessaire, du moins dans ce cas. ps $PID
a exactement le même résultat.
if [ -n "$PID" -a -e /proc/$PID ]; then
echo "process exists"
fi
ou
if [ -n "$(ps -p $PID -o pid=)" ]
Dans cette dernière forme, -o pid=
est un format de sortie pour afficher uniquement la colonne ID de processus sans en-tête. Les guillemets sont nécessaires pour que l'opérateur de chaîne non vide -n
donne un résultat valide.
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
ps
options et les fonctionnalités ont tendance à varier entre les plates-formes, de sorte qu'elles ne sont toujours pas entièrement portables.
$PID
est vide, alors [ -e /proc/$PID ]
retournera toujours true, puisque le /proc/
répertoire existe toujours.
Vous avez deux moyens:
Commençons par rechercher une application spécifique dans mon ordinateur portable:
[root@pinky:~]# ps fax | grep mozilla
3358 ? S 0:00 \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox
16198 pts/2 S+ 0:00 \_ grep mozilla
Tous les exemples recherchent maintenant le PID 3358.
Première manière : exécutez "ps aux" et grep pour le PID dans la deuxième colonne. Dans cet exemple, je recherche Firefox, puis son PID:
[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358
Donc votre code sera:
if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
kill $PID
fi
Deuxième méthode : cherchez simplement quelque chose dans le /proc/$PID
répertoire. J'utilise "exe" dans cet exemple, mais vous pouvez utiliser n'importe quoi d'autre.
[root@pinky:~]# ls -l /proc/3358/exe
lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash
Donc votre code sera:
if [ -f /proc/$PID/exe ]; then
kill $PID
fi
BTW: quel est le problème avec kill -9 $PID || true
?
ÉDITER:
Après y avoir réfléchi pendant quelques mois ... (environ 24 ...) l'idée originale que j'ai donnée ici est un joli hack, mais hautement non portable. Bien qu'il enseigne quelques détails d'implémentation de Linux, il ne fonctionnera pas sur Mac, Solaris ou * BSD. Il pourrait même échouer sur les futurs noyaux Linux. Veuillez utiliser "ps" comme décrit dans les autres réponses.
/proc/$PID/exe
n'est pas un fichier ordinaire. Donc, [ -f /proc/$PID/exe ]
retournera toujours un false
résultat. Essayez [ -h /proc/$PID/exe ]
.
Il semble que tu veux
wait $PID
qui reviendra une fois $pid
terminé.
Sinon, vous pouvez utiliser
ps -p $PID
pour vérifier si le processus est toujours en vie (c'est plus efficace que kill -0 $pid
parce qu'il fonctionnera même si vous ne possédez pas le pid).
pid 123 is not a child of this shell
Je pense que c'est une mauvaise solution, qui ouvre aux conditions de course. Et si le processus meurt entre votre test et votre appel à tuer? Alors tuer échouera. Alors pourquoi ne pas simplement essayer le kill dans tous les cas, et vérifier sa valeur de retour pour savoir comment cela s'est passé?
kill -9
. Cela tue instantanément le processus, ne lui donnant aucune chance de se nettoyer après lui-même. Utilisez plutôt kill
ce qui équivaut à kill -15
. Si cela ne fonctionne pas, vous devriez savoir pourquoi, et uniquement en dernier recours kill -9
.
ici, je stocke le PID dans un fichier appelé .pid (qui est un peu comme / run / ...) et n'exécute le script que s'il n'est pas déjà exécuté.
#!/bin/bash
if [ -f .pid ]; then
read pid < .pid
echo $pid
ps -p $pid > /dev/null
r=$?
if [ $r -eq 0 ]; then
echo "$pid is currently running, not executing $0 twice, exiting now..."
exit 1
fi
fi
echo $$ > .pid
# do things here
rm .pid
note: il y a une condition de concurrence car elle ne vérifie pas comment ce pid est appelé. si le système est redémarré et que .pid existe mais est utilisé par une autre application, cela peut entraîner des «conséquences imprévues».
Par exemple, dans GNU / Linux, vous pouvez utiliser:
Pid=$(pidof `process_name`)
if [ $Pid > 0 ]; then
do something
else
do something
fi
Ou quelque chose comme
Pin=$(ps -A | grep name | awk 'print $4}')
echo $PIN
et cela vous montre le nom de l'application, juste le nom sans ID.
pidof
ne renvoie pas de nombre négatif, car un PID négatif n'a aucun sens, et vous ne pouvez pas tuer init
, donc votre conditionnel n'a aucun sens (et de plus, vous devrez échapper à >
pour l'empêcher d'effectuer une redirection). Vous voulez vérifier un résultat vide, mais bien sûr, comme tout outil décent, pidof
définit un code de sortie pour vous dire si cela a fonctionné, donc la bonne solution est if Pid=$(pidof 'process_name'); then ...
ou (si vous n'aurez pas besoin de la valeur Pid
plus tard) simplementif pidof 'process_name'; then...
pidof
exemple est plein de malentendus sur le fonctionnement de bash test
. gnu.org/software/bash/manual/html_node/…
le code ci-dessous vérifie si mon processus est en cours d'exécution, si c'est le cas, ne faites rien.
vérifions les nouveaux messages d'Amazon SQS toutes les heures uniquement et uniquement si le processus n'est pas en cours d'exécution.
#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
/usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
echo "do nothing, just smile =)"
fi
exit $?