Como posso cancelar / substituir um elemento da execução de 'cmd1 && cmd2 && cmd3 &&…' chain?

4
$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4 && wrong_command5 && command6
Running command3
Running command4

Como posso cancelar o wrong_command5 , agendando right_command5 após o término da execução atual de command4 ?

    
por Vi. 21.08.2014 / 03:36

2 respostas

2

Se command4 estiver atualmente em execução, é possível fazer isso de forma bem direta:

^Z
$ fg && right_command5 && command6

Isto é essencialmente o que você já estava fazendo para começar command4 em primeiro lugar. wrong_command5 e o restante será substituído e nunca executado.

Eu acho que esse comportamento vai ser inesperado para você, então continue lendo para uma explicação de onde as coisas não funcionam da maneira que você achava que seriam.

No entanto: observe que sua sequência de comando original não faz o que você acha que faz . Quando você faz:

$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4

então command2 será retomado, mas o resto da cadeia não será . Parar command2 com Ctrl-Z significa que ele sai anormalmente com SIGTSTP (-20). Como command2 sai sem sucesso, && produz curto-circuito e command3 nunca será executado. command4 será iniciado imediatamente após o final do command2 retomado.

Você pode assistir a esse comportamento em ação substituindo o && por || :

$ command2 || echo Running command3, exit was $?
^Z
[1]+  Stopped                 command2
Running command3, exit was 148
$

Você tem que listar toda a cadeia subseqüente de comandos quando você retomar, se você quiser o comportamento que você está procurando. Alternativamente, se você quiser parar e retomar cadeias de comando inteiras, você precisa executá-las em um subshell:

$ (command1 && command2 && command3)
^Z
$ fg

Nesse caso, porém, não há como interceder e substituir um comando.

    
por 21.08.2014 / 09:57
1

(Isso responde a uma versão anterior da pergunta, que foi bem diferente devido à omissão de um caractere. O segundo comando foi fg && command4 & wrong_command5 && command6 originalmente, e acabou sendo realmente significado como fg && command4 && wrong_command5 && command6 Isso responde a pergunta antiga com o comando background, veja outras respostas para a nova variante da questão)

O comando que você deseja cancelar está sendo executado em primeiro plano, e também é "encadeado" com o próximo comando por && . Se ele se comportar bem em ^C e sair com status diferente de zero, tudo está bem:

Para simplificar os exemplos, vou dividir esta linha:

$ fg && command4 & wrong_command5 && command6

nas linhas equivalentes:

$ fg && command4 & 
$ wrong_command5 && command6

Precisamos sair do programa de primeiro plano wrong_command5 e podemos fazê-lo facilmente com ^C .
Em seguida, listamos as tarefas em segundo plano para ver qual delas queremos aguardar. O ID do job é usado com o comando interno wait para aguardar o término do job.
Usamos o wait como o início da lista que executa o comando de substituição e, em seguida, o seguinte comando usado anteriormente.

$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4 & 
$ wrong_command5 && command6
^C
$ jobs
[1]  - running    command3
[2]  + running    command4
$ wait %2 && right_command5 && command6

Se wrong_command5 não se comportar bem ao obter um ^C do teclado, mas em algum outro sinal, você pode usar kill em vez de ^C da seguinte forma:

$ fg && command4 & 
$ wrong_command5 && command6
[1] 14407
^Z
[2]  + 14408 suspended  wrong_command5
$ jobs
[1]  - running    command3
[2]  + running    command4
[3]    suspended  wrong_command5
$ kill %2
[2]  + 14408 terminated  wrong_command5
$ wait %2 && right_command5 && command6
    
por 21.08.2014 / 06:27

Tags