Forum Programmation.shell système de verrou ( 1 = 2, sisi avec linux )

Posté par  .
Étiquettes : aucune
0
5
nov.
2007
Je viens à votre rencontre pour vous aider dans ma recherche ^^ (voilà une manière de dire que l'on as besoin d'aide).

Plus sérieusement, je tente de me défaire des fichiers verrous que l'on peut créer dans nos scripts, tels que ceux que l'on peut mettre dans le /var/run.

J'ai pensé à une méthode, celle de compter le nombre de processus en cours et si le nombre de processus est égal à 2 ou supérieur .... c'est que le script est déjà en exécution.

Certes, simple comme idée, ca marche en console, mais dans un script, ce n'est pas la même chose.

Voilà le petit script en question ( vous pourrai le montrer à un prof de math ... ) :


#!/bin/sh
ps aux | grep '/bin/sh' | grep " $0$\|/$0$" | grep -v 'grep' | wc -l
# le résultat est 1
if [ `ps aux | grep '/bin/sh' | grep " $0$\|/$0$" | grep -v 'grep' | wc -l` -eq 2 ]
then
echo "le resultat 1 est egal a 2"
fi
# ici, c'est 2


Certes ... c'est vrai, ca fonctionne, la même ligne hors du if donne 1 et la même ligne avec un if donne 2.

Je pense qu'il y a une sorte de multi-thread ... et je ne sais pas comment résoudre mon soucis.

Il y a t'il une manière de vérifier suivant les process si le script a déjà été lancé avant ? Sans se fier avec la date/heure de début de script, car ca fonctionne, mais avec 1 minute de marge, et c'est très long pour un script fou.

