J'ai un script bash qui ressemble à ceci:
#!/bin/bash
wget LINK1 >/dev/null 2>&1
wget LINK2 >/dev/null 2>&1
wget LINK3 >/dev/null 2>&1
wget LINK4 >/dev/null 2>&1
# ..
# ..
wget LINK4000 >/dev/null 2>&1
Mais le traitement de chaque ligne jusqu'à la fin de la commande, puis le passage à la suivante prennent beaucoup de temps, je veux par exemple traiter 20 lignes à la fois, puis quand elles sont terminées, 20 autres lignes sont traitées.
J'ai pensé wget LINK1 >/dev/null 2>&1 &
envoyer la commande en arrière-plan et continuer, mais il y a 4000 lignes ici, cela signifie que j'aurai des problèmes de performances, sans parler du nombre limité de processus que je devrais démarrer en même temps, donc ce n'est pas une bonne chose idée.
Une solution à laquelle je pense en ce moment est de vérifier si l'une des commandes est toujours en cours d'exécution ou non, par exemple après 20 lignes, je peux ajouter cette boucle:
while [ $(ps -ef | grep KEYWORD | grep -v grep | wc -l) -gt 0 ]; do
sleep 1
done
Bien sûr, dans ce cas, je devrai ajouter & à la fin de la ligne! Mais je sens que ce n'est pas la bonne façon de procéder.
Alors, comment puis-je réellement regrouper chaque 20 lignes et attendre qu'elles se terminent avant de passer aux 20 lignes suivantes, ce script est généré dynamiquement afin que je puisse faire les calculs que je veux dessus pendant qu'il est généré, mais il N'EST PAS obligé utilisez wget, c'était juste un exemple, donc toute solution spécifique à wget ne me fera aucun bien.
wait
est la bonne réponse ici, mais votrewhile [ $(ps …
serait beaucoup mieux écritwhile pkill -0 $KEYWORD…
- en utilisant proctools … c'est-à-dire, pour des raisons légitimes, de vérifier si un processus avec un nom spécifique est toujours en cours d'exécution.Réponses:
Utilisez le
wait
intégré:Pour l'exemple ci-dessus, 4 processus
process1
...process4
seraient démarrés en arrière-plan, et le shell attendrait qu'ils soient terminés avant de démarrer l'ensemble suivant.Dans le manuel GNU :
la source
i=0; waitevery=4; for link in "${links[@]}"; do wget "$link" & (( i++%waitevery==0 )) && wait; done >/dev/null 2>&1
Voir parallèle . Sa syntaxe est similaire à
xargs
, mais il exécute les commandes en parallèle.la source
wait
, car il prend soin de démarrer de nouveaux travaux lorsque les anciens sont terminés, au lieu d'attendre la fin d'un lot avant de commencer le suivant.cat list_of_links.txt | parallel -j 4 wget {}
ce qui gardera quatrewget
s en cours d'exécution à la fois.parallel
.parallel --jobs 4 < list_of_commands.sh
, où list_of_commands.sh est un fichier avec une seule commande (par exemplewget LINK1
, note sans le&
) sur chaque ligne. Peut-être besoin de le faireCTRL+Z
etbg
après de le laisser fonctionner en arrière-plan.En fait,
xargs
peut exécuter des commandes en parallèle pour vous. Il existe une-P max_procs
option de ligne de commande spéciale pour cela. Tu voisman xargs
.la source
Vous pouvez exécuter 20 processus et utiliser la commande:
Votre script attendra et continuera lorsque tous vos travaux en arrière-plan seront terminés.
la source