Puis-je en quelque sorte ajouter un "&& prog2" à un prog1 déjà en cours d'exécution?

87

La plupart des shells fournissent des fonctions telles que &&et ;d'enchaîner l'exécution des commandes de certaines manières. Mais que se passe-t-il si une commande est déjà en cours d’exécution, puis-je quand même ajouter une autre commande à exécuter en fonction du résultat de la première?

Dis que j'ai couru

$ /bin/myprog
some output...

mais je voulais vraiment /bin/myprog && /usr/bin/mycleanup. Je ne peux pas tout tuer myproget tout redémarrer parce que trop de temps serait perdu. Je peux le Ctrl+ Zet fg/ bgsi nécessaire. Est-ce que cela me permet d'enchaîner une autre commande?

Bash m'intéresse surtout, mais les réponses à toutes les questions communes sont les bienvenues!

us2012
la source

Réponses:

118

Vous devriez pouvoir faire cela dans le même shell que celui dans lequel vous vous trouvez avec la waitcommande:

$ sleep 30 &
[1] 17440

$ wait 17440 && echo hi

...30 seconds later...
[1]+  Done                    sleep 30
hi

extrait de la page de manuel Bash

wait [n ...]
     Wait for each specified process and return its termination status. Each n 
     may be a process ID or a job specification; if a job spec is given,  all 
     processes  in that job's pipeline are waited for.  If n is not given, all 
     currently active child processes are waited for, and the return status is 
     zero.  If n specifies a non-existent process or job, the return status is 
     127.  Otherwise, the return status is the exit status of the last process 
     or job waited for.
slm
la source
En attente de la commande devrait faire le travail.
BillThor
Il existe un certain nombre de formulaires abrégés pour entrer le PID du processus en arrière-plan, tels que %, %1et $!. Il est important de fournir le PID sinon la deuxième commande sera toujours exécutée.
BillThor
@ BillThor - êtes-vous en train de qualifier la réponse ou de me le dire?
slm
Je qualifie la réponse. Un simple waitéchouera à fournir le résultat souhaité. Il est courant d’utiliser les formes abrégées car elles sont moins sujettes aux fautes de frappe.
BillThor
2
Permettez-moi d'être le premier à vous féliciter pour votre tout nouveau badge :)
terdon
63

fgretourne avec le code de sortie du programme qu'il reprend. Vous pouvez donc suspendre votre programme avec ^Zpuis l'utiliser fg && ...pour le reprendre.

$ /bin/myprog
some output...
^Z
[1]+ Stopped              /bin/myprog
$ fg && /usr/bin/mycleanup
John Kugelman
la source
si vous suspendez à nouveau avant la fin et que vous faites la même chose avec une commande différente, l'enchaînement initial de mycleanup est-il remplacé?
Burhan Ali
3
@BurhanAli Une myprogdeuxième suspension entraîne l' fgarrêt du code de sortie 20 - différent de zéro, de sorte que la mycleanupcommande chaînée n'est pas exécutée.
2014
1

Vous ne savez pas si ce que vous demandez est possible, mais si vous avez toujours le shell à partir duquel vous avez démarré le programme, vous pouvez toujours vérifier $?l'état de sortie du dernier processus:

$ /bin/myprog
some output...
$ if [ $? -ne 0 ];then echo "non-zero exit status";else echo "0 exit status";fi
Joseph R.
la source
1
Cela fonctionnera, mais il devra l'exécuter manuellement par la suite. Il voudra l'exécuter automatiquement à la fin de la commande.
slm
@slm D'accord. Je n'ai pas de solution à ce problème précis.
Joseph R.
3
Commander la waitcommande dans Bash.
slm
1

Si le travail est au premier plan, l'une ou l'autre de ces commandes aura le même comportement que prévu.

[ $? -eq 0 ] && prog2
(( $? )) || prog2

NOTE: $? contiendra le statut de retour du programme en cours lors de sa fermeture.

Ceci indique explicitement ce que le shell ferait si vous aviez initialement entré la commande.

prog1 && prog2

Si la première commande ne lit pas stdinet est exécutée au premier plan, vous pouvez entrer la nouvelle commande pendant l'exécution de la première. Le shell le lira et l'exécutera lors de l'exécution de la première commande. Si la commande s'exécute en arrière-plan, il est peu probable qu'elle soit en train de lire stdin.

EDIT: Vous WAITpouvez également utiliser le travail en arrière-plan et utiliser la commande. Cela doit être fait avec précaution si d'autres tâches ont également été exécutées en arrière-plan. Une spécification de travail est requise pour que la WAITcommande renvoie l'état du travail en attente.

BillThor
la source
Cela fonctionnera, mais il devra l'exécuter manuellement par la suite. Il voudra l'exécuter automatiquement à la fin de la commande.
slm
4
@slm Tant que la commande ne lit pas stdin, la nouvelle commande peut être entrée pendant l'exécution de la première commande. Le shell le lira dès que la première commande sera terminée.
BillThor
S'il fait quoi que ce soit dans la coquille une fois que celle-ci a été mise à fond, elle est probablement arrosée. Au moins selon le prelim. test que j'ai fait jusqu'à présent!
slm
2
@ BillThor Je pense que vous devriez ajouter ce commentaire à votre réponse.
Joseph R.
2
Oui, utiliser waitn'est pas idéal non plus. L'avantage, IMO, est que cela nous donne une API plus claire avec laquelle nous traitons. Taper plus de commandes sur la ligne de commande après que quelque chose soit en cours d’exploitation me paraissait un peu compliqué. waitsouffre toujours de ne pas obtenir un lien direct vers le PID en cours, en ce qui concerne le statut de retour. Cela semble être un problème plus lié à la façon dont Bash implémente les choses: stackoverflow.com/questions/356100/… . Cela pourrait donc être aussi bon que possible.
slm