Posso in qualche modo aggiungere un "&& prog2" a un prog1 già in esecuzione?


87

La maggior parte delle shell fornisce funzioni simili &&e ;concatenare l'esecuzione dei comandi in determinati modi. Ma cosa succede se un comando è già in esecuzione, posso comunque aggiungere un altro comando da eseguire a seconda del risultato del primo?

Di 'che ho corso

$ /bin/myprog
some output...

ma volevo davvero /bin/myprog && /usr/bin/mycleanup. Non posso uccidere myproge riavviare tutto perché si perderebbe troppo tempo. Posso Ctrl+ Ze fg/ bgse necessario. Questo mi permette di concatenare un altro comando?

Sono principalmente interessato a bash, ma le risposte a tutte le shell comuni sono benvenute!

Risposte:


118

Dovresti essere in grado di farlo nella stessa shell in cui ti trovi con il waitcomando:

$ sleep 30 &
[1] 17440

$ wait 17440 && echo hi

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

estratto dalla pagina man di 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.

In attesa del comando dovrebbe fare il lavoro.
BillThor,

Esistono numerosi moduli brevi per inserire il PID del processo in background come %, %1e $!. È importante fornire il PID o il secondo comando verrà sempre eseguito.
BillThor,

@BillThor - stai solo qualificando la risposta o me lo stai dicendo?
slm

Sto qualificando la risposta. Una pianura waitnon riuscirà a fornire il risultato desiderato. È comune usare le forme brevi in ​​quanto sono meno inclini a errori di battitura.
BillThor,

2
Vorrei essere il primo a congratularmi con te per il tuo nuovo brillante badge :)
Terdon

63

fgritorna con il codice di uscita dal programma che riprende. È quindi possibile sospendere il programma con ^Ze quindi utilizzarlo fg && ...per riprenderlo.

$ /bin/myprog
some output...
^Z
[1]+ Stopped              /bin/myprog
$ fg && /usr/bin/mycleanup

se sospendi di nuovo prima che finisca e fai la stessa cosa con un comando diverso, il concatenamento iniziale di mycleanup viene sostituito?
Burhan Ali,

3
@BurhanAli La sospensione myprogper la seconda volta provoca la fgchiusura con il codice di uscita 20, che è diverso da zero, quindi il mycleanupcomando incatenato non viene eseguito.
n.

1

Non sono sicuro se ciò che stai chiedendo sia possibile, ma se hai ancora la shell da cui hai avviato il programma, puoi sempre verificare $?lo stato di uscita dell'ultimo processo:

$ /bin/myprog
some output...
$ if [ $? -ne 0 ];then echo "non-zero exit status";else echo "0 exit status";fi

1
Funzionerà, ma dovrà eseguirlo manualmente in seguito, vorrà eseguirlo automaticamente al termine del comando.
slm

@slm Concordato. Non ho una soluzione per questo esatto problema.
Joseph R.

3
Controlla il waitcomando in Bash.
slm

1

Se il lavoro è in primo piano, uno di questi comandi avrebbe lo stesso comportamento previsto.

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

NOTA: $? conterrà lo stato di ritorno del programma in esecuzione quando esce.

Questo sta esplicitamente affermando cosa farebbe la shell se tu avessi inserito il comando in origine.

prog1 && prog2

Se il primo comando non sta leggendo stdined è in esecuzione in primo piano, è possibile immettere il nuovo comando mentre è in esecuzione il primo comando. La shell lo leggerà ed eseguirà quando viene eseguito il primo comando. Se il comando verrà eseguito in background, è improbabile che stia leggendo stdin.

EDIT: è WAITinoltre possibile utilizzare il processo in background e l'utilizzo del comando. Questo deve essere fatto con cura se anche altri lavori sono stati eseguiti in background. È richiesta una specifica di lavoro affinché il WAITcomando restituisca lo stato del lavoro in attesa.


Funzionerà, ma dovrà eseguirlo manualmente in seguito, vorrà eseguirlo automaticamente al termine del comando.
slm

4
@slm Finché il comando non legge stdin, il nuovo comando può essere inserito mentre il primo comando è in esecuzione. La shell lo leggerà non appena viene eseguito il primo comando.
BillThor,

Se fa qualcosa nel guscio dopo che è stato messo in background, è probabile che venga eliminato. Almeno secondo il prelim. test che ho fatto finora!
slm

2
@BillThor Penso che dovresti aggiungere quel commento alla tua risposta.
Joseph R.

2
Sì, anche l'utilizzo waitnon è l'ideale. Il vantaggio, IMO, è che ci fornisce un'API più chiara con cui abbiamo a che fare. Digitare più comandi sulla riga di comando dopo che qualcosa è in esecuzione mi è sembrato un po 'confuso. waitsoffre ancora di non ottenere un collegamento diretto al PID in esecuzione, scrivendo lo stato di ritorno. Questo sembra essere un problema in più grazie a come Bash implementa le cose: stackoverflow.com/questions/356100/… . Quindi questo potrebbe essere il massimo.
slm
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.