当我读到这篇文章时回答$?我想到了另一个问题。
有没有关于如何使用 $ 的最佳实践?在bash中?
让我们举个例子:
我们有一个线性脚本,我们想知道所有命令都执行正常。您认为可以调用一个小函数(我们称之为“did_it_work”)来检查错误代码,如果不是则中断。
#!/bin/bash
function did_it_work {
code=$1
if [ "$code" -ne "0" ]
then
echo "Error failure: code $code "
exit 1
fi
}
dir=some/path
mkdir -p $dir
did_it_work $?
cd $dir
did_it_work $?
run_some_command
did_it_work $?
这种方法当然意味着我必须手动解决问题(如果有)并重新运行脚本。
您认为这是一个好主意还是有其他最佳实践可以做到这一点?
/谢谢
答案1
一种常见的方式是:
die() {
IFS=' ' # make sure "$*" is joined with spaces
# output the arguments if any on stderr:
[ "$#" -eq 0 ] || printf '%s\n' "$*" 1>&2
exit 1
}
然后你像这样使用它:
mkdir -p some/path || die "mkdir failed with status $?"
或者,如果您希望它包含退出状态,您可以将其更改为:
die() {
last_exit_status=$?
IFS=' '
printf '%s\n' "FATAL ERROR: $* (status $last_exit_status)" 1>&2
exit 1
}
然后使用它会更容易一些:
mkdir -p some/path || die "mkdir failed"
当它失败时,mkdir
可能已经发出错误消息,因此第二个可能被视为多余,您可以这样做:
mkdir -p some/path || exit # with the same (failing) exit status as mkdir's
mkdir -p some/path || exit 1 # with exit status 1 always
(或者使用上面的第一个变体die
而不带参数)
以防万一您command1 || command2
以前没有见过,它会运行command1
,如果command1
失败,它也会运行command2
。
所以你可以像“创建目录或死亡”一样阅读它。
你的例子看起来像:
mkdir -p some/path || die "mkdir failed"
cd some/path || die "cd failed"
some_command || die "some_command failed"
或者你可以dies
进一步靠右对齐,这样主要代码就更明显了。
mkdir -p some/path || die "mkdir failed"
cd some/path || die "cd failed"
some_command || die "some_command failed"
或者当命令行很长时在下面一行:
mkdir -p some/path ||
die "mkdir failed"
cd some/path ||
die "cd failed"
some_command ||
die "some_command failed"
另外,如果您要some/path
多次使用该名称,请将其存储在变量中,这样您就不必不断键入它,并且可以在需要时轻松更改它。当将变量参数传递给命令时,请确保使用选项--
分隔符,这样如果参数以 开头,则不会将其视为选项-
。
dir=some/path
mkdir -p -- "$dir" || die "Cannot make $dir"
cd -P -- "$dir" || die "Cannot cd to $dir"
some_command || die "Cannot run some_command"
答案2
你可以像这样重写你的代码:
#!/bin/bash
function try {
"$@"
code=$?
if [ $code -ne 0 ]
then
echo "$1 did not work: exit status $code"
exit 1
fi
}
try mkdir -p some/path
try cd some/path
try run_some_command
如果您实际上不需要记录错误代码,而只需要记录命令是否成功,则可以try()
进一步缩短,如下所示:
function try {
if ! "$@"
then
echo "$1 did not work"
exit 1
fi
}
答案3
如果您确实想exit
解决错误并且正在使用 Bash,那么您还应该考虑set -e
.从help set
:
-e 如果命令以非零状态退出,则立即退出。
这当然不会为您提供 did_it_work() 函数的灵活性,但这是一种确保 bash 脚本在出现错误时停止的简单方法,而无需向新函数添加大量调用。