Script bash Nagios-Like

Script bash Nagios-Like - Divers - Programmation

Marsh Posté le 24-05-2011 à 11:17:46    

Bonjour,bonjour,
 
Je suis pas mauvais en programmation java,php,c++, mais la je suis tombé sur un qui me rebute x)  
La syntaxe, la manière de procéder avec un programme shell/Bash, c'est franchement différent de ce que je fais d'habitude x)
 
J'ai essayé à des fins d'apprentissage personnel, de faire un mini script qui ferait un peu comme nagios : qui enverrait un mail chaque fois qu'un hôte du réseau passe up ou down.
J'ai trouvé un script sur le net et j'ai essayé d'adapter un peu mais tout ne marche pas terriblement bien x)
 
voilà mon code, le for est inutile vu comment mon programme est construit pour le moment je sais x) :
 
 

Code :
  1. #!/bin/bash
  2. HOSTS="NOMDUPC";
  3. mailadmin="admin@domain.com"
  4. state=0;
  5. datt=$(date)
  6. while [ 1 = 1 ]
  7. do
  8.         for h in $HOSTS;
  9.         do
  10.                 fping -t1000 $h >& /dev/null;
  11.                 resultping = $?
  12.                         if [ $resultping != 0 -a $state == 1 ]; then
  13.                                 echo ${h} host is down;
  14.                                 mail -s "${h} down $datt" $mailadmin </dev/null;
  15.                                 $state=0;
  16.                         elif [ $resultping == 0 -a $state == 0 ]; then
  17.                                 echo $(h) host is up;
  18.                                 mail -s "${h} up $datt" $mailadmin </dev/null;
  19.                                 $state=1;
  20.                         fi
  21.         done
  22.         sleep 10
  23. done


 
 
 
voilà la trace d'execution que ca me donne en utilisant ce programme sur un PC allumé... il semblerait que je ne sache pas assigner des variables -->  
+ resultping = 0
innaccessible2.bash: line 15: resultping: command not found
+ '[' '!=' 0 -a 0 == 1 ']'
 
 

Spoiler :

+ HOSTS=NOMDUPC
+ mailadmin=admin@domain.com
+ state=0
++ date
+ datt='mardi 24 mai 2011, 10:58:11 (UTC+0200)'
+ '[' 1 = 1 ']'
+ for h in '$HOSTS'
+ fping -t1000 NOMDUPC
ar-PO1595 is alive
++ echo 0
+ resultping = 0
innaccessible2.bash: line 15: resultping: command not found
+ '[' '!=' 0 -a 0 == 1 ']'
innaccessible2.bash: line 16: [: too many arguments
+ '[' == 0 -a 0 == 0 ']'
innaccessible2.bash: line 20: [: too many arguments
+ sleep 10


Message édité par zownierd le 24-05-2011 à 11:21:09
Reply

Marsh Posté le 24-05-2011 à 11:17:46   

Reply

Marsh Posté le 24-05-2011 à 11:26:24    

en bash, il ne faut pas d'espace entre ta variable, le signe d'affectation et la valeur affectée. Donc il faut écrire :
resultping=$?

Reply

Marsh Posté le 24-05-2011 à 12:47:03    

Merci bien, j'étais sûr que c'était un truc con x)
 
Le script fonctionne maintenant bien, simplement j'ai un message d'erreur qui ressemble au précédent ^^ :
./innaccessible2.bash: line 20: h: command not found

Code :
  1. for h in $HOSTS;
  2.         do
  3.                 fping -t1000 $h >& /dev/null;
  4.                 resultping=$?
  5.                         if [ $resultping -ne 0 -a $state -eq 1 ]; then
  6.                                 echo ${h} host is down;
  7.                                 mail -s "${h} down $datt" $mailadmin </dev/null;
  8.                                 state=0;
  9.                         elif [ $resultping -eq 0 -a $state -eq 0 ]; then
  10.                                 echo $(h) host is up;
  11.                                 mail -s "${h} up $datt" $mailadmin </dev/null;
  12.                                 state=1;
  13.                         fi
  14.         done

Reply

Marsh Posté le 24-05-2011 à 13:21:30    

Plusieurs remarques :
- il est inutile de mettre un ";" à chaque fin de ligne.
- tu peux faire référence au contenu de tes variables en préfixant simplement du caractère "$". Les accolades ou parenthèses ne sont pas utiles. Je ne maîtrise pas suffisamment bash, mais je ne sais pas si dans ton cas ça ne pourrait pas faire des choses inattendues. Donc $(h) et ${h} => $h
- j'ai du mal à comprendre la logique de redirection en entrée du fichier /dev/null. Tu veux faire quoi, au juste ?
- lorsque tu testes une variable non entière, il est d'usage d'encadrer ta variable et ta valeur testée avec des guillemets. ex : if [ "$resultping" -ne "0" -a "$state" -eq "1" ]; then
Comme ca, si ta variable 'resulting' n'est pas définie, le shell teste "" -ne "0", et il ne sort pas une erreur.

Reply

Marsh Posté le 24-05-2011 à 13:55:39    

Merci pour toutes ces précisions :p
 
Voilà ce que ca donne après les corrections :
 

Code :
  1. #!/bin/bash
  2. HOSTS="NOMDUPC"
  3. mailadmin="admine@domain.com"
  4. state=0
  5. datt=$(date)
  6. while [ 1 = 1 ]
  7. do
  8.         for h in $HOSTS;
  9.         do
  10.                 fping -t1000 $h > /dev/null
  11.                 resultping=$?
  12.                         if [ "$resultping" -ne "0" -a "$state" -eq "1" ]; then
  13.                                 echo $h host is down
  14.                                 (mail -s "$h down $datt" $mailadmin < /dev/null) > /dev/null
  15.                                 state=0
  16.                         elif [ "$resultping" -eq "0" -a "$state" -eq "0" ]; then
  17.                                 echo $h host is up
  18.                                 (mail -s "$h up $datt" $mailadmin < /dev/null) > /dev/null
  19.                                 state=1
  20.                         fi
  21.         done
  22.         sleep 10
  23. done


 
La redirection en entrée "< /dev/null" c'est pour dire a la fonction mail d'envoyer aucun corps au message, mais j'imagine qu'écrire un truc comme < echo "" serait revenu au même
 
la redirection en sortie c'est simplement que j'ai pas trouvé d'option pour que la fonction fasse son boulot silencieusement x) donc ça, ça évite que des trucs s'affichent pour rien dans la console.
 
Merci encore pour les corrections :D
 
 

Reply

Marsh Posté le 24-05-2011 à 14:02:30    

Maintenant j'aimerais bien pouvoir suivre plusieurs hôtes^^ (d'où le "for h in $HOSTS" ) mais il me faudrait plusieurs variables $state
 
