12
votes

Exécuter simultanément plusieurs scripts shell

Je veux faire les choses suivantes:

  • exécuter plusieurs scripts shell (ici 2 scripts) simultanément. p> li>

  • Attendez que les deux scripts finissent p> li>

  • Valeur de décharge de chaque script p> li> ul>

    Cependant, main.sh code> ne fonctionne pas comme prévu. p>

    main.sh h2> xxx pré>

    A. / H2>
    #!/bin/bash
    sleep 5
    echo 2
    


1 commentaires

Jetez un coup d'œil à Stackoverflow.com/questions/356100/...


5 Réponses :


3
votes

La réponse que vous recherchez est dans cette question shell - obtenez le code de sortie de l'arrière-plan Processus

Fondamentalement, lorsque vous vous appuyez sur un processus, vous ne pouvez pas obtenir son code de sortie directement. Mais si vous exécutez la commande BASH WAIT, alors weatt s de sortie de sortie renvoie le code de sortie du processus d'arrière-plan. xxx

ceci fonctionnera Même si A.Sh se termine avant de courir attendre. La variable spéciale $? détient le code de sortie du processus précédent. Et $! contient l'ID de processus du processus précédemment exécuté.


1 commentaires

Cela ne mettra pas la valeur de retour d'attente dans RET1, mais définira toujours RET1 sur la chaîne vide. (attendre n'écrire rien à stdout)



6
votes

Voici quelques codes que j'ai couru, cela semble faire exactement ce que vous voulez. Juste insérer ./ a.sh et ./ b.sh le cas échéant: xxx

Notez que cela capture l'état de la sortie de la script et non ce qu'il génère sur stdout . Il n'y a pas de moyen simple de capturer le stdout d'un script en cours d'exécution dans l'arrière-plan, je vous conseillerais de vous conseiller d'utiliser le Statut de sortie pour renvoyer des informations au processus d'appel.


0 commentaires

0
votes

Les backtsticks ne donnent pas la valeur renvoyée par la commande, mais la sortie de la commande. Pour obtenir les valeurs de retour:

#!/bin/sh

./a.sh &
./b.sh
ret2=$?   # get value returned by b.sh
wait %1   # Wait for a.sh to finish
ret1=$?   # get value returned by a.sh
echo "$ret1: $ret2"


1 commentaires

Remarque: ce qui précède fonctionne dans Bash, mais je ne suis pas certain de la portabilité de% 1. Vous devrez peut-être utiliser "attendre $!" au lieu.




2
votes

Si vous avez Bash 4.2 ou ultérieur disponible, les éléments suivants vous seront utiles. Il utilise des tableaux associatifs pour stocker des noms de tâches et leur "code" ainsi que des noms de tâches et de leurs PID. J'ai également construit dans une simple méthode de limitation de taux qui pourrait être pratique si vos tâches consomment beaucoup de processeur ou d'E / S et que vous souhaitez limiter le nombre de tâches simultanées.

Le script lance toutes les tâches dans la première Boucle et consomme les résultats dans le second. P>

Ceci est un peu surpeuplé pour des cas simples, mais cela permet de jolies choses soignées. Par exemple, on peut stocker des messages d'erreur pour chaque tâche dans un autre tableau associatif et les imprimer après que tout s'est installé. P>

(J'ai copié cette réponse sur ma réponse Ici parce que cela résout les deux questions, si ce n'est pas ok, veuillez me le dire ou le remplacer directement par un lien ou tout ce qui est approprié.) P>

#! /bin/bash

main () {
    local -A pids=()
    local -A tasks=([task1]="echo 1"
                    [task2]="echo 2"
                    [task3]="echo 3"
                    [task4]="false"
                    [task5]="echo 5"
                    [task6]="false")
    local max_concurrent_tasks=2

    for key in "${!tasks[@]}"; do
        while [ $(jobs 2>&1 | grep -c Running) -ge "$max_concurrent_tasks" ]; do
            sleep 1 # gnu sleep allows floating point here...
        done
        ${tasks[$key]} &
        pids+=(["$key"]="$!")
    done

    errors=0
    for key in "${!tasks[@]}"; do
        pid=${pids[$key]}
        local cur_ret=0
        if [ -z "$pid" ]; then
            echo "No Job ID known for the $key process" # should never happen
            cur_ret=1
        else
            wait $pid
            cur_ret=$?
        fi
        if [ "$cur_ret" -ne 0 ]; then
            errors=$(($errors + 1))
            echo "$key (${tasks[$key]}) failed."
        fi
    done

    return $errors
}

main


4 commentaires

Bonjour, désolé d'avoir sauté tard, mais je veux capturer l'heure de début du temps de démarrage et le temps écoulé pour chaque tâche individuelle terminée / incomplète. Mais je suis incapable de le faire


Vous pouvez ajouter un autre tableau similaire à PIDS et stocker le temps de départ de là, mais il nécessiterait un style différent d'attente des processus. Enotime pour comprendre quelque chose, peut-être créer une nouvelle question pourrait être meilleure quand même?


Salut Just Besoin d'une clarification Pouvez-vous expliquer ces emplois de ligne 2> & 1 Comment ça ne reçoive-t-il que les emplois m'exécutent actuellement? Que se passera-t-il si d'autres emplois fonctionnent également qui ne sont pas déclenchés par moi (utilisateur)


Emplois Imprime uniquement les travaux Shell de la coque actuelle. Il n'inclut pas les travaux d'autres coquilles / terminaux ou même d'autres utilisateurs. Toutefois, si vous démarrez un travail d'arrière-plan avant d'exécuter un script à l'aide du code ci-dessus, ce travail serait également renvoyé et fera partie du nombre d'emplois «en cours d'exécution». Cela pourrait ou pourrait ne pas être recherché mais je suppose qu'il est logique de l'inclure dans la plupart des cas. Sinon, il faudrait enregistrer les travaux qui existent lorsque le script est démarré et les filtre pour le calcul.