Interrompendo um loop for no bash, mas somente após uma iteração ser concluída?

4

Existe uma maneira de interromper / parar um para -loop em bash , mas somente após a iteração atual é completada - ie. "entre" feito e do ?

Estou executando um para -loop em vários diretórios, com um comando que pode ser destrutivo, a menos que seja permitido concluir - assim, gostaria de interrompê-lo quando o comando for concluído com um diretório, mas antes de começar no próximo.

(Sim, eu sei que eu poderia ter adicionado um comando sleep ou read antes feito - mas não , e o loop é já correndo ...)

    
por Baard Kopperud 09.01.2017 / 09:19

2 respostas

2

Para já em execução : assumindo que o comando é um programa e, portanto, é executado como um processo filho no shell executando o script (ou parte do mesmo), e o script não deu um heredoc ou herestring para entrada ou ele leu ou pelo menos armazenou essa entrada, você pode parar após o processo termina por:

  • kill -STOP o shell (para que ele não faça nada após o comando atual)
  • espere até que o processo filho termine e vá zumbi
  • kill -KILL o shell

(Tudo como o mesmo usuário ou root , de outro shell, é claro). Se o corpo do do ... done fizer duas ou mais coisas em cada iteração, isso só o captura após um programa que leva tempo suficiente em tempo real para obter o -STOP , que pode ou pode não será o último programa na iteração.

Em alguns (muitos?) casos, ele irá trabalhar simplesmente para kill -KILL o shell na frente, o que evita que o shell limpe seus filhos normalmente, e deixe o filho rodar e finalmente ser obtido por init (ou equivalente no seu sistema). No entanto, isso pode resultar na criança vendo alguns erros de E / S ou diferenças de ambiente ou erros ou variações com quaisquer netos que tenha, e isso ainda pode acionar os resultados 'destrutivos' que você está tentando evitar.

    
por 09.01.2017 / 13:55
0

Dependendo do que a iteração contém e de como ela é construída, você pode desvincular os executáveis e depois quebrá-lo. Por exemplo, o script é assim:

do_first_thing && \
do_second_thing && \
do_third_thing

Supondo que você pode desvincular / mover do_first_thing globalmente, ou seja, quando nenhum outro script precisar no momento, você:

  • desvincule-o ou renomeie-o para que o script não seja iniciado
  • assista em ps o progresso da iteração
  • quando o loop começa inativo se repete, você pode matá-lo.

Você também pode vincular o primeiro comando do script a outro script que contenha sleep ou read , o que dará a você tempo e oportunidade de interromper o ciclo de maneira inofensiva.

    
por 09.01.2017 / 15:19