[Bash - Shell] Script qui se lance tant que la condition est pas valid

Script qui se lance tant que la condition est pas valid [Bash - Shell] - Codes et scripts - Linux et OS Alternatifs

Marsh Posté le 25-09-2014 à 12:14:27    

Bonjour,
 
J'ai fait un script de traitement que je voudrais automatiser.
 
Grosso modo mon script télécharge 4 fichier avec WGET (qui filtre uniquement ce qu'il a besoin via une date).
 
Sauf que je voudrais le lancer de façon automatique, mais je voudrais émettre une condition qui me permettrais que si un fichier est manquant, il fait une pause pendant 30 minutes puis re télécharge et test si les fichires sont la.
 
Si ils sont la, il execute sinon il va refaire une pause de 30 minutes et recommencer.
 
Donc on va dire que mon code est de type :
 

Code :
  1. wget -r http://...............
  2. if [ -f lefichier ]   // on peut cumuler cela sur plusieurs fichier et en le construisant avec une variable ?
  3. then
  4.    // Tous les fichier existes, je fait mon traitement
  5. else 
  6.    // Il manque une fichier, on fait une pause de 30 minutes et on recommence
  7. fi


 
Voilà ce que je voudrais faire. Une fois compris le principe, je ferais en sorte de ne télécharger que les fichiers manquant et non pas de re télécharger tout.


---------------
Recette cookeo Recette de cuisine
Reply

Marsh Posté le 25-09-2014 à 12:14:27   

Reply

Marsh Posté le 25-09-2014 à 19:19:16    

pourquoi ne pas alors lancer ton script toutes les 30 minutes ? (crontab)
 
if [ -f fichier ] sur plusieurs fichiers
 
soit tu fait un switch case... au lieu d'un if
 
soit tu fais les 4 if.....
 
soit selon le nommage des fichier tu utilises une REGEXP qui repressente les 4noms possibles des fichier... tu mets ça dans une variable par exemple ou un fichier  qui sert alors de liste pour wget ...
 
genre

Code :
  1. ....
  2. while read
  3. do
  4. wget ${REPLY}
  5. done < /tmp/liste_de_fichier.txt
  6. ....


 
comme ça que ta liste générée trouve 1 ou 1000 fichiers peut importe (dans la limite des 30 minutes de telechargement total bien sur !sinon faut augmenter le delai entre deux itérations du script, ou mieux ajouter un test au début du script qui regarde si y'en a pas déjà un qui est pas fini auquel cas il quitte pour le laisser finir)....il chargra 1 par 1 (à la fois) chaque fichiers de la liste...
 
exemple  

Code :
  1. $ cd /tmp             
  2. $ mkdir test           
  3. $ touch test/{toto,titi,tutu,tata}
  4. $ cat > liste   # ca ton script devra donc le faire lui meme hein !!!
  5. toto
  6. titi
  7. tutu
  8. $ while read
  9. > do
  10. > rm test/$REPLY
  11. > done < liste
  12. $ ls -l test/
  13. total 0
  14. -rw-r--r--  1 francois  wheel  0 Sep 25 19:18 tata
  15. $ # il reste bien plus que tata
  16. $ rm -rf test liste                                                                                                                                                                   
  17. $


Message édité par goblin_rieur le 25-09-2014 à 19:36:46

---------------
Collectionner les vieux serveurs c'est chouette mais c'est lourd et ça prend de la place ;)
Reply

Marsh Posté le 25-09-2014 à 19:50:28    

Ok Je vois ce que tu veux dire, déjà merci.
 
En fait les fichiers sont envoyer, un par un et entre le premier et le second il est possible que cela prenne du temps (2 h environ).  
 
Donc je sais pas trop comment faire pour aller chercher les fichiers des qu'ils sont la (ça je sais suffit de regarde quelle fichier est pas la ou de faire avec l'option mirroir) par contre il faut aussi lui dire, que si les fichiers ont déjà été télécharger il ne les reprend pas même si il n'y sont plus.