j'avais déjà essayé d'assigner une variable pour chaque hôte du genre de ça :  
 

Code :
  1. for h in $HOSTS;
  2. do
  3. state_$h=0
  4. done
  5. echo "$state_ar-PO1595"


 
mais ca ne marche pas terrible x)
voilà la trace d'execution avec bash -x (ar-PO1595 c'est le nom du PC) :

Code :
  1. + for h in '$HOSTS'
  2. + state_ar-PO1595=0
  3. innaccessible2.bash: line 11: state_ar-PO1595=0: command not found
  4. + echo -PO1595
  5. -PO1595

Message cité 1 fois
Message édité par zownierd le 24-05-2011 à 14:06:46
Reply

Marsh Posté le 24-05-2011 à 14:30:49    

zownierd a écrit :


La redirection en entrée "< /dev/null" c'est pour dire a la fonction mail d'envoyer aucun corps au message, mais j'imagine qu'écrire un truc comme < echo "" serait revenu au même
 
la redirection en sortie c'est simplement que j'ai pas trouvé d'option pour que la fonction fasse son boulot silencieusement x) donc ça, ça évite que des trucs s'affichent pour rien dans la console.


 
En fait, ma remarque était plus une question. /dev/null est aussi connu sous le terme de "puits sans fond", et je le conceptualisais plutôt comme une grosse poubelle. Je n'ai jamais imaginé aller chercher des trucs dedans pour les donner à manger à un programme !  :D  
 

zownierd a écrit :

Maintenant j'aimerais bien pouvoir suivre plusieurs hôtes^^ (d'où le "for h in $HOSTS" ) mais il me faudrait plusieurs variables $state
 
j'avais déjà essayé d'assigner une variable pour chaque hôte du genre de ça :  
 

Code :
  1. for h in $HOSTS;
  2. do
  3. state_$h=0
  4. done
  5. echo "$state_ar-PO1595"


 
mais ca ne marche pas terrible x)
voilà la trace d'execution avec bash -x (ar-PO1595 c'est le nom du PC) :

Code :
  1. + for h in '$HOSTS'
  2. + state_ar-PO1595=0
  3. innaccessible2.bash: line 11: state_ar-PO1595=0: command not found
  4. + echo -PO1595
  5. -PO1595



 
En tout début de boucle, tu devrais vérifier le contenu de h avec une commande 'echo "*$h*", juste pour voir s'il n'y aurait pas d'espace à la fin, ce qui rendrait l'affectation impossible.
Cela dit, je ne sais pas si on peut créer des variables à la volée comme ca.  
 
Tu peux essayer d'utiliser des variables "tableau", si cela répond à ton besoin ?
Ca s'utilise comme ca :

Code :
  1. # Pour l'affectation
  2. ma_variable[0]=ma_valeur1
  3. ma_variable[1]=ma_valeur2
  4. #Pour l'utilisation
  5. echo "ma_variable[0] = ${ma_variable[0]}"
  6. echo "ma_variable[1] = ${ma_variable[1]}"

Reply

Marsh Posté le 24-05-2011 à 14:46:21    

