在 bash 中实现回滚

Šim*_*óth 4 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) 
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 5

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

  • 如果您运行set -e,那么如果命令返回非零状态,shell 将立即退出(除非在明显的情况下,例如ifwhile条件)。
  • 如果您运行trap 'somecode' EXIT,那么如果脚本退出(显式或隐式因为set -e),somecode则首先执行。进入 时somecode$?包含上一个命令的状态。

因此你可以写一些类似的东西

(set -e; trap 'abort operation a' EXIT; perform operation a; )
Run Code Online (Sandbox Code Playgroud)

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

set -e
operation_a () {
  trap 'abort code' ERR
  perform operation a
}
Run Code Online (Sandbox Code Playgroud)

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