Implementando o rollback no bash

4

Eu tenho um script que é composto de operações preparadas que funcionam principalmente em uma maneira de iniciar / parar / status.

O problema que tenho é que, ao iniciar, cada uma das operações pode falhar e eu preciso fazer um rollback seguro usando as ações de parada.

Como eu poderia fazer isso no bash?

Eu estava pensando em algo como o seguinte (que não funciona):

operation1_start() {}
operation2_start() {}
operation1_stop() {}
operation2_stop() {}

operation1_start && rollback=operation1_stop;$rollback
test_validity || $($rollback)
operation2_start && rollback=operation2_stop;$rollback
test_validity || $($rollback) 
    
por Let_Me_Be 30.11.2011 / 20:58

3 respostas

1

Na verdade, consegui implementar isso usando matrizes. Parece funcionar bem (eu até adicionei um parâmetro extra dizendo as funções, que isso é uma reversão).

abc()
{
    echo "abc----$1";
}

cda()
{
    echo "cda----$1";
}

safe_rollback=( )

add_rollback()
{
    safe_rollback[${#safe_rollback[*]}]=$1;
}

run_rollback()
{
    while [ ${#safe_rollback[@]} -ge 1 ]; do
        ${safe_rollback[${#safe_rollback[@]}-1]} rollback;
        unset safe_rollback[${#safe_rollback[@]}-1];
    done
}

add_rollback cda
add_rollback abc
run_rollback
    
por 30.11.2011 / 23:59
2

Você encontrará estas duas técnicas de programação de shell úteis:

  • Se você executar set -e , o shell será encerrado imediatamente se um comando retornar um status diferente de zero (exceto nos casos em que isso obviamente significa, como if ou while condicionais).
  • Se você executar trap 'somecode' EXIT , então, se o script sair (seja explicitamente ou implicitamente por causa de set -e ), somecode é executado primeiro. Na entrada em somecode , $? contém o status do último comando.

Assim, você pode escrever algo como

(set -e; trap 'abort operation a' EXIT; perform operation a; )

No bash, você pode definir um trap em ERR em vez de EXIT ; tais traps são executados somente se o shell sair devido a set -e . Além disso, ERR traps são locais para funções.

set -e
operation_a () {
  trap 'abort code' ERR
  perform operation a
}

Quando você puder, é mais fácil preparar primeiro um rascunho e, em seguida, executar uma operação atômica para confirmar sua transação. Por exemplo, se você estiver gravando em um arquivo, grave em um arquivo temporário no diretório de destino e, em seguida, chame mv para colocar o novo arquivo no lugar. Isso é muito mais robusto do que qualquer coisa que exija limpeza na forma de código de reversão, porque a reversão não será executada se o script morrer devido a uma kill -9 ou falta de energia.

    
por 01.12.2011 / 03:09
1

Sua operação realmente soa como um clone de um processo de compilação, em que você tem ações de tipo start / status / continue / rollback / stop com base em várias situações. Você provavelmente conseguirá esse efeito mais elegantemente se você usou Makefiles em conjunto com seus scripts de shell, porque as interdependências que determinam o estado são mais elegantemente definíveis lá.

    
por 01.12.2011 / 06:37

Tags