De alguma forma, posso adicionar um "&& prog2" a um prog1 já em execução?

87

A maioria dos shells fornece funções como &&e ;encadear a execução de comandos de certas maneiras. Mas e se um comando já estiver em execução, ainda assim posso adicionar outro comando a ser executado, dependendo do resultado do primeiro?

Diga que eu corri

$ /bin/myprog
some output...

mas eu realmente queria /bin/myprog && /usr/bin/mycleanup. Não posso matar myproge reiniciar tudo, porque muito tempo seria perdido. Eu posso Ctrl+ Ze fg/ bgse necessário. Isso me permite encadear outro comando?

Estou interessado principalmente no bash, mas as respostas para todas as conchas comuns são bem-vindas!

us2012
fonte

Respostas:

118

Você deve conseguir fazer isso no mesmo shell em que está com o waitcomando:

$ sleep 30 &
[1] 17440

$ wait 17440 && echo hi

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

trecho da página de manual do 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
fonte
A espera do comando deve fazer o trabalho.
BillThor
Existem vários formulários curtos para inserir o PID do processo em segundo plano, como %, %1e $!. É importante fornecer o PID ou o segundo comando sempre será executado.
BillThor
@ BillThor - você está apenas qualificando a resposta ou me dizendo isso?
slm
Estou qualificando a resposta. Uma planície waitfalhará em fornecer o resultado desejado. É comum usar os formulários curtos, pois são menos propensos a erros de digitação.
BillThor
2
Deixe-me ser o primeiro a felicitá-lo em seu novo emblema brilhante :)
terdon
63

fgretorna com o código de saída do programa em que é retomado. Portanto, você pode suspender seu programa ^Ze usá fg && ...-lo para continuar.

$ /bin/myprog
some output...
^Z
[1]+ Stopped              /bin/myprog
$ fg && /usr/bin/mycleanup
John Kugelman
fonte
se você suspender novamente antes que ele termine e faça o mesmo com um comando diferente, o encadeamento inicial do mycleanup será substituído?
quer
3
@BurhanAli Suspender myprogpela segunda vez faz fgcom que o código de saída 20 seja finalizado - diferente de zero, portanto o mycleanupcomando em cadeia não é executado.
n.st 4/01/14
1

Não tenho certeza se o que você está pedindo é possível, mas se você ainda possui o shell do qual iniciou o programa, sempre pode verificar $?o status de saída do último processo:

$ /bin/myprog
some output...
$ if [ $? -ne 0 ];then echo "non-zero exit status";else echo "0 exit status";fi
Joseph R.
fonte
1
Isso funcionará, mas ele precisará executá-lo manualmente posteriormente; ele desejará executá-lo automaticamente quando o comando terminar.
Slm
@slm Concordou. Não tenho uma solução para esse problema exato.
Joseph R.
3
Confira o waitcomando no Bash.
Slm
1

Se o trabalho estiver em primeiro plano, qualquer um desses comandos terá o mesmo comportamento esperado.

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

NOTA: $? conterá o status de retorno do programa em execução quando ele sair.

Isso indica explicitamente o que o shell faria se você tivesse digitado o comando originalmente.

prog1 && prog2

Se o primeiro comando não estiver lendo stdine estiver sendo executado em primeiro plano, o novo comando poderá ser inserido enquanto o primeiro comando estiver em execução. O shell irá lê-lo e executá-lo quando o primeiro comando for executado. Se o comando for executado em segundo plano, é improvável que esteja lendo stdin.

EDIT: Colocar o trabalho em segundo plano e usar o WAITcomando também pode ser usado. Isso deve ser feito com cuidado se outros trabalhos também foram executados em segundo plano. Uma especificação de trabalho é necessária para que o WAITcomando retorne o status do trabalho aguardado.

BillThor
fonte
Isso funcionará, mas ele precisará executá-lo manualmente posteriormente; ele desejará executá-lo automaticamente quando o comando terminar.
Slm
4
@slm Enquanto o comando não estiver lendo stdin, o novo comando poderá ser inserido enquanto o primeiro comando estiver em execução. O shell irá lê-lo assim que o primeiro comando for concluído.
BillThor
Se ele fizer alguma coisa no invólucro depois de ter sido usado como pano de fundo, é provável que seja lavado. Pelo menos de acordo com o prelim. testes que venho fazendo até agora!
slm
2
@ BillThor Acho que você deve adicionar esse comentário à sua resposta.
Joseph R.
2
Sim, o uso waittambém não é ideal. A vantagem, IMO, é que ela nos fornece uma API mais clara com a qual estamos lidando. Digitar mais comandos na linha de comando depois que algo está em execução parecia um pouco hacky para mim. waitainda sofre por não obter um link direto para o PID em execução, escreve o status de retorno. Este parece ser um problema mais com o modo como o Bash implementa as coisas: stackoverflow.com/questions/356100/… . Portanto, isso pode ser o melhor possível.
Slm