---------------
Recette cookeo Recette de cuisine
Reply

Marsh Posté le 25-09-2014 à 19:52:55    

De toute façon avant ça, j'ai la function de mise a jour de table SQL qui a une méthode par défault qui est pas top et longue. Et qui au passage sature le disque de mon serveur a un moment :/
 
Je me vois pas lancer un script de DL pendant 2h et de traitement > a 12h tous les jours, aucun intérêt les traitement seront pas fini :/


---------------
Recette cookeo Recette de cuisine
Reply

Marsh Posté le 25-09-2014 à 19:59:07    

alors pourquoii utiliser un system à la rsync -zauv qui fait le différentiel entre deux volumes (y compris distants)  
 
copie différentielle quoi  
 
 

Code :
  1. # mkdir /tmp/toto ; touch /tmp/toto/{titi,tutu,toto}
  2. # mkdir /tmp/tutu
  3. # cd /tmp/tutu
  4. # rsync -auv /tmp/toto .
  5. sending incremental file list
  6. toto/
  7. toto/titi
  8. toto/toto
  9. toto/tutu
  10. sent 226 bytes  received 77 bytes  606.00 bytes/sec
  11. total size is 0  speedup is 0.00
  12. # touch /tmp/toto/{dfsdf,sdf}      # pour creer des differences ...               
  13. # rsync -auv /tmp/toto .      # ca va copier que les deux nouveaux ficheirs
  14. sending incremental file list
  15. toto/
  16. toto/dfsdf
  17. toto/sdf
  18. sent 227 bytes  received 58 bytes  570.00 bytes/sec
  19. total size is 0  speedup is 0.00
  20. # rm -rf /tmp/t[oi]t[oi]
  21. #


 
 
 
en réseau la commande rsync ressemblera donc à  
 
rsync -zuav user@host:/chemin/regexp_selection_fichiers /chemin/local/
 
:hello:


Message édité par goblin_rieur le 25-09-2014 à 20:00:53

---------------
Collectionner les vieux serveurs c'est chouette mais c'est lourd et ça prend de la place ;)
Reply

Marsh Posté le 25-09-2014 à 20:00:53    

Ça marche même si en face c'est une simple visualisation de répertoire  ?  
 
Normalement le rsync impose un serveur rsync en face non ? Car la je suis pas maître du serveur en face.


---------------
Recette cookeo Recette de cuisine
Reply

Marsh Posté le 25-09-2014 à 20:10:09    

oui il faut que ton partenaire/contact l'ai installé  
 
sinon si c'est du webfile il faut jouer comme indiqué au dessus avec un script et du wget...
 
et la solution et que donc ton script fasse :
1. liste les fichiers disponibles,  
2. avec les dates/noms de fichiers fasse une liste, ATTENTION à ta selection c'est à ce niveau que ca va optimiser le plus sur la selection la plus fine possible
3. differencie et expulse de la liste ce qui existe déjà localement (petit sed par exemple pour virer les lignes concernées) précaussion, qui n'est pas inutile  
4. si N sessions Wget existent déjà les virer de la liste
5. lancer les suivants  si la bande passante n'est pas déjà saturée ... un teste de plus à ajouter......(tjrs en tache de fond et faible priorité bien sur...)  
6. archive les listes (ça c'est pour pouvoir gerer les reprises de listes en cas de crash, reboot, etc...)
7. purge les listtes de plus de 15 jours par exemple.


Message édité par goblin_rieur le 25-09-2014 à 20:12:15

---------------
Collectionner les vieux serveurs c'est chouette mais c'est lourd et ça prend de la place ;)
Reply

Marsh Posté le 25-09-2014 à 20:12:56    

Ok je vois ce que tu veux dire. Je m'y penche dès que j'ai résolu mon soucis de script python :/
 
