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.