dans un script je fais tourner en parallèle plusieurs commandes.
Je reprend la main après un wait.
Ma question, comment savoir que l'ensemble (ou chacune) de mes commandes s'est bien déroulée?
$? ne me donne le statut de sortie que de la dernière.
Et quand j'essais de les mettre dans des accolades, le shell me dit que le ; n'est pas attendu...
Mon script actuel:
#!/bin/ksh
commande1 "$var1" SUPERIEUR fichier1 &
commande2 "$var2" SUPERIEUR fichier2 &
commande3 "$var3" SUPERIEUR fichier3 &
wait
echo "Statut = $?"
Ca me donne le code de sortie de commande3
{ commande1 "$var1" SUPERIEUR fichier1 & ; commande2 "$var2" SUPERIEUR fichier2 & ; ... }
ne marche pas, j'obtient: `;' unexpected
Merci d'avance
PS: Je suis sous SunOS / ksh
SUPERIEUR = le symbole supérieur (j'arrive pas a l'afficher dans le forum)
# Solution non testée....
Posté par Gyro Gearllose . Évalué à 2.
{ commande2 > fichier2 && CODE2 = $? } &
{ commande3 > fichier3 && CODE3 = $? } &
wait
echo La commande1 a eu pour code de retour $CODE1
echo La commande2 a eu pour code de retour $CODE2
echo La commande3 a eu pour code de retour $CODE3
Comme dit en titre, je n'ai pas testé, mais ça devrait marcher, non ?
[^] # Re: Solution non testée....
Posté par Gyro Gearllose . Évalué à 4.
[^] # Re: Solution non testée....
Posté par Paddle . Évalué à 1.
[^] # Re: Solution non testée....
Posté par Paddle . Évalué à 1.
oui, ca devrait et le pire est que c'est super simple...
Merci beaucoup!
[^] # ... malheureusement
Posté par JJD . Évalué à 2.
Je ne pense pas que cela puisse fonctionner en l'état :
- le "&&" qui sépare la commande de l'affectation de la variable CODEx fait que cette affectation ne sera effectuée que si la commande sort sans erreur. Donc, soit CODEx vaut 0, soit elle n'existe pas du tout. On pourrait remplacer && par un simple ; (point virgule), mais ...
- lorsque des commande sont exécutées en arrière plan, il y a un fork du shell. Tout ce qui est entre accolades est donc exécuté par un sous shell, et aucune des variables affectées dans ce sous-shell n'est récupérable par le shell appelant. Après le wait, les variables CODEx n'existent donc pas (sauf si elles avaient été déclarées avant, mais alors leur valeur ne serait pas modifiée).
La réponse au problème semble effectivement plus complexe que prévue.
Quelques pistes à explorer :
- wait sans argument attend que tous les processus fils soient terminés (et renvoie certainement le code retour du dernier qui se finit)
- on peut récupérer le PID d'un process lancé en arrière plan dans la variable $!
- wait nnn attend la fin du process ayant le pid nnn (mais je ne vois pas bien comment utiliser wait ici, pour attendre la fin de plusieurs processus successivement alors que l'on ne connaît pas l'ordre dans lequel ils vont finir)
Une solution simple (même si elle n'est pas très élégante) pourrait être de rajouter, à la fin des commandex quelque chose du genre "echo $? > /tmp/$$", de récupérer dans une variable le pid des commande en background ($!) et de relire les fichiers concernés après le wait.
En plus clair :
{ commande1 "$var1" > fichier1 ; echo $? >/tmp/res.$$ ; } &
pid1=$!
{ commande2 "$var2" > fichier2 ; echo $? >/tmp/res.$$ ; } &
pid2=$!
{ commande3 "$var3" > fichier3 ; echo $? >/tmp/res.$$ ; } &
pid3=$!
wait
retour1=`cat /tmp/res.$pid1`
rm /tmp/res.$pid1
retour2=`cat /tmp/res.$pid2`
rm /tmp/res.$pid2
retour3=`cat /tmp/res.$pid3`
rm /tmp/res.$pid3
[^] # Re: ... malheureusement
Posté par Gyro Gearllose . Évalué à 1.
plutôt que d'utiliser des fichiers temporaires, pourquoi ne pas utiliser la commande export pour positionner les variables de code de retour une bonne fois pour toutes ?
Ce qui reviendrait à :
{ commande1 > fichier1 && export CODE1 = $? } &
{ commande2 > fichier2 && export CODE2 = $? } &
{ commande3 > fichier3 && export CODE3 = $? } &
wait
echo La commande1 a eu pour code de retour $CODE1
echo La commande2 a eu pour code de retour $CODE2
echo La commande3 a eu pour code de retour $CODE3
Si jamais on veut faire propre, il suffit de faire quelques appels bien sentis avant de quitter le shell pour virer les variables indésirables :
export CODE1= CODE2= CODE3=
Je ne dispose pas de ksh pour tester, alors je vous laisse tester le tout pour voir ce que ça donne.
[^] # Re: ... malheureusement
Posté par Paddle . Évalué à 1.
cette solution ne semble pas marcher:
#!/bin/ksh
{ echo "valeur" ; export pid1=$$ ; echo $pid1 ; } &
{ echo "valeur" ; export pid2=$$ ; echo $pid2 ; } &
{ echo "valeur" ; export pid3=$$ ; echo $pid3 ; } &
wait
echo "Les pid sont $pid1 $pid2 $pid3"
donne
valeur
10959
valeur
10959
valeur
10959
Les pid sont
L'export ne marche pas en l'occurence...
[^] # Re: ... malheureusement
Posté par Paddle . Évalué à 1.
dans le code que tu suggere
{ commande1 > fichier1 && export CODE1 = $? } &
il faut mettre un ; a la fin, sinon, on obtient une erreur
{ commande1 > fichier1 && export CODE1 = $? ; } &
sans doute un simple oubli de ta part, mais j'avoue que j'ai cherché un moment ;)
Merci encore.
[^] # Re: ... malheureusement
Posté par Paddle . Évalué à 1.
cette solution fonctionne bien. Effectivement, ce n'est pas très propre, mais ca fonctionne, ce qui est le plus important!
Merci beaucoup!
# Parce que je suis tenace !
Posté par Gyro Gearllose . Évalué à 2.
code1 = `(commande1 > fichier1 ; echo $? ) &`
code2 = `(commande2 > fichier2 ; echo $? ) &`
code3 = `(commande3 > fichier3 ; echo $? )&`
wait
echo $code1, $code2, $code3
J'ai pu tester avec un pauv' ksh que j'ai ressorti d'un vieux serveur...
Ca semble fonctionner comme tu veux....
[^] # Re: Parce que je suis tenace ! et plein d'illusions...
Posté par JJD . Évalué à 2.
Désolé de te décevoir encore une fois, mais dans le code que tu donnes, les commandes ne sont pas exécutées en parallèle : l'affectation de la variable code1 doit être terminée pour que l'instruction suivante (code2 = `(commande2 > fichier2 ; echo $? ) &`) soit exécutée. Ça ne répond donc pas réellement au problème de départ de Paddle (exécution de plusieurs commandes en même temps avec récupération du code retour).
Pour finir, si le coup de l'export des variables ne fonctionne pas, c'est parce que export permet de dupliquer des variables vers les sous-processus et non pas de les partager avec eux. En aucun cas la modification dans un sous-shell d'une variable exportée ne sera visible dans le shell appelant (et cela n'est pas spécifique à ksh).
Je te félicite tout de même de ta persévérance.
A+
JJD
[^] # Re: Parce que je suis tenace ! et plein d'illusions...
Posté par Gyro Gearllose . Évalué à 2.
Le pire, c'est que tu as une fois encore raison, mais là, je pense être plus proche de LA SOLUTION que jamais.....
Que penses-tu de ça :
code1 = `(commande1 > fichier1 ; echo $? ) ` &
code2 = `(commande2 > fichier2 ; echo $? ) ` &
code3 = `(commande3 > fichier3 ; echo $? )` &
wait
echo $code1, $code2, $code3
En déplaçant les & en dehors des quotes, c'est l'affectation qui passe en arrière plan, et non seulement la tâche exécutée à droite du signe =.
Là, je pense que ça peut fonctionner, ça, mince alors !
Pour le coup de l'export, tu as fort raison, mais mes cours de shell sont bien loins maintenant, et je l'utilise si rarement que ... ben ... bref.
En tout cas, le coup de la persévérance, c'est surtout pour ma culture personnelle et parce que je me dis que peut-être, un jour, ça me servira à quelque chose.
D'ailleurs, j'utilise déjà quelque chose un peu dans ce genre, mais sans contrôle d'erreur... "Ce qui est bien mais pas top", comme dirait l'autre, et finalement, le problème de notre ami pourrait m'aider à résoudre le mien !
Et puis merci à toi, car si tu trouves que je suis persévérant, tu sembles l'être au moins autant que moi puisque tu es toujours là pour me corriger !
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.