Loop para executar múltiplas instruções no bash, que começam do topo se uma instrução falhar

0

Estou vendo uma maneira eficiente de fazer isso.

Eu tenho vários comandos que preciso executar em seqüência; o segundo não pode ser executado se o primeiro falhar e assim por diante.

eu passei por eles; mas o loop tem que passar por cada comando, o que não é o que preciso fazer.

Por exemplo, se houver 3 comandos: a, b e c; uma corrida o tempo todo, b rodando somente se um rodou com sucesso, e c tem que rodar somente se b rodou com sucesso, mas se b falhou uma vez, ele tem que começar tudo de um

LOOP *****************************
until a; do
  echo "a failed, retrying"
  sleep(3)
done
until b; do
  echo "b failed, need to start all over"
  b_failed=1
  break
  START FROM THE BEGIN OF LOOP ***************
done
until c; do
  echo "c failed, need to start all over from a"
  c_failed=1
  break
  START FROM THE BEGIN OF LOOP ***************
done
.... OTHER INSTRUCTIONS
LOOP *****************************

Eu tentei usar um loop regular, mas o intervalo sairá do loop secundário e não será iniciado desde o início. Eu gostaria de entrar neste loop principal, executar a primeira operação até que ela passe e depois executar a segunda; se falhar, inicie a partir da parte superior do loop, sem executar todos os outros comandos e assim por diante. Embora eu não consiga encontrar a maneira correta de fazer isso, a menos que eu inche a lógica com uma tonelada de if-else, verifique cada comando.

Existe uma maneira limpa de fazer isso em poucas linhas?

EDIT: escreveu enquanto em vez de até; fez a correção

EDIT2: Muito obrigado pela solução! Embora tenha que ser modificado, desde que eu não pude executá-lo como está: o if está faltando o fi para terminar o comando, e faltando a indicação "então". Não consegui executar o fazer dentro do if; então é isso que está funcionando para mim:

while true; do
    until a; do
        echo "a failed, retrying"
        sleep(3)
    done
    if [ ! b ]; then
        echo "b failed, need to start all over"
        continue
    else
        c
    fi
    if [ ! c ]; then
        echo "c failed, need to start all over from a"
        continue
    else
        break
    fi
done
    
por rataplan 09.09.2015 / 21:46

1 resposta

3

Uma solução muito simples, como mencionada em parte pela Squeezy:

until a && b && c; do
    :
done

&& é o lógico e o operador. Ele faz um curto-circuito, portanto, a expressão à direita é avaliada apenas quando a expressão à esquerda é verdadeira.

O valor de retorno da expressão && completa (ou cadeia de && s) é o resultado da última expressão avaliada. Então, se qualquer um dos três comandos falharem, os que aparecerem depois serão ignorados e o until verá um false e entrará em seu corpo, não faça nada ( : é apenas um não operacional para preencher o corpo de loop) e retorne à condição de teste a && b && c novamente. Se todos os três forem bem-sucedidos, o until verá um true e um fim.

Portanto, isso é bom para casos simples, mas não é bom se você quiser imprimir essas mensagens de status. É possível com || (o lógico ou) e { } , mas vai ser muito confuso.

Isso é melhor se você quiser fazer algo extra quando um comando falhar, como mensagens de status de eco:

while true; do
    until a; do
        echo "a failed, retrying"
        sleep(3)
    done
    if [ ! 'b' ]; then
        echo "b failed, need to start all over"
        continue
    fi
    if [ ! 'c' ]; then
        echo "c failed, need to start all over from a"
        continue
    fi
    break
done

continue retorna ao início do loop de fechamento. Colocando um número após ele retornar ao início do ciclo de fechamento n levels up. Embora isso não seja necessário aqui, porque eles estão dentro de if s em vez de loops. Incidentalmente, break vai pegar um número e sair de n fechando loops.

A seção a também pode ser um if [ ! a ]; em vez do until , se você preferir manter as coisas com a mesma aparência. Você precisaria adicionar um continue nesse caso.

    
por 09.09.2015 / 22:54