Il créer une table qu'il insère les nouveaux éléments, migre l'ancienne table en ignorant ce qui existe déjà, et enlève puis renomme la table.
 
je suis pas convaincu que ce soit le plus efficace, un INSERT ON DUPLICATE REPLACE aurait été plus judicieux je trouve :/
 
Edit : c'est le script fourni qui fait de base ça, c'est pas moi qui lui ai dit de procéder comme ça, je trouve ça illogique au possible.


Message édité par ionik le 25-09-2014 à 20:13:37

---------------
Recette cookeo Recette de cuisine
Reply

Marsh Posté le 26-09-2014 à 10:56:10    

Salut,
 
j'ai déjà eu ce genre de pb il y a quelque temps (plusieurs centaines de logs avec un certain timestamp à récupérer sur des dizaines de serveurs). Tu peux essayer ça pour tes wget (bon c'est overkill si tu n'en as que 4) :

Code :
  1. #!/bin/sh
  2. WORKDIR="work"
  3. LOG="/tmp/getfiles.log"
  4. LIST="/tmp/filelist"
  5. create_list()
  6. {
  7.         s=1
  8.         while [ ${s} -le 10 ]
  9.         do
  10.                 if [ ! -f ${WORKDIR}/file${s} ]
  11.                 then
  12.                         echo "file${s}" >> ${LIST}
  13.                 fi
  14.                 ((s=s+1))
  15.         done
  16. }
  17. do_wget()
  18. {
  19.         wget -P ${WORKDIR} $1
  20.         # touch ${WORKDIR}/$1
  21.         [ $? -ne 0 ] && echo FAILED > ${LOG}
  22. }
  23. fork_wget()
  24. {
  25.         for file in `cat ${LIST}`
  26.         do
  27.                 nb=`ps -C wget -o cmd=|wc -l`
  28.                 if [ $nb -gt 2 ]
  29.                 then
  30.                         sleep 10
  31.                 else
  32.                         do_wget $file &
  33.                 fi
  34.         done
  35.         nb=`ps -C wget -o cmd=|wc -l`
  36.         while [ ${nb} -gt 0 ]
  37.         do
  38.                 sleep 30
  39.                 nb=`ps -C wget -o cmd=|wc -l`
  40.         done
  41. }
  42. main()
  43. {
  44.         this=`basename $0`
  45.         running=`ps -C ${this} -o cmd=|wc -l`
  46.         [ ${running} -gt 2 ] && exit 0
  47.         succeed="no"
  48.         while [ "${succeed}" != "yes" ]
  49.         do
  50.                 > ${LOG}
  51.                 > ${LIST}
  52.                 create_list
  53.                 fork_wget
  54.                 grep -q FAILED ${LOG}
  55.                 if [ $? != 0 ]
  56.                 then
  57.                          succeed="yes"
  58.                 else
  59.                         sleep 300 # 5 mn
  60.                 fi
  61.         done
  62. }
  63. main &


 
Bon, ça n'est qu'un squelette et tu mets ce que tu veux dans create_list().
 
Le script ne se termine que quand tu as récupéré tous tes fichiers, et il est protégé contre une double execution...


Message édité par imarune le 26-09-2014 à 11:05:45
Reply

Marsh Posté le 26-09-2014 à 11:10:21    

Rho merci beaucoup, je vais regarder ça !


---------------
Recette cookeo Recette de cuisine
Reply

Marsh Posté le 26-09-2014 à 11:10:21   

Reply

Marsh Posté le 26-09-2014 à 12:27:52    

Tu peux également rajouter un timer (qui termine le script au bout de 3h, par ex) et ton traitement sur les fichiers (fonction appelée depuis main()) dans le script ...

Reply

Marsh Posté le 26-09-2014 à 16:13:22    

[:xx_xx] ce thread


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 26-09-2014 à 17:02:33    

Reply

Marsh Posté le 26-09-2014 à 17:56:11    

