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.
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.
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.
$$
est le pid du script actuel$!
est le pid du dernier processus en arrière-planVoici 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
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.
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
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.
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