IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Linux Discussion :

script shell, wc et fork


Sujet :

Linux

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 20
    Par défaut script shell, wc et fork
    Bonjour,

    En essayant de faire un script que je supposais très simple, je me suis retrouvé confronté à un problème délicat.

    L'objectif de mon script est relativement simple : il doit lancer un programme mais doit vérifier avant qu'il n'y a pas déjà un script qui l'a lancé.

    A coup de ps et de grep et en redirigeant le tout vers wc, je cherche donc à récupérer le nombre de script du même nom tournant actuellement. Si ce nombre est à 1 c'est que le script courant est le seul à tourner et je peux donc exécuter mon programme. Si ce nombre est différent de 1, c'est qu'il y en a déjà un autre qui tourne et je quitte sans rien faire.

    Le code de mon script (que nous appellerons "scriptExemple.sh") est donc le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #!/bin/sh
    n=`ps -ef | grep -v grep | grep scriptExemple.sh | wc -l`
    if [ $n -eq "1" ] ; then
       echo Je lance mon programme
    else
       echo Le programme tourne deja
    fi
    Seulement ce script ne marche pas car ps (?) fait parfois un "fork" de mon script ce qui fait que wc retourne une valeur erronée.

    On se rend compte de ce phénomène en effectuant ce petit script (toto.sh) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #!/bin/sh
     
    while true ; do
            ps -ef f | grep toto | grep -v grep
            echo
    done
    En exécutant ce script quelques secondes, j'obtient le résultat suivant :
    ./toto.sh
    root 15555 15361 0 14:33 pts/5 S+ 0:00 | \_ /bin/sh ./toto.sh

    root 15555 15361 0 14:33 pts/5 R+ 0:00 | \_ /bin/sh ./toto.sh
    root 15564 15555 0 14:33 pts/5 R+ 0:00 | \_ /bin/sh ./toto.sh
    On constate donc que parfois tout se passe bien (la première ligne) et parfois ps crée un script fils du même nom.

    Bref, à mon grand malheur, mon petit script tout simple ne me permet pas de récupérer le nombre exact de scripts du même nom tournant en même temps.

    Auriez-vous une explication sur ce phénomène et, encore mieux, une solution pour mon petit script (une solution simple serait de créer un fichier de verrouillage et de la supprimer, sa présence me signalerait donc s'il y a déjà un script qui tourne ou non).

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 124
    Par défaut
    tu fais passer ton script dans le tub?

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 20
    Par défaut
    Aucune idée, qu'est-ce que tu entends par là ?

  4. #4
    Membre émérite
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Par défaut
    Tu peux peut-être enlever le PID ($$) en entier (grace a \<\>) de ton script dans le grep (qui enleve aussi celui du fork en tant que PPID):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    n=`ps -ef | grep -v grep | grep scriptExemple.sh | grep -v "\<$$\>" | wc -l`
    Bon c'est pas idyllique parce que par un hasard quelconque tu peux très bien avoir ton PID présent dans la ligne du ps -ef, peut être en forçant ps à n'afficher que le PID et le PPID:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    n=`ps -ef o pid,ppid,cmd | grep -v grep | grep scriptExemple.sh | grep -v "\<$$\>" | wc -l`
    Rq: o (et non -o) c'est pour choisir les champs à afficher.

    Reste le pb qu'un editeur peut très bien ouvrir ton programme, et il peu y avoir un "gvim scriptExample.sh" qui traine !
    Conclusion, filtrer avec -C et ne greper que sur les PID et PPID
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #!/bin/sh
    n=`ps -C scriptExemple.sh o pid,ppid | grep -v "\<$$\>" | wc -l`
    if [ $n -eq "0" ] ; then
       echo "Je lance mon programme"
    else
       echo "Le programme tourne deja ($n instances)"
    fi
    [edit] ajout d'un | endre ppid et grep

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 20
    Par défaut
    Je comprend pas trop pourquoi tu fais un grep sur le pid (grep -v "\<$$\>").

    Parce que si il y a deux toto.sh qui tournent, ils ont chacun un pid différent donc si on fait un grep -v sur le pid du script dans lequel on se trouve, il devrait systématiquement nous renvoyer que lui et ses fils, à moins de ne pas mettre le ppid à l'affichage dans ce cas on aurait même pas les fils mais on aurait systématiquement un seul résultat alors qu'il y a 2 toto.sh qui tournent.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 20
    Par défaut
    Ca y est, je crois que j'ai trouvé une solution.

    Mes N scripts toto.sh ont tous le même père (mon bash).
    Donc si je récupère le PID du père et qu'ensuite je filtre les résultats de mon ps par rapport à ce PID, je n'aurais pas les fork (qui ont pour PPID le PID d'un script toto.sh et non le PID du bash).

    Donc je récupère dans un premier temp le PPID de mon script courant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    VAR_PPID=`ps -p $$ o ppid | grep -v PPID`
    Dans un second temps, je filtre le résultat du ps sur ce ppid :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ps -C toto.sh o ppid,cmd | grep $VAR_PPID
    En définitive, mon script a le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    VAR_PPID=`ps -p $$ o ppid | grep -v PPID`
    n=`ps -C scriptExemple.sh o ppid,cmd | grep $VAR_PPID | wc -l`
     
    if [ $n -eq "1" ] ; then
       echo Aucun autre scriptExemple.sh en cours d'execution, on peut lancer le programme
       # <-- APPEL DU PROGRAMME ICI -->
    else
       echo Il y a deja $(($n-1)) autre(s) scriptExemple.sh qui tourne(nt), on ne lance pas le programme
    fi

  7. #7
    Membre émérite
    Avatar de D[r]eadLock
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    504
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 504
    Par défaut
    Citation Envoyé par nlo38 Voir le message
    Je comprend pas trop pourquoi tu fais un grep sur le pid (grep -v "\<$$\>").
    C'est pour enlever l'instance courrante (ainsi que les eventuels fork (du a ps voire a d'autres trucs)).
    Rq: dans le test en dessous j'ai mis 0 (et non plus 1): c-a-d s'il existe aucun autre processus (que celui-ci ou ses children).


    Citation Envoyé par nlo38
    Parce que si il y a deux toto.sh qui tournent, ils ont chacun un pid différent
    oui

    Citation Envoyé par nlo38
    donc si on fait un grep -v sur le pid du script dans lequel on se trouve, il devrait systématiquement nous renvoyer que lui et ses fils,
    au contraire le -v va les enlever, il ne restera que les autres !

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 20
    Par défaut
    Oui mais si les autres instances du script ont eux aussi des fork, ça ne les retire pas...

Discussions similaires

  1. Script shell
    Par anzar dans le forum Linux
    Réponses: 4
    Dernier message: 03/12/2004, 14h41
  2. [JSP] script shell
    Par goolix dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 06/08/2004, 09h08
  3. Exécution d'un script shell
    Par Manu0086 dans le forum Linux
    Réponses: 8
    Dernier message: 15/06/2004, 16h31
  4. Explication script shell
    Par crasho007 dans le forum Linux
    Réponses: 2
    Dernier message: 14/06/2004, 13h54
  5. Cron + terminal + script shell
    Par nicolas.pissard dans le forum Linux
    Réponses: 3
    Dernier message: 17/03/2004, 09h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo