suspendre un script bash jusquà ce que les commandes précédentes soient terminées

Jai un script bash qui ressemble à ce qui suit:

##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done 

Je voudrais créer une autre boucle for après la première pour continuer pendant 30. Par exemple

##script #!/bin/bash rm data* rm logfile* for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done 

Je voudrais le premier ensemble de travaux à terminer avant de démarrer le nouvel ensemble. Mais à cause des nohup, il semble quils soient tous exécutés simultanément.

Jai nohup parce que je me connecte à distance à mon serveur et démarre les travaux là-bas, puis ferme mon bash. Existe-t-il une solution alternative?

Commentaires

  • Recherchez dans le manuel le wait intégré.

Réponse

Vous « voudrez utiliser la commande wait pour faites-le pour vous. Vous pouvez soit capturer tous les ID de processus enfants et les attendre spécifiquement, soit sil sagit des seuls processus darrière-plan que votre script crée, vous pouvez simplement appeler wait sans argument. Par exemple:

#!/bin/bash # run two processes in the background and wait for them to finish nohup sleep 3 & nohup sleep 10 & echo "This will wait until both are done" date wait date echo "Done" 

Réponse

Quelques points:

  • Si votre objectif avec nohup est dempêcher une sortie shell distante de tuer vos processus de travail, vous devez utiliser nohup sur le script lui-même, pas sur les processus de travail individuels quil crée.

  • Comme expliqué ici , nohup empêche uniquement les processus de recevoir SIGHUP et dinteragir avec le terminal, mais cela ne rompt pas la relation entre le shell et ses processus enfants.

  • À cause du point ci-dessus, avec ou sans nohup, un simple wait entre les deux for boucles provoquera la deuxième for à exécuter uniquement après la fermeture de tous les processus enfants lancés par le premier for.

  • Avec un simple wait:

    tous les processus enfants actuellement actifs sont attendus et le statut de retour est zéro.

  • Si vous devez exécuter le deuxième for uniquement sil ny a pas eu derreur dans le premier , alors vous « devrez enregistrer chaque PID worker avec $!, et les transmettre tous à wait:

    pids= for ... worker ... & pids+=" $!" done wait $pids || { echo "there were errors" >&2; exit 1; } 

Commentaires

  • Il y a cou ld être dautres travaux en cours dexécution sur le serveur. Donc je ' ne veux attendre que mon lot .. ce sont des scripts R donc ils sont exécutés sous R ou cc1plus dans la commande top
  • Aussi ' jaimerais utiliser nohup à lintérieur pour exécuter toutes les commandes en " parallel ". ce sont essentiellement des simulations pour un programme scientifique. Je souhaite exécuter 180 simulations au total, mais par lots de 60. Le compteur doit également passer de 1 à 180. Si je les fais une à la fois, cela prendra trop de temps.
  • wait fait que bash attend les travaux darrière-plan quil a générés, rien dautre. Il pourrait y avoir une certaine confusion ici – ces boucles for, les avez-vous sauvegardées dans un fichier et les avez-vous appelées en tant que script (ce que jai supposé, à cause du ##script), ou les saisissez-vous à la main dans le terminal?
  • Jétais en train de faire cat file.txt | while et les pids nétaient pas définis en dehors de la boucle la commande wait a donc vu une chaîne $pids vide. pourquoi cela se produit est expliqué à serverfault.com/q/259339 . facilement corrigé comme while ... < files.txt comme répondu à serverfault.com/a/259346
  • Juste curieux à quoi sert le signe + avec la variable pids?

Réponse

Utilisez le fg intégré. Il attend la fin des processus darrière-plan.

Essayez help fg pour plus de détails.

Commentaires

  • Un script sexécute sans contrôle de tâche.

Réponse

Si vous insérez quelque chose comme le segment de code suivant entre vos deux boucles for, cela peut aider.

flag=0 while [ flag -eq 0 ] do ps -ef | grep "Rscript --vanilla" | grep -v grep > /dev/null flag=${?} sleep 10 done 

Bien sûr, si votre application Rscript a une chance de ne pas réussir et de persister, votre deuxième boucle for peut ne pas avoir une chance de sexécuter. Le segment de code ci-dessus suppose que tous les processus avec lidentificateur Rscript --vanilla se termineront et disparaîtront correctement. Sans savoir ce que fait votre application et comment elle fonctionne, je dois me fier à cette hypothèse.

EDIT

À la lumière des commentaires, cela conviendrait mieux vos besoins. (il inclut votre code dorigine ainsi que la logique de vérification dachèvement)

for i in {1..30} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & pids[$i]=${!} done flag=0 while [ flag -eq 0 ] do for PID in $(echo ${pids[@]}) do flag=1 ps -ef | grep ${PID} | grep -v grep >/dev/null; r=${?} if [ ${r} -eq 0 ] then flag=0 fi done done for i in {31..60} do ## append a & if you want to run it parallel; nohup Rscript --vanilla main.R 10 100 $i &> logfile"$i" & done 

Commentaires

  • Le processus nom dans top affiche parfois R ou cc1plus.
  • Dans ce cas, vous devrez trouver un dénominateur commun, apparaissant dans la liste ps -ef. Ou après chaque commande nohup, enregistrez le PID dans une variable (de préférence un tableau) par echo ${!} et vérifiez ce groupe de PID. Lorsquils disparaissent tous, vous pouvez passer à la deuxième for boucle

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *