我编写了一个bash脚本,可以从源代码安装3个软件包。脚本非常简单,./configure
,make
,make install
语句写入三次(cd
进入源文件夹后)。为了使它看起来更清洁,我将输出重定向到另一个文件,如:./configure >> /usr/local/the_packages/install.log 2>&1
。
问题是,如果任何一个软件包由于某种原因而无法编译(我甚至不确定是什么原因,因为它一直成功运行到现在 - 这只是我要添加的内容),我'我希望终止脚本和回滚。
我想回滚只是删除prefix=/install/path
中指定的目标文件夹,但如何终止脚本呢?
答案 0 :(得分:2)
也许这样的事情可行:
./configure && make && make install || rm -rf /install/path
答案 1 :(得分:2)
您可以使用$?
bash变量检查脚本运行的返回代码。
moo@cow:~$ false
moo@cow:~$ echo $?
1
moo@cow:~$ true
moo@cow:~$ echo $?
0
您也可以直接将命令放入if
语句中来检查返回码。
moo@cow:~$ if echo a < bad_command; then echo "success"; else echo "fail"; fi
fail
可以使用!
字符反转命令的返回码。
moo@cow:~$ if ! echo a < bad_command; then echo "success"; else echo "fail"; fi
success
为了好玩,我决定根据你的问题编写这个脚本。
#!/bin/bash
_installed=()
do_rollback() {
echo "rolling back..."
for i in "${_installed[@]}"; do
echo "removing $i"
rm -rf "$i"
done
}
install_pkg() {
local _src_dir="$1"
local _install_dir="$2"
local _prev_dir="$PWD"
local _res=0
# Switch to source directory
cd "$_src_dir"
# Try configuring
if ! ./configure --prefix "$_install_dir"; then
echo "error: could not configure pkg in $_src_dir"
do_rollback
exit 1
fi
# Try making
if ! make; then
echo "error: could not make pkg in $_src_dir"
do_rollback
exit 1
fi
# Try installing
if ! make install; then
echo "error: could not install pkg from $_src_dir"
do_rollback
exit 1
fi
# Update installed array
echo "installed pkg from $_src_dir"
_installed=("${_installed[@]}" "$_install_dir")
# Restore previous directory
cd "$_prev_dir"
}
install_pkg /my/source/directory1 /opt/install/dir1
install_pkg /my/source/directory2 /opt/install/dir2
install_pkg /my/source/directory3 /opt/install/dir3
答案 2 :(得分:1)
分两部分:
要在任何命令返回错误时立即中止脚本,您需要使用set -e
。从手册页(BUILTINS部分; set
内置的描述):
-e
Exit immediately if a pipeline (which may consist of a single simple command),
a subshell command enclosed in parentheses, or one of the commands executed as
part of a command list enclosed by braces (see SHELL GRAMMAR above) exits with
a non-zero status. The shell does not exit if the command that fails is part of
the command list immediately following a while or until keyword, part of the
test following the if or elif reserved words, part of any command executed in a
&& or ││ list except the command following the final && or ││, any command in a
pipeline but the last, or if the command's return value is being inverted with
!. A trap on ERR, if set, is executed before the shell exits. This option
applies to the shell environment and each subshell environment separately (see
COMMAND EXECUTION ENVIRONMENT above), and may cause subshells to exit before
executing all the commands in the subshell.
你可以用三种方式设置它:将你的shebang线加到#!/bin/bash -e
;将脚本称为bash -e scriptname
;或者只是在脚本顶部附近使用set -e
。
问题的第二部分(解释)如何在退出前赶上出口并进行清理。上面引用了答案 - 您想要设置a trap on ERR
。
为了向您展示这些如何协同工作,这是一个简单的脚本运行。请注意,只要我们有一个非零退出代码,执行就会转移到负责清理的信号处理程序:
james@bodacious:tmp$cat test.sh
#!/bin/bash -e
cleanup() {
echo I\'m cleaning up!
}
trap cleanup ERR
echo Hello
false
echo World
james@bodacious:tmp$./test.sh
Hello
I'm cleaning up!
james@bodacious:tmp$