Pages : 1
#1 Le 25/04/2007, à 09:06
- Daëavelwyn
[RESOLU] BASH : problème de boucle
Bonjour,
alors voilà, je me suis coder un petit truc en bash qui log l'activité d'un system et qui renvoi le resultat dans un mail et aussi dans un fichier daté. J'arrive a un ensemble de fonctionalité qui larche bien. Il y a dans mon script une sorte de mode de configuration, qui pose des questions sur ce que je veux mettre dans le rapport
par exemple
dreport-setting -C --mail
me demande de configurer les adresses mails ou je veux recevoir le rapport
dreport-setting -C --uptime
me demande si je veux afficher l'uptime du system dans le rapport, etc...
chacune de des options fait appel à une fonction. et mon pb, c'est que si je fais :
dreport-setting -C --all
dans mon script, cette option doit exécuter toutes les fonctions les unes a la suite des autres, or n'est exécuté que la première fonction.
à force de chercher j'ai fini par trouver d'ou venait le pb, il s'agit d'une boucle while qui se trouve dans chaque function et qui permet de reposer la question si l'utilisateur a entré une mauvaise réponse.
Visiblement, lorsque j'enleve cette boucle, l'option --all fonctionne bien, mais lorsqu'une mauvaise reponse est entrée, et bien la question n'est pas reposé, et le script passe a la question suivante...
voici un extrait de la fonction mail et de la fonction uptime :
echo "$SET_MSG_MAIL_ADDRESSA"
read MainMailAddress
CurrentMainMailAddress=`strings $CONFIG_SCRIPT_NAME | grep "ADDRESSA="`
sed -i s/$CurrentMainMailAddress/"OPT_MAIL_ADDRESSA="$MainMailAddress""/ $CONFIG_SCRIPT_NAME
echo ""
echo "$SET_MSG_MAIL_ADDRESSCC"
read CcMailAddress
CurrentCcMailAddress=`cat $CONFIG_SCRIPT_NAME | grep "ADDRESSCC="`
sed -i s/"$CurrentCcMailAddress"/"OPT_MAIL_ADDRESSCC="$CcMailAddress/ $CONFIG_SCRIPT_NAME
echo ""
echo "$SET_MSG_MAIL_ADDRESSBCC"
read BccMailAddress
CurrentBccMailAddress=`cat $CONFIG_SCRIPT_NAME | grep "ADDRESSBCC="`
sed -i s/"$CurrentBccMailAddress"/"OPT_MAIL_ADDRESSBCC="$BccMailAddress/ $CONFIG_SCRIPT_NAME
echo ""
while [ "$error" != "false" ]
do
echo "$SET_MSG_BACKUP_SEND_REPORT"
read BackupSendReport
CurrentBackupSendReport=`cat $MAIN_SCRIPT_NAME | grep "SendReportByMail"`
case "$BackupSendReport" in
$SET_INPUT_MAIL )
sed -i s/"$CurrentBackupSendReport"/'SendReportByMail'/ $MAIN_SCRIPT_NAME
rm -f "*$OPT_REPORT_FILE_NAME" # only send report by mail, so delete the tmp file
error="false"
;;
$SET_INPUT_FILE )
sed -i s/"$CurrentBackupSendReport"/'#SendReportByMail'/ $MAIN_SCRIPT_NAME
CurrentDate=`date +%d-%m-%Y`
if [ -f $OPT_REPORT_FILE_NAME ];then #if file doesn't exist we need to create it
mv $OPT_REPORT_FILE_NAME $CurrentDate$OPT_REPORT_FILE_NAME #add the current date in the file name
else echo "** report file generated **" > $OPT_REPORT_FILE_NAME
fi
error="false"
;;
$SET_INPUT_BOTH )
sed -i s/"$CurrentBackupSendReport"/'SendReportByMail'/ $MAIN_SCRIPT_NAME
CurrentDate=`date +%d-%m-%Y`
if [ -f $OPT_REPORT_FILE_NAME ];then #if file doesn't exist we need to create it
mv $OPT_REPORT_FILE_NAME $CurrentDate$OPT_REPORT_FILE_NAME #add the current date in the file name
else echo "** report file generated **" > $OPT_REPORT_FILE_NAME
fi
error="false"
;;
* )echo "$SET_MSG_ERROR_BACKUP_SEND_REPORT";;
esac
done
while [ "$error" != "false" ]
do
echo "$SET_MSG_UPTIME"
read ServerUptime
CurrentServerUptime=`cat $MAIN_SCRIPT_NAME | grep "ShowUptime"`
case "$ServerUptime" in
$SET_INPUT_YES ) sed -i s/"$CurrentServerUptime"/'ShowUptime'/ $MAIN_SCRIPT_NAME; error="false";;
$SET_INPUT_NO ) sed -i s/"$CurrentServerUptime"/'#ShowUptime'/ $MAIN_SCRIPT_NAME; error="false";;
* )echo "$SET_MSG_ERROR";;
esac
done
si j'enleve la boucle while, ça fonctionne. sinon, il n'y a que la premiere boucle qui est lu
Je pense que c'est parceque j'ai mal géré le type de boucle et la logique du retour d'erreur, mais je n'arrive pas a trouver la bonne logique...
si quelqu'un avait un bon tuto ou un peu de temps pour m'aider, merci ^^
Eventuellement, je peux aussi filer l'intégralité du programme, tte façon il est sous gpl v2 donc bon
Dernière modification par Daëavelwyn (Le 24/05/2007, à 00:08)
La connaissance est le droit de tous, et le devoir de chacun.
Hors ligne
#2 Le 25/04/2007, à 09:45
- kaworu
Re : [RESOLU] BASH : problème de boucle
Salut !
Je pense que c'est un problème de portée de variable. En bash, toutes les variables sont visible/modifiable depuis partout (sauf dans une fonction si déclarée avec local myvar="blablabla") !
Ainsi quand tu sors de la première boucle c'est parce que "$error" == "false" , mais à ce moment, $error est toujours initialisée et a toujours la même valeur !
Donc comme la condition d'entrée dans la 2ème boucle est la même que la première ( "$error" != "false" ) et que l'on a "$error" == "false" alors on rentre pas dans la boucle !
Une solution serait de prendre un autre nom de variable, mais ce que je ferai c'est à chaque fin de boucle :
unset error
de cette manière tu réinitialise la variable $error et tu peux la réutiliser pour les boucles suivante (à condition de faire le unset à chaques fin de boucle )
EDIT : la bible du Bash (traduite en français !) => http://abs.traduc.org/
Bonne continuation.
EDIT2 : Aïe ! Un chat mort ! Tu peux aussi remplacer ceci (si tu veux) :
cat $fichier | grep $motif
par
grep $motif $fichier
c'est plus clair, et ça ne fais pas un "Useless Use of Cat". C'est très courant de voir un cat machin | grep chose alors que souvent grep suffit. Certains on trouvé que c'est tellement courant qu'il y a un "Useless Use of Cat Awards" où la plus inutile utilisation de cat est récompensée chaque années (sisi..). Voir ici :
http://partmaps.org/era/unix/award.html
Dernière modification par kaworu (Le 25/04/2007, à 09:52)
"There are in order of increasing severity: lies, damn lies, statistics, and computer benchmarks."
Hors ligne
#3 Le 25/04/2007, à 10:04
- Daëavelwyn
Re : [RESOLU] BASH : problème de boucle
ok, super, mais en fait, je ne trouve pas ma solution très élégante devoir donner un code erreur (error="false") à chaque fin de test me semble un peu lourd. Donc je me penche sur une autre solution qui serait de ne reposer la question que en cas d'erreur (et donc seulement si error="true") . Donc je vois bien que je dois mettre error="true" là :
* )echo "$SET_MSG_ERROR_BACKUP_SEND_REPORT";;
pour avoir
* )echo "$SET_MSG_ERROR_BACKUP_SEND_REPORT";error="true";;
mais je ne vois pas comment tourner mon code pour que la question soi reposer si error="true" ....
j'en viens a me dire que c'est la structure complète de ma fonction qui est a revoir ....
Merci pour le guide bash, je vais potasser
La connaissance est le droit de tous, et le devoir de chacun.
Hors ligne
#4 Le 25/04/2007, à 10:19
- kaworu
Re : [RESOLU] BASH : problème de boucle
Salut !
si tu veux que ça continue tant que "$error" == "true" il faut mettre dans la condition de test pour la boucle :
while [ "$error" = "true" ]; do [...] done
Une autre solution par exemple :
while true; do
[...]
case $var in
a) [...] break ;;
b) [...] break ;;
c) [...] continue ;;
done
avec break on sort de la boucle, avec continue (ou rien du tout) on reste dedans. ça t'évite de devoir mettre une variable.
Dernière modification par kaworu (Le 25/04/2007, à 10:20)
"There are in order of increasing severity: lies, damn lies, statistics, and computer benchmarks."
Hors ligne
#5 Le 25/04/2007, à 10:39
- Daëavelwyn
Re : [RESOLU] BASH : problème de boucle
wwwwwèèèèèèèèè
Marvellous kaworu !!! C'est exactement ça que je cherchais !!!
Je te remercie vraiment, tu m'évite un mal de tête certain !!
ça et dirait de tester mon script une fois que j'aurais fini ??
La connaissance est le droit de tous, et le devoir de chacun.
Hors ligne
#6 Le 26/04/2007, à 18:08
- kaworu
Re : [RESOLU] BASH : problème de boucle
pourquoi pas ^^
n'hésite pas si tu as encore besoin d'aide
"There are in order of increasing severity: lies, damn lies, statistics, and computer benchmarks."
Hors ligne