J'ai un script batch qui démarre quelques travaux qsub, et je veux intercepter quand ils sont tous terminés.
Je ne veux pas utiliser l'option -sync, car je veux qu'ils s'exécutent simultanément. Chaque travail a un ensemble différent de paramètres de ligne de commande.
Je veux que mon script attende que tous les travaux soient terminés et fasse quelque chose après. Je ne veux pas utiliser la fonction sommeil, par ex. pour vérifier si certains fichiers ont été générés toutes les 30 s, car il s'agit d'un épuisement des ressources.
Je crois que Torque peut avoir certaines options, mais j'utilise SGE.
Des idées sur la façon dont je pourrais mettre en œuvre ceci s'il vous plaît?
Merci P.s. J'ai trouvé un autre fil Lien
qui a eu une réponse
Vous pouvez utiliser wait pour arrêter l'exécution jusqu'à ce que tous vos travaux soient terminés. Vous pouvez même collecter tous les états de sortie et autres statistiques en cours d'exécution (le temps qu'il a fallu, le nombre de travaux effectués à l'époque, peu importe) si vous faites le tour en attendant des identifiants spécifiques.
mais je ne sais pas comment l'utiliser sans interroger sur une certaine valeur. Peut-on utiliser bash trap, mais comment le ferais-je avec qsub?
Lancez vos jobs qsub, en utilisant l'option -N pour leur donner des noms arbitraires (job1, job2, etc.):
qsub -N job1 -cwd ./job1_script
qsub -N job2 -cwd ./job2_script
qsub -N job3 -cwd ./job3_script
Lancez votre script et dites-lui d'attendre la fin des travaux nommés job1, job2 et job3 avant de commencer:
qsub -hold_jid job1,job2,job3 -cwd ./results_script
Une autre alternative (de ici ) est la suivante:
FIRST=$(qsub job1.pbs)
echo $FIRST
SECOND=$(qsub -W depend=afterany:$FIRST job2.pbs)
echo $SECOND
THIRD=$(qsub -W depend=afterany:$SECOND job3.pbs)
echo $THIRD
L'idée est que qsub renvoie l'ID de travail, ce qui est généralement transféré vers la sortie standard. Au lieu de cela, capturez-le dans une variable ($FIRST
, $SECOND
, $THIRD
) et utilisez le -W depend=afterany:[JOBIDs]
flag lorsque vous mettez vos jobs en file d'attente pour contrôler la structure de dépendance du moment où ils sont retirés de la file d'attente.
Si tous les travaux ont un modèle commun dans le nom, vous pouvez fournir ce modèle lorsque vous soumettez les travaux. https://linux.die.net/man/1/sge_types vous montre quels modèles vous pouvez utiliser. exemple:
-hold_jid "job_name_pattern*"
qsub -hold_jid job1,job2,job3 -cwd ./myscript
Cela fonctionne en bash, mais les idées doivent être portables. Utilisation -terse
pour faciliter la création d'une chaîne avec des ID de tâche à attendre; puis soumettez un travail factice qui utilise -hold_jid
pour attendre les travaux précédents et -sync y
pour que qsub ne revienne pas tant qu'il n'a pas terminé (et donc tous les prérequis):
# example where each of three jobs just sleeps for some time:
job_ids=$(qsub -terse -b y sleep 10)
job_ids=job_ids,$(qsub -terse -b y sleep 20)
job_ids=job_ids,$(qsub -terse -b y sleep 30)
qsub -hold_jid ${job_ids} -sync y -b y echo "DONE"
-terse
L'option fait que la sortie de qsub est juste l'ID du travail-hold_jid
option (comme mentionné dans d'autres réponses) fait attendre un travail sur les identifiants de travail spécifiés-sync y
option (référencée par l'OP) demande à qsub de ne pas revenir tant que le travail soumis n'est pas terminé-b y
spécifie que la commande n'est pas un chemin vers un fichier de script (par exemple, j'utilise sleep 30
comme commande)Voir page de manuel pour plus de détails.
Dans le cas où vous souhaitez traiter 150 fichiers et ne pouvoir en exécuter que 15 à chaque fois, tandis que les autres sont dans la file d'attente, vous pouvez définir quelque chose comme ça.
# split my list files in a junk of small list having 10 file each
awk 'NR%10==1 {x="F"++i;}{ print > "list_part"x".txt" }' list.txt
qsoumettez tous les travaux de telle manière que le premier de chaque list_part * .txt contienne le second .... le second contienne le troisième ..... et ainsi de suite.
for list in $( ls list_part*.txt ) ; do
PREV_JOB=$(qsub start.sh) # create a dummy script start.sh just for starting
for file in $(cat $list ) ; do
NEXT_JOB=$(qsub -v file=$file -W depend=afterany:$PREV_JOB myscript.sh )
PREV_JOB=$NEXT_JOB
done
done
Ceci est utile si vous avez dans myscript.sh une procédure qui nécessite de déplacer ou de télécharger de nombreux fichiers ou de créer un trafic intense dans le cluster-lan
J'avais besoin de plus de flexibilité, j'ai donc construit un module Python à cet effet et à d'autres fins ici . Vous pouvez exécuter le module directement en tant que script (python qsub.py
) Pour une démo.
Usage:
$ git clone https://github.com/stevekm/util.git
$ cd util
$ python
Python 2.7.3 (default, Mar 29 2013, 16:50:34)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import qsub
>>> job = qsub.submit(command = 'echo foo; sleep 60', print_verbose = True)
qsub command is:
qsub -j y -N "python" -o :"/home/util/" -e :"/home/util/" <<E0F
set -x
echo foo; sleep 60
set +x
E0F
>>> qsub.monitor_jobs(jobs = [job], print_verbose = True)
Monitoring jobs for completion. Number of jobs in queue: 1
Number of jobs in queue: 0
No jobs remaining in the job queue
([Job(id = 4112505, name = python, log_dir = None)], [])
Conçu avec Python 2.7 et SGE puisque c'est ce que notre système fonctionne. Les seules bibliothèques Python non standard requises sont les modules tools.py
Et log.py
Inclus, et sh.py (également inclus)
Évidemment, ce n'est pas aussi utile si vous souhaitez rester purement dans bash
, mais si vous devez attendre des travaux qsub
, j'imagine que votre flux de travail se rapproche d'une complexité qui bénéficierait de l'utilisation de Python à la place.