427 votes

Comment obtenir l'ID d'un processus en arrière-plan ?

Je lance un processus en arrière-plan à partir de mon shell script, et j'aimerais tuer ce processus lorsque mon script se termine.

Comment obtenir le PID de ce processus à partir de mon shell script ? Pour autant que je puisse voir la variable $! contient le PID du script en cours, et non du processus d'arrière-plan.

9 votes

$ ! est correct. Êtes-vous sûr de lancer le script dans l'exemple BG ? s'il vous plaît.

7 votes

Oui, $ ! est exact. Je me suis trompé.

12 votes

$$ contient le PID actuel du script.

672voto

camh Points 13169

Vous devez enregistrer le PID du processus d'arrière-plan au moment où vous le démarrez :

foo &
FOO_PID=$!
# do other stuff
kill $FOO_PID

Vous ne pouvez pas utiliser le contrôle des tâches, puisqu'il s'agit d'une fonction interactive liée à un terminal de contrôle. Un script n'aura pas nécessairement de terminal attaché, de sorte que le contrôle des tâches ne sera pas nécessairement disponible.

31 votes

Puisque $ ! renvoie le pid du dernier processus en arrière-plan. Est-il possible que quelque chose démarre entre foo y $! et nous obtenons que quelque chose est pid au lieu de foo 's ?

65 votes

@WiSaGaN : Non. Il n'y a rien entre ces lignes. Toute autre activité sur le système n'aura pas d'incidence. $ ! se développera jusqu'au PID du dernier processus d'arrière-plan. dans cette coquille .

9 votes

... qui vous arrose si foo se trouve être plusieurs commandes pipées (ex. tail -f somefile.txt | grep sometext ). Dans ce cas, vous obtiendrez le PID de la commande grep à partir de $! plutôt que la commande tail si c'est ce que vous recherchez. Vous devrez utiliser la commande jobs ou ps ou les "likes" en l'occurrence.

166voto

jldupont Points 31331

Vous pouvez utiliser le jobs -l pour accéder à un emploi particulierL

^Z
[1]+  Stopped                 guard

my_mac:workspace r$ jobs -l
[1]+ 46841 Suspended: 18           guard

Dans ce cas, 46841 est le PID.

De help jobs :

-l Indique l'identifiant du groupe de processus et le répertoire de travail des travaux.

jobs -p est une autre option qui n'affiche que les PID.

0 votes

Pour l'utiliser dans un shell script, il faut traiter la sortie.

7 votes

@Phil Pour lister les pids uniquement : jobs -p. Pour lister le pid d'un certain job : jobs -p %3. Il n'est pas nécessaire de traiter la sortie.

1 votes

@Erik avec des commandes / arguments différents vous changez le contexte de mon commentaire. Sans l'argument supplémentaire suggéré, la sortie nécessite un traitement. Suggérez une amélioration à la réponse !

50voto

catwalk Points 3508
  • $$ est le pid du script actuel
  • $! est le pid du dernier processus d'arrière-plan

Voici un exemple de transcription d'une session bash ( %1 désigne le numéro ordinal du processus d'arrière-plan tel qu'il est perçu à partir de jobs ) :

$ echo $$
3748

$ sleep 100 &
[1] 192

$ echo $!
192

$ kill %1

[1]+  Terminated              sleep 100

0 votes

Écho %1 ne renvoie pas le processus en arrière-plan sur mon Ubuntu alors que echo $! fait

0 votes

Il convient de noter que $$ n'est pas toujours le PID actuel. Par exemple, si vous définissez une nouvelle fonction dans bash et exécuter la fonction en arrière-plan, la fonction $$ à l'intérieur de cette fonction contient le PID du processus qui a lancé la fonction en arrière-plan. Si vous avez besoin du PID du processus qui exécute un code donné, vous devez utiliser $BASHPID au lieu de cela.

27voto

Alexey Polonsky Points 432

Une façon encore plus simple de tuer tous les processus enfants d'un script bash :

pkill -P $$

En -P fonctionne de la même manière avec pkill y pgrep - il obtient des processus enfants, seulement avec pkill les processus enfants sont tués et avec pgrep les PID des enfants sont imprimés sur stdout.

1 votes

Très pratique ! C'est la meilleure façon de s'assurer que vous ne laissez pas de processus ouverts en arrière-plan.

0 votes

@lepe : Pas tout à fait. Si vous êtes un grand-parent, cela ne fonctionnera pas : après bash -c 'bash -c "sleep 300 &"' & en cours d'exécution pgrep -P $$ ne montre rien, car le sommeil ne sera pas un enfant direct de votre coquille.

1 votes

@AlexeyPolonsky : ça devrait être : kill all child procs of a shell, not a script. Parce que $$ fait référence à l'interpréteur de commandes actuel.

5voto

Luis Ramirez Points 31

Voici ce que j'ai fait. Jetez-y un coup d'œil, j'espère que cela vous aidera.

#!/bin/bash
#
# So something to show.
echo "UNO" >  UNO.txt
echo "DOS" >  DOS.txt
#
# Initialize Pid List
dPidLst=""
#
# Generate background processes
tail -f UNO.txt&
dPidLst="$dPidLst $!"
tail -f DOS.txt&
dPidLst="$dPidLst $!"
#
# Report process IDs
echo PID=$$
echo dPidLst=$dPidLst
#
# Show process on current shell
ps -f
#
# Start killing background processes from list
for dPid in $dPidLst
do
        echo killing $dPid. Process is still there.
        ps | grep $dPid
        kill $dPid
        ps | grep $dPid
        echo Just ran "'"ps"'" command, $dPid must not show again.
done

Il suffit ensuite de l'exécuter en tant que : ./bgkill.sh avec les autorisations nécessaires, bien entendu

root@umsstd22 [P]:~# ./bgkill.sh
PID=23757
dPidLst= 23758 23759
UNO
DOS
UID        PID  PPID  C STIME TTY          TIME CMD
root      3937  3935  0 11:07 pts/5    00:00:00 -bash
root     23757  3937  0 11:55 pts/5    00:00:00 /bin/bash ./bgkill.sh
root     23758 23757  0 11:55 pts/5    00:00:00 tail -f UNO.txt
root     23759 23757  0 11:55 pts/5    00:00:00 tail -f DOS.txt
root     23760 23757  0 11:55 pts/5    00:00:00 ps -f
killing 23758. Process is still there.
23758 pts/5    00:00:00 tail
./bgkill.sh: line 24: 23758 Terminated              tail -f UNO.txt
Just ran 'ps' command, 23758 must not show again.
killing 23759. Process is still there.
23759 pts/5    00:00:00 tail
./bgkill.sh: line 24: 23759 Terminated              tail -f DOS.txt
Just ran 'ps' command, 23759 must not show again.
root@umsstd22 [P]:~# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root      3937  3935  0 11:07 pts/5    00:00:00 -bash
root     24200  3937  0 11:56 pts/5    00:00:00 ps -f

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X