J'essaie d'écrire un fichier .sh qui exécute plusieurs programmes simultanément
J'ai essayé
prog1
prog2
Mais cela exécute prog1 puis attend la fin de prog1 puis démarre prog2 ...
Alors, comment puis-je les exécuter en parallèle?
bash
parallel-processing
Betamoo
la source
la source
wait
! Oui, dans bash, vous pouvez attendre les processus enfants du script.nohup
empêcher le programme d'être tué lorsque le shell raccroche.Que diriez-vous:
Cette volonté:
prog1
.prog2
et gardez-le au premier plan pour pouvoir le fermerctrl-c
.prog2
, vous revenez àprog1
de » l'avant - plan , de sorte que vous pouvez refermer avecctrl-c
.la source
prog1
lorsque seprog2
termine? Pensez ànode srv.js & cucumberjs
prog1 & prog2 ; fg
c'était pour exécuter plusieurs tunnels ssh à la fois. J'espère que cela aide quelqu'un.prog2
ne s'exécute pas immédiatement, vous reviendrezprog1
au premier plan. Si cela est souhaitable, c'est ok.prog1 & prog2 && kill $!
.Vous pouvez utiliser
wait
:Il attribue les PID du programme d'arrière-plan aux variables (
$!
est le dernier PID du processus lancé), puis lawait
commande les attend. C'est bien car si vous tuez le script, il tue aussi les processus!la source
#!/usr/bin/env bash ARRAY='cat bat rat' for ARR in $ARRAY do ./run_script1 $ARR & done P1=$! wait $P1 echo "INFO: Execution of all background processes in the for loop has completed.."
${}
pour l'interpoler dans une liste de chaînes ou similaire.Avec GNU Parallel http://www.gnu.org/software/parallel/, c'est aussi simple que:
Ou si vous préférez:
Apprendre encore plus:
la source
parallel
avec une syntaxe différente. Par exemple, sur les dérivés Debian, lemoreutils
paquet contient une commande différente appeléeparallel
qui se comporte assez différemment.parallel
mieux que d'utiliser&
?parallel
est meilleur lorsqu'il y a plus de travaux que de cœurs, auquel cas&
ils exécuteraient plus d'un travail par cœur à la fois. (cf. principe du pigeonhole )Si vous voulez pouvoir exécuter et tuer facilement plusieurs processus avec
ctrl-c
, voici ma méthode préférée: générer plusieurs processus d'arrière-plan dans un(…)
sous - shell et intercepterSIGINT
pour exécuterkill 0
, ce qui tuera tout ce qui est généré dans le groupe de sous-shell:Vous pouvez avoir des structures d'exécution de processus complexes, et tout se terminera par un seul
ctrl-c
(assurez-vous simplement que le dernier processus est exécuté au premier plan, c'est-à-dire, n'incluez pas d'&
afterprog1.3
):la source
xargs -P <n>
vous permet d'exécuter des<n>
commandes en parallèle.Bien qu'il
-P
s'agisse d'une option non standard, les implémentations GNU (Linux) et macOS / BSD la prennent en charge.L'exemple suivant:
La sortie ressemble à quelque chose comme:
Le timing montre que les commandes ont été exécutées en parallèle (la dernière commande n'a été lancée qu'après la fin du premier des 3 originaux, mais exécutée très rapidement).
La
xargs
commande elle-même ne reviendra pas tant que toutes les commandes ne seront pas terminées, mais vous pouvez l'exécuter en arrière-plan en la terminant avec l'opérateur de contrôle&
, puis en utilisant la fonctionwait
intégrée pour attendre la fin de laxargs
commande entière .Remarque:
BSD / macOS
xargs
vous oblige à préciser le nombre de commandes à exécuter en parallèle explicitement , alors que GNUxargs
vous permet de spécifier-P 0
d'exécuter le plus grand nombre possible en parallèle.La sortie des processus exécutés en parallèle arrive au fur et à mesure de sa génération , elle sera donc entrelacée de façon imprévisible .
parallel
, comme mentionné dans la réponse d'Ole ( non fourni en standard avec la plupart des plates-formes), sérialise (regroupe) commodément la sortie par processus et offre de nombreuses fonctionnalités plus avancées.la source
Redirigez les erreurs vers des journaux distincts.
la source
prog1 2> .errorprog1.log & prog2 2> .errorprog2.log &
ls notthere1 & 2> .errorprog1.log; ls notthere2 & 2>.errorprog2.log
. Les erreurs vont à la console et les deux fichiers d'erreur sont vides. Comme le dit @Dennis Williamson,&
est un séparateur, comme;
, donc (a) il doit aller à la fin de la commande (après toute redirection), et (b) vous n'avez pas besoin du;
tout :-)Il existe un programme très utile qui appelle nohup.
la source
nohup
par lui-même n'exécute rien en arrière-plan, et l'utilisationnohup
n'est pas une exigence ou une condition préalable pour exécuter des tâches en arrière-plan. Ils sont souvent utiles ensemble mais en tant que tels, cela ne répond pas à la question.Voici une fonction que j'utilise pour exécuter au max n processus en parallèle (n = 4 dans l'exemple):
Si max_children est défini sur le nombre de cœurs, cette fonction essaiera d'éviter les cœurs inactifs.
la source
wait -n
nécessitebash
4.3+ et il change la logique en attendant la fin de l' un des processus spécifiés / implicites.Vous pouvez essayer ppss . ppss est assez puissant - vous pouvez même créer un mini-cluster. xargs -P peut également être utile si vous avez un lot de traitement parallèle embarrassant à faire.
la source
J'ai eu une situation similaire récemment où j'avais besoin d'exécuter plusieurs programmes en même temps, de rediriger leurs sorties vers des fichiers journaux séparés et d'attendre qu'ils se terminent et je me suis retrouvé avec quelque chose comme ça:
Source: http://joaoperibeiro.com/execute-multiple-programs-and-redirect-their-outputs-linux/
la source
Gestionnaire de génération de processus
Bien sûr, techniquement, ce sont des processus, et ce programme devrait vraiment être appelé un gestionnaire de génération de processus, mais cela n'est dû qu'à la façon dont BASH fonctionne quand il bifurque en utilisant l'esperluette, il utilise l'appel système fork () ou peut-être clone () qui clone dans un espace mémoire séparé, plutôt que quelque chose comme pthread_create () qui partagerait la mémoire. Si BASH supportait ce dernier, chaque "séquence d'exécution" fonctionnerait de la même manière et pourrait être qualifiée de threads traditionnels tout en gagnant une empreinte mémoire plus efficace. Fonctionnellement, cependant, cela fonctionne de la même manière, bien qu'un peu plus difficile car les variables GLOBALES ne sont pas disponibles dans chaque clone de travail, d'où l'utilisation du fichier de communication interprocessus et du sémaphore du troupeau rudimentaire pour gérer les sections critiques. Le fork de BASH est bien sûr la réponse de base ici, mais j'ai l'impression que les gens le savent mais cherchent vraiment à gérer ce qui est généré plutôt que de simplement le fork et l'oublier. Cela illustre un moyen de gérer jusqu'à 200 instances de processus bifurqués accédant tous à une seule ressource. De toute évidence, c'est exagéré, mais j'ai aimé l'écrire, alors j'ai continué. Augmentez la taille de votre terminal en conséquence. J'espère que vous trouvez ça utile.
la source
Votre script devrait ressembler à:
En supposant que votre système peut prendre n tâches à la fois. utilisez wait pour exécuter uniquement n jobs à la fois.
la source
Avec bashj ( https://sourceforge.net/projects/bashj/ ), vous devriez être en mesure d'exécuter non seulement plusieurs processus (comme d'autres l'ont suggéré) mais également plusieurs threads dans une machine virtuelle Java contrôlée à partir de votre script. Mais bien sûr, cela nécessite un JDK java. Les threads consomment moins de ressources que les processus.
Voici un code de travail:
la source