web-dev-qa-db-fra.com

Comment obtenir le PID du processus d'arrière-plan?

Je lance un processus d'arrière-plan à partir de mon script Shell et je souhaite supprimer ce processus à la fin de mon script.

Comment obtenir le PID de ce processus à partir de mon script Shell? Autant que je sache, la variable $! contient le PID du script en cours, pas le processus d'arrière-plan.

339
Volodymyr Bezuglyy

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, car il s'agit d'une fonctionnalité interactive liée à un terminal de contrôle. Un script ne sera pas nécessairement associé à un terminal, de sorte que le contrôle des tâches ne sera pas nécessairement disponible.

511
camh

Vous pouvez utiliser la commande jobs -l pour accéder à un travail particulier

^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'ID du groupe de processus et le répertoire de travail des travaux.

jobs -p est une autre option qui affiche uniquement les PID.

130
jldupont
  • $$ est le pid du script actuel
  • $! est le pid du dernier processus en arrière-plan

Voici un exemple de transcription d'une session bash (%1 fait référence au nombre ordinal de processus d'arrière-plan vu de jobs):

$ echo $$
3748

$ sleep 100 &
[1] 192

$ echo $!
192

$ kill %1

[1]+  Terminated              sleep 100
45
catwalk

Un moyen encore plus simple de tuer tous les processus enfants d'un script bash:

pkill -P $$

Le drapeau -P fonctionne de la même manière avec pkill et pgrep - il obtient des processus enfants, mais avec pkill, les processus enfants sont supprimés et avec pgrep PID enfants. sont imprimés sur la sortie standard.

25
Alexey Polonsky

c'est ce que j'ai fait. Allez voir ça, espérons que ça peut aider.

#!/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

Ensuite, lancez-le simplement comme: ./bgkill.sh avec les permissions appropriées bien sûr

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
3
Luis Ramirez

Vous pourriez aussi pouvoir utiliser pstree:

pstree -p user

Cela donne généralement une représentation textuelle de tous les processus pour "l'utilisateur" et l'option -p donne l'identifiant du processus. Autant que je sache, cela ne dépend pas de la propriété du processus actuel par Shell. Il montre également des fourchettes.

2
villaa

pgrep peut vous fournir tous les PID enfants d'un processus parent. Comme mentionné précédemment, $$ est le PID des scripts en cours. Donc, si vous voulez un script qui se nettoie après lui-même, ceci devrait faire l'affaire:

trap 'kill $( pgrep -P $$ | tr "\n" " " )' SIGINT SIGTERM EXIT
1
errant.info