Merci d'avance.
  • # Voir grep

    Posté par  . Évalué à 2.

    Je n'ai pas beaucoup exploré ton script mais l'erreur classique quand on fait ce genre de chose, c'est de reconnaître, en plus du processus examiné, le grep lui même. Ex :

    $ ps | grep toto
    obs 1005 ./toto
    obs 1006 grep toto

    Et selon la planification des tâches, le grep peut ou non apparaître dans la liste des processus.

    Le meilleur moyen, à mon goût, d'éviter le lancement multiple de plusieurs applications est l'utilisation de sockets Unix que l'on peut interroger. Ainsi, on reste dans la philosophie du système de fichier, ça marche sur les archis distribuées et les serveurs, on n'exploite pas un port réseau (hérésie), et l'espace de nommage des sockets est virtuellement sans limite (contrairement aux ids des IPC SysV par exemple). En outre, si le fichier traîne dans le /var/run ou ailleurs, mais qu'il n'y a plus de processus à l'autre bout, on le sait très vite en l'interrogeant.

    Maintenant, je conçois qu'exploiter des sockets en shell ...
    • [^] # Re: Voir grep

      Posté par  . Évalué à 1.

      grep, voire meme simplement le ` xxx `
      qui si je ne m'abuse lance un shell, execute la ligne de commande xxx et renvoie le resultat

      pour tester la premiere ligne j'aurais fait un

      RES=` la ligne complete`
      echo $RES

      puis le if...

      pour bien avoir la meme ligne executer dans les 2 cas.
  • # De toute façon ça ne marche pas ...

    Posté par  . Évalué à 3.

    si tu lance la commande avec le chemin absolu, depuis le repertoire courant ou un chemin relatif, ça risque de ne pas marcher.

    Le fichier verrou est bien plus simple.

    Ou alors, il faut encapsuler ton lancement de process dans un script qui exécutera toujours la même ligne de commande, quel que soit la façon dont il est appelé .... mais ça commence a faire compliqué.
    • [^] # Re: De toute façon ça ne marche pas ...

      Posté par  . Évalué à 1.

      Pour ce qui est de l'erreur classique du grep, c'est géré.

      grep -v 'grep'

      et pour ce qui est de l'absolu ou du relatif, c'est géré également :

      grep " $0$\|/$0$"

      soit :
      espace nomduscrip puis $
      ou
      slash nomduscript puis $

      Et les deux lignes sont strictement identiques.

      L'erreur est que pendant l'éxécution en mémoire, une même commande peut avoir plusieurs thread en process ...

      Le problème du fichier verrou, c'est que s'il n'est pas supprimé, le script considère qu'il tourne perpétuellement.
      • [^] # Re: De toute façon ça ne marche pas ...

        Posté par  . Évalué à 4.

        Bon, le problème: quand tu execute une commande via ` `, tu lances un sous shell. Pour contourner, il faut supprimer de la liste les process ayant en PID ou PPID le numéro de process de ton script. Par exemple avec awk :

        #!/bin/sh

        if [ `ps -ao pid,ppid,command | awk 'BEGIN {CTR=0} (($1 != "'$$'") && ($2 != "'$$'")) && ($4 ~ ".*/*'$0'") {
        CTR=1
        }
        END { print CTR }'` -gt 0 ]
        then
        echo " Process tournant deja"
        fi
        sleep 100

        ------------------------------------------------------
        plus simple on compte le nombre de process, s'il est superieur a 1 on sort de awk en retournant une erreur:

        #!/bin/sh

        if ! ps -ao command | awk '(($1 == "/bin/sh") && ($2 ~ ".*/*'$0'")) {
        CTR++
        }
        END { exit (CTR-1) }'

        then
        echo " Process tournant deja"
        fi

        sleep 100



        Je viens de me rendre compte dans la premiere solution que je ne teste pas la presence de "/bin/sh", mais c'est pas grave, l'idée est là (un test a ajouter).

        • [^] # Re: De toute façon ça ne marche pas ...

          Posté par  . Évalué à 2.

          Y a un pb dans mon truc, ca marche pas ...

          Essaye, pour la secnde solution:

          #!/bin/sh

          echo " $$ $0"

          COMMAND=`basename $0`

          if ! ps -ao command | awk '($1 == "/bin/sh") && ($2 ~ "/*'$COMMAND'$") {
          CTR++
          }
          END { exit (CTR-1) }'

          then
          echo " Process tournant deja"
          fi
          sleep 100
        • [^] # Re: De toute façon ça ne marche pas ...

          Posté par  . Évalué à 4.

          la premiere solution corrigee donne ca:

          #!/bin/sh

          COMMAND=`basename $0`
          if [ `ps -ao pid,ppid,command | awk 'BEGIN {CTR=0} (($1 != "'$$'") && ($2 != "'$$'")) && ($4 ~ "/*'$COMMAND'") {
          CTR=1
          }
          END { print CTR }'` -gt 0 ]
          then
          echo " Process tournant deja"
          fi
          sleep 100
          • [^] # Script final

            Posté par  . Évalué à 2.

            Je me suis inspiré fortement de ta solution, ce qui me donne ceci :

            #!/bin/sh
            PID=$$
            if [ `ps -ao pid,ppid,command | tail +2 | grep ' /bin/sh ' | grep /\`basename $0$\` | grep -v "$PID " | wc -l` -ne 0 ]
            then
            echo "tourne deja"
            exit
            fi

            Je n'aime pas trop awk (enfin, je ne saisie pas son sens).
            • [^] # Re: Script final

              Posté par  . Évalué à 2.




              Je n'aime pas trop awk (enfin, je ne saisie pas son sens).



              TU REAGIS MAL !!!
              • [^] # Re: Script final

                Posté par  . Évalué à 1.

                TU REAGIS MAL !!!


                Tu réagis sous le coup de la colère ?
  • # écorchage

    Posté par  . Évalué à 3.

    vous pourrai le montrer à un prof de math ...

    En tous cas ne le montre pas à un prof de français ...
    • [^] # Re: écorchage

      Posté par  . Évalué à 1.

      Merci pour tout.

      J'ai encore du soucis avec mon orthographe (avant, c'était pire).

      Merci totof2000.

Suivre le flux des commentaires

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