订购功能和条件的正确方法

问题描述 投票:3回答:3

我正在编写一个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
bash function condition
3个回答
1
投票

一个选项是制作一个函数列表并在循环中运行它们,如Shellcheck-clean代码所示:

#! /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的“Failure”分支中根据需要添加exit "$?"if

如果函数接受参数,这种方法也很有效,但前提是参数始终相同。 (只需在循环中将参数添加到函数调用中。)如果不同的函数采用不同的参数,则效果较差。您可以尝试将完整的函数调用放在数组中的字符串中,但处理需要引用的参数很棘手。

请考虑使用ChefPuppetAnsibleSalt等配置管理工具来配置NFS服务。它们比脚本有许多优点。


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应该检查以确保提供至少一个参数(命令名称)。

1
投票

这是检查$?的反模式。最好直接在if语句中测试命令:

if cmd; then
    ...
fi

有明确的if检查和错误消息是笨拙的。避免它的常见模式是在命令失败时简单地退出并依赖命令打印自己的错误消息。您不需要自己打印任何东西。然后你可以使用|| return|| exit来挽救命令失败,其中a || bif ! a; then b; fi的简写。

function_1 || exit
function_2 || exit
function_3 || exit
...

请注意,returnexit将自动使用$?

如果要在任何命令失败时退出,更简单的选择是使用errexit启用set -e标志。这样做,shell将自动退出脚本,而无需插入繁琐的检查。

set -e

function_1
function_2
function_3
...
© www.soinside.com 2019 - 2024. All rights reserved.