Ou sinon tu peux utiliser inotify [:prodigy]


---------------
Wedge#2487 @HS -#- PW: +∞ -#- Khaz-Modan/Boltiz @WoW
Reply

Marsh Posté le 26-09-2014 à 19:43:47    

wedgeant a écrit :

Ou sinon tu peux utiliser inotify [:prodigy]


 
sans tomber dans des features linux only, on peut quand meme faire bien mieux....
 

ionik a écrit :

Un truc de mal ?


 
de "mal" non, mais j'ai un peu mal quand je vois la teneur des réponses, ça va des réponses à coté de la plaque (changer de protocole) à une usine à gaz
un des premiers principes unix c'est KISS : Keep It Simple Stupid
 
quand on prend ton premier bout de code, ta demande c'est de ne pas le redownloader : ben il suffit de décaler le test  
 

Code :
  1. if [ ! -f lefichier ]   // on peut cumuler cela sur plusieurs fichier et en le construisant avec une variable ?
  2. then
  3.    wget -r http://............... -O lefichier
  4. fi


 
la condition peut etre étendue, je te laisse voir comment faire. ou utiliser une boucle. tout simplement
 
et ne loope pas comme ça, ça rend ton script mal aisé à utiliser de façon standalone : si un jour ton "partenaire" te dit "y'a eu un soucis, on a mis à jour" tu as plus qu'à relancer ton script une fois et zou. les boucles à base de sleep dans les scripts c'est en règle générale une mauvaise idée.
 
pour ton SQL, si toutes tes données sont changées, et que tu downloades un fichier sql, alors un alter table pour la renommer avec un timestamp + copy te permettra d'aller plus vite (copy est en général optimisé) et d'avoir un fallback (genre le copy echoue, tu as toujours tes donnees de la veille)
 
et si tu ne connais pas l'heure exacte, avec ce systeme tu peux lancer plusieurs fois dans la nuit ton traitement, c'est facile de setter un marqueur en cas d'echec repete : par exemple si les fichiers arrivent trop tard (ou pas du tout)
 
bref : rendre les choses robustes sans en faire une usine à gaz
 
pour imarune, vite fait :
 

Code :
  1. do_wget()
  2. {
  3.         wget -P ${WORKDIR} $1
  4.         # touch ${WORKDIR}/$1
  5.         [ $? -ne 0 ] && echo FAILED > ${LOG}
  6. }


 
c'est très ballot d'ecraser le ficher, et cette fonction est useless, comme dit plus bas

Code :
  1. create_list()
  2. {
  3.         s=1
  4.         while [ ${s} -le 10 ]
  5.         do
  6.                 if [ ! -f ${WORKDIR}/file${s} ]
  7.                 then
  8.                         echo "file${s}" >> ${LIST}
  9.                 fi
  10.                 ((s=s+1))
  11.         done
  12. }


 
man seq pour la boucle (ou jot en BSD)
 

Code :
  1. main()
  2. {
  3.         this=`basename $0`
  4.         running=`ps -C ${this} -o cmd=|wc -l`
  5.         [ ${running} -gt 2 ] && exit 0


 
man flock, ça c'est une façon on ne peut plus mauvaise de tester...
 

Code :
  1. succeed="no"
  2.         while [ "${succeed}" != "yes" ]
  3.         do


 
 [:pingouino]  
 

Code :
  1. > ${LOG}
  2.                 > ${LIST}


 
man touch.....
 

Code :
  1. create_list
  2.                 fork_wget


 
l'interet de la fonction est nul, il pose meme probleme
 

Code :
  1. grep -q FAILED ${LOG}


 
et si wget meurt sans logger ? ha ben c'est plus bon. dommage, tu considères que si....
 

Code :
  1. if [ $? != 0 ]
  2.                 then
  3.                          succeed="yes"
  4.                 else
  5.                         sleep 300 # 5 mn
  6.                 fi
  7.         done
  8. }
  9. main &


 
