Exécuter tous les scripts Bash dans le dossier en même temps

10

Supposons que j'ai cinq .shscripts Bash ( ) dans un dossier ( my_folder), et ils sont nommés comme suit:

script_1.sh
script_2.sh
script_3.sh
script_4.sh
script_5.sh

Comment puis-je écrire un sixième script Bash ou juste un liner qui commencera à exécuter tous ces scripts ensemble?

J'ai besoin des cinq scripts pour commencer à fonctionner tous ensemble en même temps et pas l'un après l'autre.

aaaaa
la source

Réponses:

12

GNU parallelest parfait pour ce genre de chose. Installez avec sudo apt install parallelpuis:

parallel -j0 ::: my_folder/*sh

Le -jcontrôle le nombre de processus exécutés en parallèle et -j0signifie «tous». Définissez-le sur une autre valeur (par exemple -j20) pour exécuter les scripts par lots à la place.

terdon
la source
1
note: il y a aussi la parallelcommande du moreutilspackage. L'exemple d'utilisation: parallel -j 20 -- my_folder/*.sh(Contrairement à GNU parallel, -j0exécuter les scripts un par un).
jfs
1
@jfs bon point. Mais notez que sudo apt install parallelcela remplacera le fichier /usr/bin/parallelpar celui du parallèle GNU. Donc, tant que vous l'installez, comme ma réponse le suggère, cela devrait fonctionner comme prévu.
terdon
Oui, je l'avais découvert à la dure en essayant sans succès les parallelcommandes du manuel lors de l'écriture de ma réponse pour suggérer GNU parallèle.
jfs
9

Pour exécuter tous les scripts en même temps (en parallèle), utilisez:

script_1.sh &
script_2.sh &
script_3.sh &
script_4.sh &
script_5.sh &

Pour exécuter l'un après l'autre (séquentiellement), utilisez:

script_1.sh &&
script_2.sh &&
script_3.sh &&
script_4.sh &&
script_5.sh

Amélioration des commentaires

Si vous avez 200 scripts que vous souhaitez exécuter en même temps (ce qui pourrait enliser la machine BTW), utilisez ce script:

#!/bin/bash
for Script in my_folder/*.sh ; do
    echo bash "$Script" &
done

Définissez les attributs de script sur exécutable avec la commande:

chmod a+x /path/to/script.sh

La première fois que vous exécutez le script, il ne fera écho que les noms des 200 scripts qu'il exécutera. Lorsque vous êtes satisfait des bons noms, modifiez le script et modifiez cette ligne:

    echo bash "$Script" &

à:

    bash "$Script" &

Il existe trois façons d'appeler un script bash à partir d'un autre, comme indiqué ici:

  1. Rendez l'autre script exécutable, ajoutez la #!/bin/bashligne en haut et le chemin d'accès du fichier à la $PATHvariable d'environnement. Ensuite, vous pouvez l'appeler comme une commande normale;

  2. Ou appelez-le avec la commande source (l'alias est.) Comme ceci source /path/to/script:;

  3. Ou utilisez la commande bash pour l' exécuter: /bin/bash /path/to/script;

Dans le cas d'OP, un ou plusieurs des 200 scripts ne contenaient pas la #!/bin/bashpremière ligne de shebang dans le fichier. En tant que telle, l'option 3. devait être utilisée.


200 scripts exécutés en même temps

Un commentaire a été soulevé quant à savoir s'ils "fonctionnent en même temps". Sur un système typique à 8 CPU, 25 scripts partageront un CPU en même temps, mais un seul script s'exécutera à la fois jusqu'à ce que sa tranche de temps (mesurée en millisecondes) s'épuise. Ensuite, le prochain travail recevra sa juste part de millisecondes, puis le prochain travail, etc., etc.

En termes vagues, nous pouvons dire que 200 travaux s'exécutent "simultanément" mais pas "simultanément" sur 8 processeurs, ce qui équivaut à 25 travaux par processeur:

thread states.png

Image ci-dessus et commentaires ci-dessous du planificateur du noyau Linux

time slice.png

WinEunuuchs2Unix
la source
merci .. la chose est que dans mon cas réel j'ai plus de 200 scripts à exécuter. existe-t-il un moyen de les exécuter tous avec une seule commande (c'est-à-dire sans écrire leurs noms de fichiers)?
aaaaa
@aaaaa J'ai changé la réponse pour 200 scripts.
WinEunuuchs2Unix
Merci. cela fonctionne .. la seule chose que j'ai dû ajouter à votre dernière ligne était «bash». sinon j'obtiens une «autorisation refusée».
aaaaa
1
@aaaaa Préférez-vous réellement que tous les 200+ scripts s'exécutent en même temps, ou préférez-vous qu'un certain nombre (disons, 10) s'exécute à la fois, avec les autres en file d'attente pour s'exécuter quand un ou plusieurs d'entre eux se terminent et le nombre de scripts en cours d'exécution tombe en dessous de ce nombre? (Si vous êtes intéressé par de telles solutions, je vous suggère de modifier votre question avec des informations sur le nombre de scripts dont vous disposez, sur la durée de leur exécution, sur le type de travail qu'ils effectuent, etc.)
Eliah Kagan
@aaaaa Merci pour la rétroaction. J'ai mis à jour la réponse pour inclure un bashpréfixe pour appeler le script.
WinEunuuchs2Unix
3

Il y a un outil pour cela, lisez man run-parts.

Par exemple, je fais:

 run-parts ${visorhome}/pbackup.d/

dans mon script de sauvegarde Palm Pilot. ${visorhome}/pbackup.d/:

01PopulateJpilot  02Extract_Pedometer  03URLs  04google  05Books  06Weight  07Sec  08Bkgm 50hardlinks
waltinator
la source
1
@ eliah-kagan Exécuter "plus de 200 scripts" "en même temps" semble imprudent. Ce pourrait être un bon moyen de tester un système sous
contrainte
Bon point. Je pense que vous voudrez peut-être encore mentionner que run-partsexécute les scripts de manière séquentielle plutôt que d'un seul coup, comme l'OP l'a demandé. Cependant, vous avez raison, il est peu probable que l'exécution de 200 scripts à la fois soit identique à l'exécution de 5 - et même si les exécuter tous en même temps ne pose aucun problème, cela peut quand même être inutile. J'ai commenté pour suggérer au PO de clarifier ses préférences à cet égard.
Eliah Kagan
run-partsne lancera pas les scripts (ils ont un point dans le nom:my_folder/*.sh
jfs
1
run-partsa des exigences de nom de fichier très spécifiques pour une raison étrange. Il ne lancera pas de noms de fichiers avec des extensions, donc je crains que cela ne fonctionne pas ici.
terdon
1

Pour exécuter tous les *.shscripts du my_folderrépertoire en même temps en utilisant xargs:

$ ls my_folder/*.sh | xargs -P0 -n1 bash

Pour limiter le nombre de scripts exécutés simultanément à 10:

$ ls my_folder/*.sh | xargs -P10 -n1 bash
jfs
la source
C'est une mauvaise pratique d'utiliser la sortie de lsdans un script. L'utilisation findest beaucoup plus sûre. C'est le tout premier élément ici: mywiki.wooledge.org/BashPitfalls#for_f_in_.24.28ls_.2A.mp3.29
Joe
@Joe en général, c'est vrai. Je ne vois pas de problèmes dans ce cas particulier.
jfs
C'est parce que vous le savez déjà. Les gens qui viendront ici plus tard pourraient ne pas le faire.
Joe
@Joe ne suit pas aveuglément le dogme. Pensez par vous-même qu'une option est meilleure qu'une autre, quels sont les compromis dans votre cas.
jfs
Ce n'est pas un dogme. Je suis allergique à ceux-là. Mais j'ai vu les choses que ls peuvent émettre. L'analyse d'une sortie lisible par l'homme n'est pas fiable. Les développeurs ne sont pas incités à garder
Joe