我正试图找到一种方法来模拟函数中set -e
的行为,但仅限于该函数的范围内。
基本上,我想要一个函数,如果任何简单命令会触发set -e
,它会向上返回1级。目标是将多组风险工作隔离成函数,以便我可以优雅地处理它们。
答案 0 :(得分:3)
如果您希望任何失败的命令返回1,您可以通过使用|| return 1
跟随每个命令来实现此目的。
例如:
false || return 1 # This will always return 1
如果没有明确的处理,我绝不会让任何命令失败。对于我的脚本,我使用的是异常处理技术,我以不返回代码的方式返回错误,并捕获所有错误(使用bash陷阱)。任何带有非零返回码的命令都会自动意味着处理不当的情况或错误,我更喜欢我的脚本在发生这种情况时立即失败。
答案 1 :(得分:0)
警告:我强烈建议不要使用这种技术。如果在子shell环境中运行该函数,则几乎可以获得所需的行为。考虑:
#!/bin/bash
foo() ( # Use parens to get a sub-shell
set -e # Does not impact the main script
echo This is executed
false
echo This should *not* be executed
)
foo # Function call fails, returns 1
echo return: $?
# BUT: this is a good reason to avoid this technique
if foo; then # Set -e is invalid in the function
echo Foo returned 0!!
else
echo fail
fi
false # Demonstrates that set -e is not set for the script
echo ok
答案 2 :(得分:0)
好像你正在寻找“嵌套异常”,就像Java给出的那样。对于您确定范围的要求,如何在函数开头执行set -e
并确保在返回之前运行set +e
?
另一个不高效或方便的想法是在子shell中调用你的函数:
# some code
(set -e; my_function)
if [[ $? -ne 0 ]]; then
# the function didn't succeed...
fi
# more code
在任何情况下,请注意set -e
不是处理shell脚本错误的最佳方式。有太多问题使它变得非常不可靠。请参阅以下相关帖子:
我需要在生产环境中长时间存在的大型脚本采用的方法是:
mv
,cp
,mkdir
,ln
,rm
等。将仔细验证参数并处理异常-
# library of common functions
trap '_error_handler' ERR
trap '_exit_handler' EXIT
trap '_int_handler' SIGINT
_error_handler() {
# appropriate code
}
# other handlers go here...
#
exit_if_error() {
error_code=${1:-0}
error_message=${2:-"Uknown error"}
[[ $error_code == 0 ]] && return 0 # it is all good
# this can be enhanced to print out the "stack trace"
>&2 printf "%s\n" $error_message
# out of here
my_exit $error_code
}
my_exit() {
exit_code=${1:-0}
_global_graceful_exit=1 # this can be checked by the "EXIT" trap handler
exit $exit_code
}
# simple wrapper for cp
my_cp() {
# add code to check arguments more effectively
cp $1 $2
exit_if_error $? "cp of '$1' to '$2' failed"
}
# main code
source /path/to/library.sh
...
my_cp file1 file2
# clutter-free code
这有效地使用trap
对ERR
和EXIT
事件采取行动,这将是编写可靠shell脚本的好方法。
答案 3 :(得分:0)
进行更多研究,我在Google的Shell Style Guide中找到了一个我更喜欢的解决方案。这里有一些非常有趣的建议,但我认为为了便于阅读,我会选择这个:
if ! mv "${file_list}" "${dest_dir}/" ; then
echo "Unable to move ${file_list} to ${dest_dir}" >&2
exit "${E_BAD_MOVE}"
fi