pour goblin rieur :
 

Citation :


oui il faut que ton partenaire/contact l'ai installé  
 
sinon si c'est du webfile il faut jouer comme indiqué au dessus avec un script et du wget...  
 
et la solution et que donc ton script fasse :  
1. liste les fichiers disponibles,  
2. avec les dates/noms de fichiers fasse une liste, ATTENTION à ta selection c'est à ce niveau que ca va optimiser le plus sur la selection la plus fine possible  
3. differencie et expulse de la liste ce qui existe déjà localement (petit sed par exemple pour virer les lignes concernées) précaussion, qui n'est pas inutile  
4. si N sessions Wget existent déjà les virer de la liste  
5. lancer les suivants  si la bande passante n'est pas déjà saturée ... un teste de plus à ajouter......(tjrs en tache de fond et faible priorité bien sur...)  
6. archive les listes (ça c'est pour pouvoir gerer les reprises de listes en cas de crash, reboot, etc...)  
7. purge les listtes de plus de 15 jours par exemple.


 
à part les points 3 et 6, qui sont biens le reste c'est  [:tartragnan]


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 26-09-2014 à 22:52:53    

black_lord » man touch, man touch ... touch ne permet pas de vider les fichiers sans changer l'inode :o


---------------
"Mieux vaut demander à un qui sait plutôt qu'à deux qui cherchent." ... "Le plus dur, c'est de faire simple.", TNZ
Reply

Marsh Posté le 26-09-2014 à 22:53:15    

pour Blacklord vite fait: il me semble que tu considères tes capacités bien au dessus de ce qu'elles doivent être réellement  :D  
 
man humblitude  :o  (à la ségolène)
 
PS: il me semblait avoir préciser que c'était un squelette (pas un truc über proof)
 
re PS : je ne comprends pas trop non  plus ce qui te choque dans les quelques lignes que j'ai eu l'audace de commettre; pas optimisé, c'est sûr... Mais bon: aurais tu la bonté de corriger ce shell et de soumettre ta version à l'OP ? Ou de lui proposer une solution encore plus mieux ? (si tu en es capable bien sûr)
 
re re PS : je vois modérateur en dessous de ton alias : c'est probablement une blague ?
 
Edit: de plus j'ai dit "Tu peux essayer ça pour tes wget (bon c'est overkill si tu n'en as que 4)"; donc ta réflexion sur l'usine à gaz...
 
re edit : je n'en reviens pas de la lecture en travers :

Citation :


pour imarune, vite fait :
 
Code :
 
    do_wget()
    {
            wget -P ${WORKDIR} $1
            # touch ${WORKDIR}/$1
            [ $? -ne 0 ] && echo FAILED > ${LOG}
    }
 
 
c'est très ballot d'ecraser le ficher, et cette fonction est useless, comme dit plus bas  
 


 
on remarque bien un "#" devant le touch: pour info, cette ligne a servi à tester la syntaxe du script ... (et touch n''écrase rien, comme l'a dit TNZ)
 
wget meurt et ne log rien ? pas grave, on ne récupère pas l'output de wget, juste son code retour...
 
Par contre, merci pour flock (que je n'ai jamais utilisé sur un démon shell), je regarde de plus près.
 
Ah, dernière chose: si tu ne vois pas l'intérêt de paralléliser les récupérations de fichiers (fork wget), moi j'en vois un, même si il y a peu de fichiers (2h pour un des fichiers, beaucoup  moins pour les autres)

Message cité 2 fois
Message édité par imarune le 27-09-2014 à 00:02:44
Reply

Marsh Posté le 27-09-2014 à 19:32:45    

TNZ a écrit :

black_lord » man touch, man touch ... touch ne permet pas de vider les fichiers sans changer l'inode :o


 
l'idée c'est justement de ne pas effacer le fichier; mais soit de s'arreter, soit de gérer l'erreur (l'arret etant une des façons de le faire), cf plus bas
 

imarune a écrit :

pour Blacklord vite fait: il me semble que tu considères tes capacités bien au dessus de ce qu'elles doivent être réellement  :D  


 
surement :o
 

imarune a écrit :


PS: il me semblait avoir préciser que c'était un squelette (pas un truc über proof)


 
indeed, my bad
 

imarune a écrit :


re re PS : je vois modérateur en dessous de ton alias : c'est probablement une blague ?


 
surement :D
 

imarune a écrit :


on remarque bien un "#" devant le touch: pour info, cette ligne a servi à tester la syntaxe du script ... (et touch n''écrase rien, comme l'a dit TNZ)


 
cf plus haut, et plus bas
 

imarune a écrit :


wget meurt et ne log rien ? pas grave, on ne récupère pas l'output de wget, juste son code retour...


 
en effet; your point
 

imarune a écrit :


Par contre, merci pour flock (que je n'ai jamais utilisé sur un démon shell), je regarde de plus près.


 
:jap:
 

imarune a écrit :


Ah, dernière chose: si tu ne vois pas l'intérêt de paralléliser les récupérations de fichiers (fork wget), moi j'en vois un, même si il y a peu de fichiers (2h pour un des fichiers, beaucoup  moins pour les autres)


 
je vois bien l'interet de paralleliser les choses, ne t'inquiètes pas pour moi.
A noter que la façon dont tu le fais est propice à la race condition : si fichier2 échoue pendant que fichier1 se fait, alors le test de fichier1 sera considéré comme échoué (parce que fichier de "log" qui est le meme pour tous°


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 29-09-2014 à 08:37:01    

black_lord a écrit :


A noter que la façon dont tu le fais est propice à la race condition : si fichier2 échoue pendant que fichier1 se fait, alors le test de fichier1 sera considéré comme échoué (parce que fichier de "log" qui est le meme pour tous°


 
Désolé, mais je ne vois pas de race condition.
 
1) on vide LOG (que j'aurai du appeler FLAG) et LIST
2) on alimente la liste des fichiers à récupérer en écartant ceux déjà présents en local et en testant leur validité (taille # 0, présence d'une balise html final pour un web file, etc...)
3) on lance un wget sur chacun de ces fichiers (en parallèle), et on attend la fin de tous les wget. Si l'un 2 échoue, on met FAILED dans LOG (FLAG)
4) on teste FAILED, Si un (ou plusieurs) des fichiers n'est pas récupéré, on reboucle sur 1) (les fichiers récupérés avec succès seront écartés de la liste des fichiers à relancer)
 
PS : je reconnais que create_list prête à confusion (son contenu a servi à tester la syntaxe des fonctions); il est bien évident que c'est là qu'on doit vérifier la validité des fichiers récupérés...
 

Reply

Marsh Posté le 29-09-2014 à 10:12:21    

imarune a écrit :

re re PS : je vois modérateur en dessous de ton alias : c'est probablement une blague ?


On essaye de lui expliquer depuis des années, mais il veut pas comprendre [:elessar53]


Message édité par wedgeant le 29-09-2014 à 10:12:30

---------------
Wedge#2487 @HS -#- PW: +∞ -#- Khaz-Modan/Boltiz @WoW
Reply

Marsh Posté le 29-09-2014 à 19:27:19    

[quotemsg=1365305,20,456680]
 
 
Edit : auto modération  :) Effectivement, mon post était assez moyen...
 


Message édité par imarune le 30-09-2014 à 09:54:38
Reply

Marsh Posté le 29-09-2014 à 19:32:01    

Heu, dans le cas présent, on s'en fout qu'il soit modérateur ou pas, il contribue simplement au topic comme n'importe quel membre de ce forum.
Merci donc de rester dans la thématique du topic.

 

edit: /oggy


Message édité par o'gure le 29-09-2014 à 19:38:13
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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