Forum Programmation.shell action simultanée

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
2
4
fév.
2013

Actuellement j'ai une script récoltant des informations sur différent poste du réseau à l'aide d'une liste d'adresse contenu dans un fichiers config . Cependant c'est action se font 1 par 1 et j'aimerai faire ces récoltes simultanément . je suis sur cent os et justilse un :

while read IP do 

{action $IP}

done <ip.cfg

Merci de votre aide

  • # &

    Posté par  . Évalué à 1.

    Un & à la fin de la ligne? (pour lancer en arrière-plan)

    • [^] # Re: &

      Posté par  . Évalué à -1.

      euh je ne suis pas sur que ça marche ! je vais testé

      • [^] # Re: &

        Posté par  . Évalué à 1.

        ne marche pas : S

        • [^] # Re: &

          Posté par  . Évalué à 1.

          Tu l'as mis où ton & ?

          • [^] # Re: &

            Posté par  . Évalué à -2.

            j'ai essayé a plusieurs endroit. En gros les action dans les actions dans le while read sont 4 requête snmp qui utilise les adresse ip de ip.cfg . j'ai testé après le do mais ça bug.

            • [^] # Re: &

              Posté par  . Évalué à 2. Dernière modification le 04 février 2013 à 10:37.

              Tu pourrais poster ton script dans son intégralité s'il y a si peu de ligne, on y verrait plus clair.

              Considère l'exemple suivant :

              $ cat toto.sh
              #!/bin/bash
              for i in $(seq 1 3); do
              sleep 1;
              done;
              
              
              $ cat titi.sh
              #!/bin/bash
              for i in $(seq 1 3); do
              sleep 1 &
              done;
              
              
              $ time ./toto.sh
              
              real    0m3.307s
              user    0m0.108s
              sys     0m0.167s
              
              $ time ./titi.sh
              
              real    0m0.184s
              user    0m0.030s
              sys     0m0.122s
              
              

              Dans toto.sh on fait 3 sleep 1 consécutifs donc le script dure 3 secondes, dans titi.sh les sleep tournent en parallèle, le shell n'attend que le premier soit fini pour lancer le deuxième.

              j'ai testé après le do mais ça bug

              Certainement une erreur de syntaxe. On ne peut pas vraiment parler de bug, c'est le comportement attendu…

              • [^] # Re: &

                Posté par  . Évalué à -2.

                while IFS=" " read nom swip nbport machine
                do
                jour=$(date +"%d-%m-%y" )
                heure=$(date +"%T")
                echo $machine
                #Recuperation des addresse mac dans un fichier au format decimal et hexa
                        #creation du fichier mac1016.dat contenant la relation mac hex / mac deci
                        snmpwalk -v 2c -c public -OX -Cc $swip 1.3.6.1.2.1.17.4.3.1.1 | \
                        cut -c29- | \
                        awk -F " " '{ print $1,$4"-"$5"-"$6"-"$7"-"$8"-"$9 }' | \
                        sort -k 1,1 > ./mac1016.dat
                
                        #recuperation du portbridge et creation de bridge.dat
                        snmpwalk -v 2c  -c public -Of -Cc $swip .1.3.6.1.2.1.17.4.3.1.2 |\
                        cut  -c44- | \
                        awk -F " " '{ print $1,$4 }' | \
                        sort -k 1,1 > ./bridge.dat
                
                        #recuperation du portID et creation du fichier portid.dat
                        snmpwalk -v 2c  -c public -Of  $swip .1.3.6.1.2.1.17.1.4.1.2 | \
                        cut  -c45- | \
                        awk -F " " '{ print $4,$1 }' | \
                        sort -k 1,1 > ./portid.dat
                
                        #recuperation du port et creation de port.dat
                        snmpwalk -v 2c  -c public -Of  $swip .1.3.6.1.2.1.31.1.1.1.1 | \
                        cut -c78- | \
                        awk -F " " '{ print $1,$4 }' | \
                        sort -k 1,1 >./port.dat
                done < ip.cfg
                
                
                • [^] # Re: &

                  Posté par  . Évalué à 3.

                  while IFS=" " read nom swip nbport machine
                  do
                  jour=$(date +"%d-%m-%y" )
                  heure=$(date +"%T")
                  echo $machine
                  #Recuperation des addresse mac dans un fichier au format decimal et hexa
                          #creation du fichier mac1016.dat contenant la relation mac hex / mac deci
                          snmpwalk -v 2c -c public -OX -Cc $swip 1.3.6.1.2.1.17.4.3.1.1 | \
                          cut -c29- | \
                          awk -F " " '{ print $1,$4"-"$5"-"$6"-"$7"-"$8"-"$9 }' | \
                          sort -k 1,1 > ./mac1016.dat &
                  
                          #recuperation du portbridge et creation de bridge.dat
                          snmpwalk -v 2c  -c public -Of -Cc $swip .1.3.6.1.2.1.17.4.3.1.2 |\
                          cut  -c44- | \
                          awk -F " " '{ print $1,$4 }' | \
                          sort -k 1,1 > ./bridge.dat &
                  
                          #recuperation du portID et creation du fichier portid.dat
                          snmpwalk -v 2c  -c public -Of  $swip .1.3.6.1.2.1.17.1.4.1.2 | \
                          cut  -c45- | \
                          awk -F " " '{ print $4,$1 }' | \
                          sort -k 1,1 > ./portid.dat &
                  
                          #recuperation du port et creation de port.dat
                          snmpwalk -v 2c  -c public -Of  $swip .1.3.6.1.2.1.31.1.1.1.1 | \
                          cut -c78- | \
                          awk -F " " '{ print $1,$4 }' | \
                          sort -k 1,1 >./port.dat &
                  done < ip.cfg
                  
                  

                  En les mettant là ça ne fonctionne pas ?

                  • [^] # Re: &

                    Posté par  . Évalué à -2.

                    c'a va paralléliser les 4 snmp , moi ce que j'aimerai c'est que les 4 soit fait dans cette ordre sur toutes les IP.

                    • [^] # Re: &

                      Posté par  . Évalué à 3.

                      si tu écrit tes 4 actions dans un script séparé et que du appel ton script avec un & ça donne quoi ?
                      ca ferai un truc du genre :

                      while IFS=" " read nom swip nbport machine
                      do
                         script.sh $param1 $param2 &
                      done < ip.cfg
                      
                      
                    • [^] # Re: &

                      Posté par  . Évalué à 1.

                      &&

                      : )

                    • [^] # Re: &

                      Posté par  . Évalué à 1.

                      Ils vont bien être lancé dans l'ordre mais sans attendre la fin de la commande précédente à chaque fois. Par contre il y a un truc que je ne comprends pas : tu écrases tes fichiers .dat pour chaque IP ? Cela ne devrait pas être >> à la place de > ?

                      En parallélisant tes snmpwalk ne vont pas forcément se finir dans l'ordre donc l'ordre dans tes fichiers .dat ne seront pas forcément dans le même ordre que ton ip.cfg ?!

                      Bref je ne comprends pas bien et je sèche désolé. Bon courage.

                      À moins que…

                      Si tu mettais tes quatre snmpwalk dans une fonction et qu'ensuite tu appelles ta fonction à l'intérieur de ta boucle avec & ?

                      • [^] # Re: &

                        Posté par  . Évalué à -1.

                        En parallélisant tes snmpwalk ne vont pas forcément se finir dans l'ordre donc l'ordre dans tes fichiers .dat ne seront pas forcément dans le même ordre que ton ip.cfg ?!

                        Oui c'est normal, mais ce que j'ai compris c'est que benofdark veux que les 4 actions soient faite dans l'ordre pour chaque ip donc c'est bon, nan ? voir sont dernier commentaire :

                        moi ce que j'aimerai c'est que les 4 soit fait dans cette ordre sur toutes les IP.

                        Sinon pour les fichier je suis d'accord avec toi , ça va écrasé mais si on ce concentre sur un pb a la fois ça ira mieu …

                        • [^] # Re: &

                          Posté par  . Évalué à -2.

                          effectivement c'est 4 actions doivent se faire dans cette ordre , mais pour chaque IP en même temps.

                          • [^] # Re: &

                            Posté par  . Évalué à 0.

                            oki je crois comprendre ce que tu veux

                            tu veux que les action ce fasse dans cette ordre mais tu veux faire toute les ip sur l'action 1 puis toutes les ips sur l'action2 ,etc… c'est ça ?

                            donc avec 4 boucles a la suite ca devrai le faire non ?
                            ça ferai un truc du genre

                            while IFS=" " read nom swip nbport machine
                            do
                            commande1 &
                            done;
                            while IFS=" " read nom swip nbport machine
                            do
                            commande2 &
                            done;
                            ...
                            
                            
                            • [^] # Re: &

                              Posté par  . Évalué à -1.

                              par exemple :

                              ip.cgf
                              192.168.0.1
                              192.168.0.2

                              j'aimerai :

                              faire les 4 action une par une pour 192.168.0.1 et en meme temps les faire pour 192.168.0.2

                              un ami ma diriger vers Gnu parallel , quelqu'un connai ?

                              • [^] # Re: &

                                Posté par  . Évalué à 0.

                                si pour toi il n'est pas important d'attendre que toute les premières action soient terminé pour toutes les ip avant de lancer les actions 2, en gros si tu veux juste garantir l'ordre des actions pour chacune des ip, mon premier exemple devrai faire ce que tu veux :

                                Tu mets tes 4 actions dans un script qui attend l'ip en paramètre et dans ta boucle tu appel ton script en tache de fond avec un &
                                ça te lancera les 4 actions à la suite par ip mais chaque ip sera lancé en tache de fond.

                                et hop t'as gagner …

                                ca ferai un truc du genre :
                                while IFS=" " read nom swip nbport machine
                                do
                                script.sh $paramTonIP &
                                done < ip.cfg

                                • [^] # Re: &

                                  Posté par  . Évalué à 3.

                                  Des parenthèses bien placées et un & derrière devraient suffire.

                                  Sans parenthèses :

                                  #!/bin/bash
                                  
                                  
                                  for i in a b c
                                  do
                                          echo "$i"
                                          sleep 10
                                          echo " -- $i"
                                  done
                                  
                                  

                                  A l'exécution :

                                  $ time sh /tmp/toto.sh
                                  a
                                   -- a
                                  b
                                   -- b
                                  c
                                   -- c
                                  
                                  real    0m30.025s
                                  user    0m0.000s
                                  sys     0m0.004s
                                  
                                  

                                  Avec les parenthèses :
                                  le code :

                                  #!/bin/bash
                                  
                                  
                                  for i in a b c
                                  do
                                  (       echo "$i"
                                          sleep 10
                                          echo " -- $i" ) &
                                  done
                                  
                                  

                                  a l'exécution :

                                  $ time sh /tmp/toto.sh
                                  a
                                  b
                                  c
                                  
                                  real    0m0.009s
                                  user    0m0.004s
                                  sys     0m0.000s
                                  $  -- a
                                   -- b
                                   -- c
                                  
                                  

                                  Explication : les parenthèses exécutent les commandes qu'elles contiennent dans un sous-shell. Ce qui signifie que, dans le code, il faudrait mettre entre parenthèses tout le bloc de code qui doit s'exécuter dans un ordre précis et mettre un & derrière pour que les blocs entre parenthèses s'exécutent en paralèle les uns des autres.

                                  • [^] # Re: &

                                    Posté par  . Évalué à 4.

                                    Si je reprends ton code, ça fait un truc du genre :

                                    while IFS=" " read nom swip nbport machine
                                    do
                                    
                                    (
                                    jour=$(date +"%d-%m-%y" )
                                    heure=$(date +"%T")
                                    echo $machine
                                    #Recuperation des addresse mac dans un fichier au format decimal et hexa
                                            #creation du fichier mac1016.dat contenant la relation mac hex / mac deci
                                            snmpwalk -v 2c -c public -OX -Cc $swip 1.3.6.1.2.1.17.4.3.1.1 | \
                                            cut -c29- | \
                                            awk -F " " '{ print $1,$4"-"$5"-"$6"-"$7"-"$8"-"$9 }' | \
                                            sort -k 1,1 > ./mac1016.dat 
                                    
                                            #recuperation du portbridge et creation de bridge.dat
                                            snmpwalk -v 2c  -c public -Of -Cc $swip .1.3.6.1.2.1.17.4.3.1.2 |\
                                            cut  -c44- | \
                                            awk -F " " '{ print $1,$4 }' | \
                                            sort -k 1,1 > ./bridge.dat 
                                    
                                            #recuperation du portID et creation du fichier portid.dat
                                            snmpwalk -v 2c  -c public -Of  $swip .1.3.6.1.2.1.17.1.4.1.2 | \
                                            cut  -c45- | \
                                            awk -F " " '{ print $4,$1 }' | \
                                            sort -k 1,1 > ./portid.dat 
                                    
                                            #recuperation du port et creation de port.dat
                                            snmpwalk -v 2c  -c public -Of  $swip .1.3.6.1.2.1.31.1.1.1.1 | \
                                            cut -c78- | \
                                            awk -F " " '{ print $1,$4 }' | \
                                            sort -k 1,1 >./port.dat 
                                    ) &
                                    done < ip.cfg
                                    
                                    

                                    Après, il te faudra probablement jouer avec les fichiers de logs de façon à ne pas les écraser entre eux en générant 1 fichier de log par machine.

                                    • [^] # Re: &

                                      Posté par  . Évalué à 0.

                                      l'avantage de gèrer les fichier de logs à part c'est qu'on peut avant de regrouper les résultats faire un contrôle d'erreur bien plus facile si besoin et surtout plus complêt. après c'est que de la mise en forme du résultat bien sur.

  • # xargs, tout simplement

    Posté par  . Évalué à 4. Dernière modification le 05 février 2013 à 15:36.

    Tout simplement, tu fais un script qui fait l'action sur une IP donnée en argument, genre action_sur_IP :

    #!/bin/bash
    
    IP=$1
    # Je fais plein de truc avec $IP
    
    

    Puis après tu lances tout avec xargs, genre

    xargs -n 1 -P 0 ./action_sur_IP < ip.cfg
    
    

    Et hop, ça roule.

    En jouant avec le -P tu peux décider combien de processus tu execute en paralelle (-P 0 veut dire autant qu'il y a de processus à lancer, donc tout en même temps).

  • # grouper les resultats

    Posté par  . Évalué à 2.

    j'ai l'impression, en relisant tes differents posts
    que ce que tu veux faire ressemble à ca

    Action 1 sur IP-A => log1 qui stocke l'IP et le resultat1
    Action 2 sur IP-A => log2 qui stocke l'IP et le resultat2
    Action 3 sur IP-A => log3 qui stocke l'IP et le resultat3
    Action 4 sur IP-A => log4 qui stocke l'IP et le resultat4

    puis avec un script regrouper les log1 à log4 en fonction de l'adresse IP (le post precedent sur les joins ou les filtres pour trouver une info dans un fichier de log)

    c'est une technique

    mais tu pourrais aussi faire une boucle sur les IPs

    executer Action1 et stocker le resultat1 dans une variable1,
    executer Action2 et stocker le resultat2 dans une variable2,
    executer Action3 et stocker le resultat3 dans une variable3,
    executer Action4 et stocker le resultat4 dans une variable4,

    et en fin de boucle faire un echo $IP $variable1 $variable2 $variable3 $variable4 dans un fichier logIP

    du coup tu pourrais paralleliser pour chaque IP, mais pas pour chaque test.

  • # parallel

    Posté par  . Évalué à 2.

    le successeur de xargs.
    un peu plus d'option (comme la conservation de l'ordre des outputs).
    une très bonne doc.

Suivre le flux des commentaires

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