Obtention du PID de la commande plus tôt dans Pipeline

11

J'écris un script bash à utiliser inotifywaitpour surveiller un répertoire et lancer des actions lorsque des changements sont détectés. Quelque chose comme:

inotifywait -m ... | while read f; do something; done

Puisque inotifywaitne se termine pas par lui-même, ce script ne s'arrêtera pas.

Mon plan était donc d'obtenir le PID du processus inotifywait, de l'enregistrer dans un fichier et de le tuer plus tard par un processus différent, par exemple:

inotifywait -m ... | { echo ??PID?? > pid-file; while ... }

Mais je ne sais pas comment obtenir le PID. Existe-t-il un moyen simple d'y parvenir? Une autre façon consiste simplement à enregistrer le PID du script shell $$dans le fichier et à tuer l'intégralité du script shell, mais je voulais faire un peu de nettoyage après la boucle while.

J'ai essayé d'utiliser coprocet je pense que cela fonctionnera mais cela semble être plus compliqué que nécessaire.

Adrian Pronk
la source
Vous pouvez utiliser quelque chose comme ceci `ps -ef | grep processName | grep -v grep | awk '{print $ 2}' | xargs kill -9 `
Kiwy
@Kiwy - au lieu de ce gâchis, faites juste un pgrep inotifywait. Cela vous donnera le PID, tuer, pkill inotifwait.
slm
@slm selon votre système, vous n'aurez pas pgrep et pkill tandis que grep et ps seront presque présents. Vous êtes les bienvenus
Kiwy
@Kiwy - douteux, ces outils sont assez omniprésents. De plus, vous n'avez pas besoin de faire un grep -v grep, mais vous ps -ef | grep [p]rocessname...feriez de même.
slm
1
@DavidsonChua - oui, vous pouvez utiliser le -fcommutateur si vous avez besoin de faire correspondre plus de noms d'exécutables.
slm

Réponses:

6

Dans un pipeline, tous les processus sont démarrés simultanément , aucun n'est plus tôt que les autres.

Vous pourriez faire:

(echo "$BASHPID" > pid-file; exec inotifywait -m ...) | while IFS= read -r...

Ou portable:

sh -c 'echo "$$" > pid-file; exec inotifywait -m ...' | while IFS= read -r...

Notez également que lorsque le sous-shell qui exécute la whileboucle se termine, inotifywaitil sera automatiquement tué la prochaine fois qu'il écrit quelque chose sur stdout.

Stéphane Chazelas
la source
3

Si vous avez besoin de l'ID de processus dans la boucle, imprimez-le d'abord.

sh -c 'echo "$$"; exec inotifywait -m ...' | {
  read inotifywait_pid
  while IFS= read -r f; do
    
    if …; then kill "$inotifywait_pid"; break;
  done
}
Gilles 'SO- arrête d'être méchant'
la source