shaoyin a écrit :


 
En fait, ma remarque était plus une question. /dev/null est aussi connu sous le terme de "puits sans fond", et je le conceptualisais plutôt comme une grosse poubelle. Je n'ai jamais imaginé aller chercher des trucs dedans pour les donner à manger à un programme !  :D  
 


 
Lol, et bien si tu as une alternative je suis preneur ^^ ça ressemble en effet pas mal à du bidouillage mais ça marche pas trop mal ^^

Reply

Marsh Posté le 24-05-2011 à 14:58:37    

Bidouillage, je n'en suis pas certain. On n'est souvent limité que par son imagination. Toutes les docs que j'aie lu sur /dev/null en parlaient en tant que "trou noir", donc uniquement pour les redirections de sortie.
 
Maintenant, c'est vrai que je n'ai jamais pensé qu'on pouvait peut-être l'utiliser dans l'autre sens. Reste à savoir ce que cela fait exactement.
 
EDIT : Ah si ! Sur le site de Wikipedia (anglais), il est dit que ce fichier ne fournit aucune donnée aux processus qui le lisent (envoi de EOF immédiatement). Je vais me coucher moins bête ce soir... Donc ca confirme que ce n'est pas du bidouillage...


Message édité par shaoyin le 24-05-2011 à 15:01:06
Reply

Marsh Posté le 24-05-2011 à 15:14:28    

Il semblerait que ça fonctionne bien, je n'ai aucune erreur ^^
merci pour l'idée des tableaux, je cherchais bien compliqué^^ :p
 

Code :
  1. #!/bin/bash
  2. HOSTS="ar-PO1595 ar-UC2038"
  3. mailadmin="admin@domain.com"
  4. i=0
  5. for h in $HOSTS
  6. do
  7.         state[$i]=1
  8.         i=$i+1
  9. done
  10. i=0
  11. datt=$(date)
  12. while [ 1 = 1 ]
  13. do
  14.         i=0
  15.         for h in $HOSTS;
  16.         do
  17.                 fping -t2000 $h > /dev/null
  18.                 resultping=$?
  19.                         if [ "$resultping" -ne "0" -a "${state[i]}" -eq "1" ];
  20.                         then
  21.                                 echo $h host is down
  22.                                 (mail -s "$h down $datt" $mailadmin < /dev/null)  > /dev/null
  23.                                 state[i]=0
  24.                         elif [ "$resultping" -eq "0" -a "${state[i]}" -eq "0" ];
  25.                         then
  26.                                 echo $h host is up
  27.                                 (mail -s "$h up $datt" $mailadmin < /dev/null)  > /dev/null
  28.                                 state[i]=1
  29.                         fi
  30.         done
  31.         sleep 10
  32. done


 
EDIT : ET NON x) ça marche toujours pas complètement ^^
REedit : corrections apportées ca a l'air ok ^^


Message édité par zownierd le 24-05-2011 à 15:29:43
Reply

Marsh Posté le 24-05-2011 à 15:14:28   

Reply

Marsh Posté le 26-05-2011 à 09:25:31    

petit problème, la date ne s'affiche plus x)  
j'ai bien un mail qui me donne "ar-PO1595 up" mais plus ce que je devrais avoir :  
"ar-PO1595 up mardi 24 mai 2011, 15:24:51 (UTC+0200)"
je vois pas le problème x)

Reply

Marsh Posté le 26-05-2011 à 16:00:43    

Peut être un problème de porté, essaye çà :

Code :
  1. export datt=$(date)

Reply

Marsh Posté le 27-05-2011 à 14:18:19    

le problème n'était pas dans le programme du dessus x) j'ai simplement bêtement écrit $date au lieu de $(date) dans des bidouillages que j'ai fait x)
le programme du dessous marche très bien :p
 
 
 
 
#!/bin/bash
 
############################
#### By XXXXXXXXXXXXXXXXXXXX !!!####
############################
 
HOSTS="NOMDUPC1 NOMDUPC2"
mailadmin="admin@domain.com"
i=0
 
for h in $HOSTS
do
        state[$i]=1
        i=$i+1
done
i=0
 
while [ 1 = 1 ]
do
        datt=$(date)
        minidatt=$(date +%d/%m/%Y,%T)
        i=0
        for h in $HOSTS;
        do
                fping -q -t2000 $h > /dev/null
                resultping=$?
                        if [ "$resultping" -ne "0" -a "${state[i]}" -eq "1" ]; then
                                echo "$h : host is down ($minidatt)"
                                echo "L hote $h passe down le $datt" | (mail -s "$h down $minidatt" $mailadmin) > /dev/null
                                state[i]=0
                        elif [ "$resultping" -eq "0" -a "${state[i]}" -eq "0" ]; then
                                echo "$h : host is up ($minidatt)"
                                echo "L hote $h passe up le $datt" | (mail -s "$h up $minidatt" $mailadmin) > /dev/null
                                state[i]=1
                        fi
        i=$i+1
        done
        sleep 10
done
 
 
 

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed