Je démarre un processus d'arrière-plan à partir de mon script shell, et je voudrais tuer ce processus lorsque mon script se termine.
Comment obtenir le PID de ce processus à partir de mon script shell? Autant que je puisse voir, la variable $!
contient le PID du script actuel, pas le processus d'arrière-plan.
linux
shell
background-process
pid
Volodymyr Bezuglyy
la source
la source
Réponses:
Vous devez enregistrer le PID du processus d'arrière-plan au moment où vous le démarrez:
Vous ne pouvez pas utiliser le contrôle des travaux, car il s'agit d'une fonction interactive et liée à un terminal de contrôle. Un script n'aura pas nécessairement un terminal attaché du tout, donc le contrôle des travaux ne sera pas nécessairement disponible.
la source
foo
et$!
, et nous obtenons le pid de quelque chose au lieu de celuifoo
de?foo
se trouve être plusieurs commandes piped (par exemple.tail -f somefile.txt | grep sometext
). Dans de tels cas, vous obtiendrez le PID de la commande grep$!
plutôt que la commande tail si c'est ce que vous cherchiez. Vous devrez utiliserjobs
oups
ou les likes dans ce cas.grep
, mais si vous le tuez, tail recevra un SIGPIPE quand il essaiera d'écrire dans le tuyau. Mais dès que vous essayez d'entrer dans une gestion / contrôle de processus délicat, bash / shell devient assez douloureux./bin/sh -c 'echo $$>/tmp/my.pid && exec program args' &
- sysfault 24 novembre 10 à 14:28Vous pouvez utiliser la
jobs -l
commande pour accéder à un travail particulierDans ce cas, 46841 est le PID.
De
help jobs
:jobs -p
est une autre option qui affiche uniquement les PID.la source
$!
juste après avoir commencé est plus portable et plus simple dans la plupart des situations. C'est ce que fait la réponse actuellement acceptée.jobs -p
retourné le même quejobs -l
sur Lubuntu 16.4$$
est le pid du script actuel$!
est le pid du dernier processus d'arrière-planVoici un exemple de transcription d'une session bash (se
%1
réfère au nombre ordinal de processus d'arrière-plan vu dejobs
):la source
%1
ne renvoie pas le processus d'arrière-plan sur mon Ubuntu alorsecho $!
queUn moyen encore plus simple de tuer tous les processus enfants d'un script bash:
Le
-P
drapeau fonctionne de la même manière avecpkill
etpgrep
- il obtient les processus enfants, seulement avecpkill
les processus enfants qui sont tués et avecpgrep
les PID enfants sont imprimés sur stdout.la source
bash -c 'bash -c "sleep 300 &"' &
courupgrep -P $$
ne montre rien, car le sommeil ne sera pas un enfant direct de votre coquille.$$
fait référence au shell actuel.bash -c 'bash -c "sleep 300 &"' & ; pgrep -P $$
, je[1] <pid>. So at least it shows something, but this is probably not the output of
monte sur stdout pgrep`bash -c 'bash -c "sleep 10 & wait $!"' & sleep 0.1; pstree -p $$
c'est ce que j'ai fait. Vérifiez-le, j'espère que cela peut aider.
Ensuite, exécutez-le comme:
./bgkill.sh
avec les autorisations appropriées bien sûrla source
Vous pouvez également utiliser pstree:
Cela donne généralement une représentation textuelle de tous les processus pour "l'utilisateur" et l'option -p donne l'ID de processus. Pour autant que je sache, cela ne dépend pas de la propriété des processus par le shell actuel. Il montre également des fourches.
la source
pgrep
peut vous obtenir tous les PID enfants d'un processus parent. Comme mentionné précédemment,$$
le PID des scripts actuels. Donc, si vous voulez un script qui se nettoie après lui-même, cela devrait faire l'affaire:la source
trap 'pkill -P $$' SIGING SIGTERM EXIT
semble plus simple, mais je ne l'ai pas testé.SIG
préfixe. Il est autorisé par POSIX mais juste comme une extension que les implémentations peuvent prendre en charge: pubs.opengroup.org/onlinepubs/007904975/utilities/trap.html Le shell de tirets par exemple ne le fait pas.