Forum Programmation.shell comment tuer des process fils automatiquement dans un script shell...

Posté par .
Tags : aucun
0
25
juil.
2008
Bonsoir,

j'ai un script toto.sh qui lance plein de processes et je veux que lorsque mon script se termine les processes meurent. Il n'est pas impossible que les processes meurent d'eux même avant la fin de l'execution de toto.sh.

Au debut j'avais fait un naif:

#!/bin/bash

proc1 &
pid1=$!
proc2 &
pid2=$!
...
...
kill -9 $pid1 $pid2

mais il y a un risque, si proc1 meurent avant la fin de toto.sh de flinguer un innocent process qui aurait récupéré le pid.

J'ai pas bien saisi pourquoi lorsque j'enlève la ligne kill, les processes proc1 et proc2 disent avoir init pour pere... alors que pendant l'execution de toto, c'est bien toto le pere....

bref, c'est je pense une question basique mais google n'a pas voulu m'aider
  • # utiliser "jobs" ?

    Posté par . Évalué à 3.

    Bonjour,

    Une solution possible, c'est d'utiliser la commande jobs qui va te fournir la liste des tâches en cours, en particulier sans celles qui se sont terminées. En pratique: jobs -p.

    Pour ce qui est des parents des process, si le père se termine alors les process deviennent orphelins, donc ils ne sont plus rattachés à personne... Quel outil te dis le contraire et te les montre attachés à init?

    Enfin, perd cette habitude de mettre un -9 dans les commandes kill quand ce n'est pas nécéssaire, c'est une très mauvaise pratique.
    • [^] # Re: utiliser "jobs" ?

      Posté par . Évalué à 2.

      Bon, je viens de faire un essai: en effet, les process orphelins sont bien rattachés à init. C'est probablement un héritage d'unix: on ne cherche pas le père du père, on passe directement à init qui est le père de tous...
    • [^] # Re: utiliser "jobs" ?

      Posté par . Évalué à 1.

      Bonsoir,

      merci pour ta prompte réponse. pour l'instant je vois pas d'arnaque :-) alors qu'on m'en a proposé des trucs pas clair pour faire ça... (avec des set -m)

      pour ta question: je me suis peut-être mal exprimé, proc1 et proc2 ont leur ppid = au pid de toto.sh jusqu'à ce que toto.sh soit terminé. Ensuite leur ppid est 1, soit celui d'init. J'ai traduit ça dans un Français un peu approximatif.

      c'est bien de me conseiller de pas faire des kill -9, mais pourquoi ? ça fait 12 ans que je fais des kill -9.... ? Je vais pas prendre le risque que les processes que je lance trappent mes signaux....
      • [^] # Re: utiliser "jobs" ?

        Posté par . Évalué à 4.

        c'est bien de me conseiller de pas faire des kill -9, mais pourquoi ?

        Parce que les process bien éduqués meurent proprement au SIGTERM :)
      • [^] # Re: utiliser "jobs" ?

        Posté par . Évalué à 1.

        Qu'est-ce qui t'embête avec le set -m ?
  • # init

    Posté par (page perso) . Évalué à 2.

    Il est en effet normal, sous Unix, que les processus "orphelins" soient récupéré par init, donc que leur ppid passe à 1.

    Un lien au hasard de google :
    http://www.unixgarden.com/index.php/programmation/programmation-systeme-processus-tubes-et-threads

    Sinon, pour ton kill, si tu connais le nom de proc1 et proc2, tu peux essayer de les tuer par nom et non pas par pid : pkill proc1 .
    Il y a toujours un risque : tuer des processus du meme nom (tu peux toujours verifier, avant de faire le kill, que le nom du processus et le pid (que tu as dans ta variable) concordent).
    Sinon, si j'ai bien compris, tu veux non pas tuer certains processus, mais detruire tous ceux lancés par toto.sh. Il suffit donc de tuer les processus dont le ppid est le pid de toto.sh. Toujours avec pkill (pratique pkill, mieux que killall) :

    pkill -P $$

    (où $$ est le PID du script en cours (toto.sh), et -P demande à pkill de rechercher par ppid)
    • [^] # Re: init

      Posté par . Évalué à 3.

      Pour ne pas tuer à l'aveugle, un bon moyen est de vérifier le contenu de /proc/$pid . Évidemment ça ne fonctionne que sous linux, sous d'autres Unix il faut adapter.

      Par ex en regardant dans /proc/$pid/cmdline on peut retrouver la ligne de commande qui a servi à lancer le process.

      Dans les script /etc/init.d/, on peut trouver parfois des trucs sympa :


      running_pid() {
      # Check if a given process pid's cmdline matches a given name
      pid=$1
      name=$2
      [ -z "$pid" ] && return 1
      [ ! -d /proc/$pid ] && return 1
      cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
      # Is this the expected server
      [ "$cmd" != "$name" ] && return 1
      return 0
      }


      Évidemment reste le cas foireux où le pid a été réutilisé par le même process, mais là il faut vraiment pas avoir de bol. En plus les pid vont en s'incrémentant, le max est 32k, donc il faudrait avoir une rotation complète ET une relance du "bon" process pour être dans ce cas... Si ça t'arrive, joue au loto ;-)
  • # pkill

    Posté par (page perso) . Évalué à 2.

    La commande pkill est très bien pour cela.
    # pkill -P ...
    ou
    # pkill -g ...

    Tu peux jouer avec pgrep pour voir ce que ça donne sans casser quoi que ce soit.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.