Récupérer une variable d'un sous shell en bash
Bonjour, Cette liste existe toujours ? Si oui, je cherche un moyen de récupérer le code de sortie d'une commande que je fais tourner en arrière plan (avec bash), pour sortir de mon script avec ce code. J'ai essayé $commande && exit $? & mais ça sort du sous-shell, pas du script (logique), avec function end() { exit $1; } $commande && end $? & c'est pas mieux, ni avec export sortie=12 $commande && sortie=$? & (celui-là me parait logique aussi, la valeur est modifiée dans le sous-shell mais remonte pas) trap ne choppe que les signaux du shell courant, wait m'arrange pas parce que je veux pas m'arrêter (j'ai un truc qui tourne en parallèle pour surveiller $commande), comment remonter mon code de sortie au shell parent ? Merci -- Daniel Pourquoi lave-t-on une injure alors qu'on essuie un affront ? Alphonse Allais
Le 02/12/15 à 12:27, Daniel Caillibaud <ml@lairdutemps.org> a écrit : […] DC> Si oui, je cherche un moyen de récupérer le code de sortie d'une commande que je fais DC> tourner en arrière plan (avec bash), pour sortir de mon script avec ce code. […] J'ai contourné le pb avec trap "exit 0" RTMIN trap "exit 1" RTMAX $command && kill -RTMIN $$ || kill -RTMAX $$ & pid=$! # ici je peux surveiller $pid tranquillement J'ai pris RTMIN et RTMAX arbitrairement dans la liste de kill -l Je récupère pas le vrai code de sortie mais ok/ko, ça me suffit. Mais je suis quand même preneur d'une manière de modifier une variable d'un shell parent dans un sous-shell, si y'en a une sans passer par un fichier (qui serait une solution). -- Daniel - Tu sais pourquoi Bruce Lee ? - Parce qu'on a lui a appris à lire.
hello,
comment remonter mon code de sortie au shell parent ?
excellente formulation! du coup la lecture d'un document expliquant le fonctionnement des processus unix te donnera la réponse: tu ne peux simplement pas. Il faut donc utiliser un socket unix ou internet, un fichier ou n'importe quel autre mecanisme qui permettent aux process de s'échanger de l'info.
Si oui, je cherche un moyen de récupérer le code de sortie d'une commande que je fais tourner en arrière plan.
comment peux-tu avoir un code de retour d'un truc qui tourne a moins de lire dans le futur ?
J'ai essayé $commande && exit $? &
oula ... reprennons: commande; exit $? et commande; font la meme chose (parceque le shell renvoie la valeur de la derniere expression evaluée (soit $?)). idem pour les fonctions foo () { commande; return $? } et foo () { commande } mais donc... que renvoie une expression qui passe une commande en bg ? foo () { return 5 } foo perl -E'sleep 1; exit 10'& echo $? # 0 donc $? veut juste dire que & a marché foo wait echo $? # 0 ... donc $? veut dire que wait a bien fonctionné dans zsh tu as le $pipe_status mais j'ai jamais utilisé. donc le plus simple a mon avis est de passer par des fichiers pstatus=$( mktemp -d ~/process-status-$(date +%F_%X_%s_XXXX )) { montruc --avec --plein de parametres <<< $? > $pstatus/montruc } & du coup tu peux voir si le process est fini dans ton script test -f $pstatus/montruc && echo "job done" et comme c'est dans des fichiers, tu peux facilement surveille l'état d'avancement des jobs meme apres avoir quitté ton script. cordialement, -- Marc Chantreux (eiro on github and freenode) http://eiro.github.com/ http://eiro.github.com/atom.xml "Don't believe everything you read on the Internet" -- Abraham Lincoln
Le 04/12/15 à 18:21, Marc Chantreux <khatar@phear.org> a écrit : MC> hello, MC> MC> > comment remonter mon code de sortie au shell parent ? MC> MC> excellente formulation! du coup la lecture d'un document expliquant le MC> fonctionnement des processus unix te donnera la réponse: tu ne peux MC> simplement pas. MC> MC> Il faut donc utiliser un socket unix ou internet, un fichier ou MC> n'importe quel autre mecanisme qui permettent aux process de s'échanger MC> de l'info. Bon ben pas la peine que je cherche davantage ;-) MC> > Si oui, je cherche un moyen de récupérer le code de sortie d'une commande que je fais MC> > tourner en arrière plan. MC> MC> comment peux-tu avoir un code de retour d'un truc qui tourne a moins de lire dans le MC> futur ? J'attends simplement que le futur devienne maintenant ;-) MC> > J'ai essayé MC> > $commande && exit $? & MC> MC> oula ... reprennons: MC> MC> commande; MC> exit $? MC> MC> et MC> MC> commande; MC> MC> font la meme chose (parceque le shell renvoie la valeur de la MC> derniere expression evaluée (soit $?)). idem pour les fonctions MC> MC> foo () { commande; return $? } MC> MC> et MC> MC> foo () { commande } Pour une fonction c'est évident, j'espérais bêtement que mon exit sortirait du script principal, alors qu'il ne sort que du bg (ce qu'il aurait fait de toute façon). Parce que dans le script principal, commande; # la suite n'est pas la même chose que commande; exit $? # la suite car dans le 2e cas la suite n'est jamais exécutée. (c'est évident, juste pour expliquer ma tentative de exit $? qui parait vraiment stupide) MC> mais donc... que renvoie une expression qui passe une commande MC> en bg ? MC> MC> foo () { return 5 } MC> foo MC> perl -E'sleep 1; exit 10'& MC> echo $? # 0 donc $? veut juste dire que & a marché MC> foo MC> wait MC> echo $? # 0 ... donc $? veut dire que wait a bien fonctionné MC> MC> dans zsh tu as le $pipe_status mais j'ai jamais utilisé. MC> MC> donc le plus simple a mon avis est de passer par des fichiers MC> MC> pstatus=$( mktemp -d ~/process-status-$(date +%F_%X_%s_XXXX )) MC> { montruc --avec --plein de parametres MC> <<< $? > $pstatus/montruc } & MC> MC> du coup tu peux voir si le process est fini dans ton script MC> MC> test -f $pstatus/montruc && echo "job done" MC> MC> et comme c'est dans des fichiers, tu peux facilement surveille l'état MC> d'avancement des jobs meme apres avoir quitté ton script. Ok, c'est clair, merci Marc. Je m'étais contenté d'un ok|KO, avec trap "exit $OK" RTMIN trap "exit $KO" RTMAX $commande && kill -RTMIN $$ || kill -RTMAX $$ & mais je viens d'ajouter le vrai code de sortie en passant par un fichier, voici le script complet (qui veut mettre en pause un process trop gourmand en I/O, que ionice ne suffit pas à calmer et qui exlose mon load), si y'en a que ça intéressent. Les critiques sont bienvenues, je viens d'ajouter (en plus du bon code d'erreur) la partie de reprise pour rsync que je n'ai pas encore testée (pour cp et rm ça marche bien) #!/bin/bash # wrapper pour lancer une commande et la mettre en pause si le load monte trop # les bornes du load x100 pour arrêter / reprendre MAX=150 MIN=100 # intervalle de temps en secondes pour la mesure du load et décision d'arrêter / reprendre PAUSE=10 # durée de la reprise brève pour rsync RESUME=5 # nb d'intervalle à attendre avant de lancer un resume NBCYCLES=10 # pour la lisibilité OK=0 K0=1 # affiche un message horodaté function log() { echo "[$(date '+%F:%T')] $@" } # idem sur stderr function logErr() { echo "[$(date '+%F:%T')] $@" >&2 } # met à jour la variable state et répond ok si vide function isLost() { state=$(ps -o s= $pid) [ -z "$state" ] && return $OK || return $KO } function exitOk() { log "fin ok $commande" exit $OK } function exitKO() { logErr "fin KO $commande" exit $(<$statusFile) } function end() { rm -f $statusFile } # pour être prévenu de la sortie on utilise ces signaux passés à $$ (le pid courant, identique en arrière plan) trap exitOk RTMIN trap exitKO RTMAX # et pour nettoyer notre fichier temporaire trap end EXIT # on a des alias (symlinks) comme benice_cp pour préfixer les arguments reçu avec la commande cp [ "$0" == "benice.sh" ] && commande="$@" || commande="${0#*benice_} $@" # faut au moins /bin et /sbin dans notre PATH, pour les alias [ "$PATH" == "${PATH/:\/sbin/}" ] && $PATH="$PATH:/sbin" [ "$PATH" == "${PATH/:\/bin/}" ] && $PATH="$PATH:/bin" statusFile=$(mktemp /tmp/${0}_XXXX) # on lance la commande en arrière plan (et on sortira quand elle sera terminée avec son code de retour) #echo "on lance $commande && kill -RTMIN $$ || kill -RTMAX $$ &" $commande && kill -RTMIN $$ || (echo $? > $statusFile && kill -RTMAX $$) & # le pid de la commande qui tourne en arrière plan # ok, grep -v grep est quick&dirty, un pid=$(ps -o pid= -C "$commande") serait plus propre mais ça marche pas pid=$(ps auxw|grep " $commande"|grep -v grep|awk '{print $2}') state="" isLost # pour init $state i=0 #echo "pid $pid dans l'état $state avec les process benice :" #ps auxwf |grep -2 [b]enice # et on boucle avec une sonde toutes les $PAUSE secondes while true do load=$(cut -d " " -f 1 /proc/loadavg) # valeur entière (le /1) du load x100 load100=$(echo "$load * 100 / 1"|bc) isLost && sleep 1 && isLost && logErr "$0 tourne toujours alors que le pid $pid ne tourne plus" \ && exit $KO # pour savoir si on a mis en pause le process on teste si l'état vaut T (en pause), # sinon il peut valoir R (running) ou D (pour des attentes I/O) ou S (autre attente), man ps pour le détail if [ "$state" == "T" ] then # en pause if [ $load100 -lt $MIN ] then kill -CONT $pid && log "Reprise de la commande '$commande' (load x100 : $load100 état $state)" else i=$((i+1)) if [ "$aliasName" == "rsync" && $i -gt $NBCYCLES ] then # on reprend brièvement pour pas couper la connexion rsync log "reprise brève de la commande '$commande' (load x100 : $load100)" \ && kill -CONT $pid && sleep $RESUME && kill -STOP $pid && i=0 fi fi else # D ou R [ $load100 -gt $MAX ] && kill -STOP $pid && i=0 \ && log "Commande '$commande' mise en pause (load x100 : $load100 état $state)" fi sleep $PAUSE done logErr "Sortie anormale de $0" exit $KO -- Daniel La pensée vole et les mots vont à pied. Voilà tout le drame de l'écrivain. Green.
salut,
J'attends simplement que le futur devienne maintenant ;-)
commande; # la suite n'est pas la même chose que commande; exit $? # la suite car dans le 2e cas la suite n'est jamais exécutée. (c'est évident, juste pour expliquer ma tentative de exit $? qui parait vraiment stupide)
je ne disais pas le contraire, par contre le $? est inutile exit fait la meme chose que exit $?
#!/bin/bash
j'avoue ne pas avoir lu ton script par manque de temps. désolé. cordialement, -- Marc Chantreux (eiro on github and freenode) http://eiro.github.com/ http://eiro.github.com/atom.xml "Don't believe everything you read on the Internet" -- Abraham Lincoln
Le 07/12/15 à 15:13, Marc Chantreux <khatar@phear.org> a écrit : MC> j'avoue ne pas avoir lu ton script par manque de temps. désolé. Ne soit pas désolé, c'était p'tet pas clair mais je demandais pas une correction, juste filer le script maintenant qu'il tourne (aux arguments genre --truc="toto tutu" près), et récupérer éventuellement des retours de ceux que ça pourrait intéresser mais qui le trouveraient trop mal écrit pour s'en servir tel quel ;-) -- Daniel Il y a trois sortes de mathématiciens : ceux qui savent compter et ceux qui ne savent pas.
On Mon, Dec 07, 2015 at 03:37:22PM +0100, Daniel Caillibaud wrote:
Le 07/12/15 à 15:13, Marc Chantreux <khatar@phear.org> a écrit : MC> j'avoue ne pas avoir lu ton script par manque de temps. désolé.
Ne soit pas désolé, c'était p'tet pas clair mais je demandais pas une correction, juste filer le script maintenant qu'il tourne (aux arguments genre --truc="toto tutu" près), et récupérer éventuellement des retours de ceux que ça pourrait intéresser mais qui le trouveraient trop mal écrit pour s'en servir tel quel ;-)
alors ca manque de doc et d'exemple! -- Marc Chantreux (eiro on github and freenode) http://eiro.github.com/ http://eiro.github.com/atom.xml "Don't believe everything you read on the Internet" -- Abraham Lincoln
Le 07/12/15 à 16:09, Marc Chantreux <khatar@phear.org> a écrit : MC> On Mon, Dec 07, 2015 at 03:37:22PM +0100, Daniel Caillibaud wrote: MC> > Le 07/12/15 à 15:13, Marc Chantreux <khatar@phear.org> a écrit : MC> > MC> j'avoue ne pas avoir lu ton script par manque de temps. désolé. MC> MC> > Ne soit pas désolé, c'était p'tet pas clair mais je demandais pas une MC> > correction, juste filer le script maintenant qu'il tourne (aux MC> > arguments genre --truc="toto tutu" près), et récupérer éventuellement MC> > des retours de ceux que ça pourrait intéresser mais qui le MC> > trouveraient trop mal écrit pour s'en servir tel quel ;-) MC> MC> alors ca manque de doc et d'exemple! C'est juste un wrapper, que j'utilise pour rm et cp pour les mettre en pause si le load dépasse une limite et reprendre quand ça redescend. J'essaierai de nettoyer, documenter et publier un de ces jours. -- Daniel Pourquoi lave-t-on une injure alors qu'on essuie un affront ? Alphonse Allais
participants (2)
-
Daniel Caillibaud
-
Marc Chantreux