Como faço para suspender e retomar a cadeia 'cmd1 && cmd2 && cmd3'?

5

Do pergunta anterior parece que não consegui entender como && e ^Z interagem corretamente:

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

, que eu acho que pode ser usado para "anexar" a cadeia depois de iniciada, pareceu funcionar apenas porque command3 foi o último comando; e pará-lo em command2 , por exemplo, deve ter fornecido resultado diferente ( command3 que deveria ter sido ignorado).

Como faço para suspender a corrente && normalmente, sem cancelar o restante dos comandos? Eu quero também que o código de saída seja preservado se for necessário para mais lógica na linha de comando.

Se eu souber que posso querer suspender a cadeia antecipadamente, posso começar assim: ( command1 && command2 && command3 ) , para que ela seja graciosamente suspensa. Buw como faço quando é iniciado claramente?

Se os comandos não fornecem saída (ao contrário do exemplo acima), não devem ser executados duas vezes ou fora de ordem, então a única maneira de pensar é pressionando ^Z , analisando o que foi parado e construindo manualmente fd && the_rest_of_commands , que é inconveniente e propenso a erros.

    
por Vi. 21.08.2014 / 14:23

3 respostas

2

Eu acho que você está interpretando mal o que está acontecendo. Quando você faz:

cmd1 && cmd2

O shell inicia cmd1 em um processo filho, aguarda esse processo e, em seguida, inicia cmd2 se cmd1 sair com um status de saída zero.

Se você pressionar Ctrl + Z , a espera retornará, o shell definirá $? para 148 por exemplo (128 + SIGTSTP) e a avaliação do restante será feita naquele point , então cmd2 é não executado. E cmd1 se torna um trabalho em segundo plano.

Você digitou:

cmd1 || cmd2

Ou:

cmd1; cmd2

cmd2 teria sido executado em Ctrl-Z e você teria que esperar que ele terminasse para obter o próximo prompt (em que você pode fg ou bg do seu trabalho em segundo plano).

Em zsh , quando você pressiona Ctrl-Z em:

{cmd1 && cmd2 && cmd3}

Isso suspende todo o grupo (e o move para um subshell). No entanto, ao reiniciar, o comando suspenso, quando terminar, definirá $? para 20, independentemente de seu status de saída, e não acho que haja uma maneira de contornar isso, então você acaba com o mesmo comportamento (embora em {cmd1 || cmd2} O cmd2 seria executado após o término do cmd1, em vez de seguir diretamente para o Ctrl-Z ).

    
por 21.08.2014 / 15:10
1

Parece que suspender o componente em execução no momento com gdb -p provices pausa normal, ao contrário de kill -STOP .

Então, se você sabe que command2 está sendo executado, você pode fazer:

gdb -p $(pgrep -f 'command2')

de outro terminal para suspender, depois saia ou continue o GDB para continuar.

    
por 21.08.2014 / 15:52
0

Você pode suspender o shell pai - o shell interativo em que você está iniciando os comandos:

Imprima o PID antes de executar os comandos (ou encontre o pid mais tarde, veja abaixo):

$ echo $$
1234

De outro terminal, você pode parar toda a lista de comandos suspendendo o shell interativo - a lista consiste em processos filhos do shell interativo:

$ kill -STOP 1234

Continue a lista de comandos com:

$ kill -CONT 1234


Como é uma parte importante do seu caso de uso que não há preparações (como echo $$ ) necessárias antes de executar a lista de comandos, aqui está como você obtém o PID do shell que deseja interromper quando a lista já está sendo executada em primeiro plano.

A ideia é encontrar o PID do processo pai de qualquer um dos comandos na lista:

Primeiro, usamos pgrep para encontrar o PID do comando atualmente em execução. Encontrar o PID de qualquer um deles é suficiente, pois apenas um é executado por vez:

$ pgrep 'command1|command2|command3'

Se command1 etc não for realmente o nome do comando do processo - ou seja, a primeira palavra da linha de comando - você precisará adicionar a opção -f (e usar -a para experimentar para ver mais de apenas o PID):

$ pgrep -f 'command1|command2|command3'

Em seguida, usamos ps para encontrar o PID pai do comando:

$ ps -o ppid= 

Combinados, nós temos o PID do shell para suspender assim:

$ pid=$(ps -o ppid= $(pgrep 'command1|command2|command3'))

No total:

$ kill -STOP $(ps -o ppid= $(pgrep 'command1|command2|command3'))
$ kill -CONT $(ps -o ppid= $(pgrep 'command1|command2|command3'))
    
por 21.08.2014 / 14:52

Tags