我正在编写一个bash脚本来配置NFS服务器。我能够手动配置NFS服务器,并且该服务器功能齐全。 现在,我想在bash脚本中重现相同的步骤。 我有所有步骤,每一步,shell命令,我都放入了bash函数。 然后,我在一个主要部分中进行函数调用,总共有16个函数。 在主要部分中,我想检查函数的返回值,通常只是“ $?”。值
if [ "function_1" -eq "0" ]; then
echo "Success"
else
echo "Failure"
fi
由于有16个函数调用,因此每个函数调用都取决于先前的函数是否成功,因此整个过程变得有点荒唐
if [ "function_1" -eq "0" ]; then
if [ "function_2" -eq "0" ]; then
if [ "function_3" -eq "0" ]; then
if [ "function_..." -eq "0" ]; then
if [ "function_16" -eq "0" ]; then
我的问题是,这是构建程序的正确方法吗?还是根本不使用函数,而只在主要部分中进行命令验证?
chmod -R 0755 $SHARED_FILE_SYSTEM
if [ "$?" -eq "0" ]; then
echo "Success"
else
echo "Failure
fi
答案 0 :(得分:1)
一个选择是列出功能列表并循环运行它们,如以下Shellcheck-纯净代码所示:
#! /bin/bash -p
# ...
config_functions=(
function_1
function_2
# ...
function_15
function_16 )
for cfunc in "${config_functions[@]}" ; do
if "$cfunc" ; then
printf 'Success: %s\n' "$cfunc"
else
printf 'Failure: %s (%d)\n' "$cfunc" "$?"
fi
done
$?
,并且Shellcheck会发出警告。参见Shellcheck SC2181。break
或exit "$?"
放在相应的if
的'Failure'分支中。如果函数采用参数,但仅当参数始终相同时,此方法也可以很好地工作。 (只需将参数添加到循环中的函数调用中。)如果不同的函数采用不同的参数,则效率较低。您可以尝试将完整函数调用放在数组的字符串中,但是处理需要用引号引起来的参数是很棘手的。
请考虑使用诸如Chef,Puppet,Ansible或Salt之类的配置管理工具来配置NFS服务。与脚本相比,它们具有许多优势。
答案 1 :(得分:1)
如果函数采用参数(而不同的函数采用不同的参数),则简化命令验证的一种方法是使用函数来实现:
#! /bin/bash -p
# ...
# Run a configuration command (passed as arguments) and report if it succeeds or
# fails. Call 'exit' if the command fails.
function doconf
{
if "$@" ; then
printf 'Success: %s\n' "$*"
return 0
else
local status=$?
printf 'Failure: %s (%d)\n' "$*" "$status"
exit "$status"
fi
}
doconf function_1 arg1
doconf function_2 arg2a arg2b
# ...
doconf function_15 arg15a arg15b arg15c arg15d
doconf function_16 arg16a arg16b arg16c
如果您不希望程序在函数失败时立即退出,则可以通过将exit
调用放在子shell中来捕获doconf
完成的doconf
:
# ...
(
doconf function_1 arg1
doconf function_2 arg2a arg2b
# ...
doconf function_15 arg15a arg15b arg15c arg15d
doconf function_16 arg16a arg16b arg16c
)
# Program execution continues here, even if a `doconf` exits
# ...
doconf
并不是一个好名字。您可能要更改它。doconf
应该进行检查,以确保至少提供了一个参数(命令名称)。答案 2 :(得分:1)
检查$?
是一种反模式。最好直接在if
语句中测试命令:
if cmd; then
...
fi
进行明确的if
检查和错误消息非常麻烦。避免这种情况的常见模式是在命令失败时直接退出,然后依靠该命令打印自己的错误消息。您无需自己打印任何内容。然后,当命令失败时,您可以使用|| return
或|| exit
来纾困,其中a || b
是if ! a; then b; fi
的简写。
function_1 || exit
function_2 || exit
function_3 || exit
...
请注意,return
和exit
将自动使用$?
。
如果要在任何命令失败时退出,一个更简单的选择是使用errexit
启用set -e
标志。这样做,外壳程序将自动退出脚本,而无需插入繁琐的检查。
set -e
function_1
function_2
function_3
...