在 bash 中实现回滚

在 bash 中实现回滚

我有一个由分阶段操作组成的脚本,这些操作主要以启动/停止/状态方式工作。

我遇到的问题是,启动时,每个操作都可能失败,我需要使用停止操作进行安全回滚。

我怎样才能在 bash 中做到这一点?

我正在考虑类似以下的事情(这是行不通的):

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) 

答案1

您会发现这两种 shell 编程技术很有用:

  • 如果你跑set -e,那么如果命令返回非零状态(除非有明显含义的情况,例如ifwhile条件),则 shell 立即退出。
  • 如果你跑trap 'somecode' EXIT,那么如果脚本退出(无论是显式退出,还是由于 隐式退出set -e),somecode首先执行。进入 时somecode$?包含最后一个命令的状态。

因此你可以写类似的东西

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

在 bash 中,您可以在 上 设置陷阱ERR而不是EXIT;仅当 shell 由于set -e.退出时才会执行此类陷阱。此外,ERR陷阱对于函数来说是局部的。

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

如果可以的话,首先准备草稿然后执行会更容易原子操作来提交您的交易。例如,如果您要写入文件,请写入目标目录中的临时文件,然后调用mv将新文件移动到位。这比需要以回滚代码形式进行清理的任何内容都要强大得多,因为如果您的脚本因kill -9电源故障而终止,则不会执行回滚。

答案2

我实际上设法使用数组来实现这一点。似乎工作正常(我什至添加了一个额外的参数告诉函数,这是一个回滚)。

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

答案3

您的操作实际上听起来像是构建过程的克隆,其中您可以根据各种情况执行启动/状态/继续/回滚/停止类型的操作。如果您将 Makefile 与 shell 脚本结合使用,您可能可以更优雅地实现该效果,因为可以更优雅地定义确定状态的相互依赖关系。

相关内容