Bash Script - Idea Check

Hi all,

I’m working on a script to automate some stuff. The catch with this script is that if any action fails, it needs to “rollback” all the actions it just performed.

After thinking for a bit, I thought instead of having a billion if statements, I would put each command into an array:


CMD[0]='command';
CMD[1]='command';
# ...

Then I could run them in sequence. I would then make another array which had the expected string so I can check against it and see if it worked or not:


EXPECTED[0]='expected';
EXPECTED[1]='expected';
# ...

Then I could also have an array of rollback actions to run.


ROLLBACK[0]='rollback';
ROLLBACK[1]='rollback';
# ...

So, to run this I would just loop through CMD and for each action, make sure it’s response was EXPECTED, and if not, I stop calling commands and then go back through ROLLBACK in reverse order starting at the index of the last good command.

Does anyone see a problem with this plan? More importantly, does anyone know a better way to do this?

Thanks.

That is a very clever approach. It seems, though, that it would be quite complex to develop.

Another (slight variant) approach would be to write a series of small scripts - each one performs a set of actions. You could call the scripts in sequence, with each returning a success code. If one fails, the “rollback” could be another script that gets called.

As I said, this is simply a variation on your creative idea. But it may prove easier to build, troubleshoot and expand as needed.

As you make progress on this, please post more details. I am VERY curious about your success.

Maybe this can offer a few other ideas: http://unix.stackexchange.com/questions/25809/implementing-rollback-in-bash

Thanks guys, that looks great.

Just to follow up, what I ended up doing was this:


add_action() {
	actions[${#actions[*]}]=$1;
	safe_rollback[${#safe_rollback[*]}]=$2;
}

run_actions() {
	I=0;
	while [ $I -le  ${#actions[@]} ]; do
		${actions[$I]};

		if [ $? -ne 0 ];
		then
			echo "Rollback" $I;

			J=$I;			
			while [ $J -ge 0 ]; do
				${safe_rollback[$J]};
				$J=$(($J+1));
			done;

			exit 1;
		fi

		I=$(($I+1));
	done
}

actions=( );
safe_rollback=( );

Then to use it, you create an action function and a rollback function for that action and add them:


my_action() { 
  echo "a";
}

rollback_my_action() {
  echo "rollback";
}

You then add it with the add_action function:


add_action my_action rollback_my_action;

Then at the end you run all of them:


run_actions;

If any of them return a code that isn’t 0, it will rollback that action and all previous actions as well, going in reverse order.