BASH:不能在函数内部使用变量

BASH: can't use variable inside function

提问人:Buffalosoldier 提问时间:8/29/2023 更新时间:8/29/2023 访问量:57

问:

在我的函数中,我定义了一个变量:CHECKRESULT:

function checkport {
if nc -zv -w3 $1 $2 <<< '' &> /dev/null
then
    echo -e "TCP-Port $1/$2 is open"
    CHECKRESULT="ok"
else
    echo -e "TCP-Port $1/$2 is closed" 
    CHECKRESULT="error"
fi
}

在脚本的后面,我有一个使用 CHECKRESULT 变量的 if 语句:

if ssh -q $host-- "$(declare -f checkport); checkport $someotherhost ${Ports[$i]} &> /dev/null" && [ "$CHECKRESULT" == "ok" ]

不幸的是,$CHECKRESULT变量似乎总是“好的”。即使我的函数失败,变量也不会更新为“错误”。

我认为这是因为该函数是通过远程主机上的 ssh 执行的,并且本地计算机不会在定义的变量中获得结果。

我需要获取变量吗?或者我该如何解决这个问题?

bash 函数 变量

评论

3赞 Gordon Davisson 8/29/2023
该函数在远程系统上运行,因此这是定义变量的位置。但是您正在本地系统上测试它,它看不到远程值。最好让函数只打印结果,用 捕获它,然后测试。顺便说一句,我还建议使用小写或混合大小写的变量名称,以避免与许多具有特殊含义或功能的全大写名称发生意外冲突。我也会避免使用关键字,因为它们是非标准的,并且在某些 shell 上会失败。CHECKRESULT =$(ssh ...)echo -efunction
0赞 user1934428 8/29/2023
如果你想保留或期望有一天你会在 stdout 上打印其他信息,我建议你将变量的值写入一个文件,并从本地主机的这个文件中读取它。echo

答:

1赞 Ed Morton 8/29/2023 #1

我相信这是因为该函数是通过远程上的 ssh 执行的 host 和本地计算机不会在变量中获取结果 定义。

正确。

我需要获取变量吗?

不。

或者我该如何解决这个问题?

这只是代码中更普遍问题的症状。无论是否通过 ssh 调用它,都应避免使用全局变量在函数和调用代码之间共享信息,因为这会破坏封装。写成:checkport

checkport() {
    local state=closed result=1

    if nc -zv -w3 "$1" "$2" <<< '' &> /dev/null
    then
        state=open
        result=0
    fi

    printf 'TCP-Port %s/%s is %s\n' "$1" "$2" "$state"
    return "$result"
}

或者,如果您出于某种原因不想使用退出状态,则:

checkport() {
    local state=closed result=error

    if nc -zv -w3 "$1" "$2" <<< '' &> /dev/null
    then
        state=open
        result=ok
    fi

    printf 'TCP-Port %s/%s is %s\n' "$1" "$2" "$state" >&2
    printf '%s\n' "$result"
}

艺术

    printf 'TCP-Port %s/%s is %s\n' "$1" "$2" "$state"
    printf '%s\n' "$result" >&2

艺术

    printf 'TCP-Port %s/%s is %s\n' "$1" "$2" "$state"
    printf '%s\n' "$result"

或类似(以最适合您的需求为准 - 将状态或结果重定向到 stderr 或将两者都打印到 stdout 或 stderr),然后编写调用代码以使用它,例如,如果您使用上面第一个使用退出状态的脚本(鉴于我到目前为止在您的代码中看到的内容,最有可能是您应该使用的脚本):

if state=$(checkport "$someotherhost" "${Ports[$i]}"); then
    do success stuff
else
    do failure stuff
fi
printf 'checkport output "%s"\n' "$state"

作为额外的奖励,它将解决您当前的问题,因为您不再在函数内部的一台机器上设置全局变量,并尝试由其外部的另一台机器读取。

0赞 KamilCuk 8/29/2023 #2

您的函数总是以 0 退出,表示成功:

function checkport {
if nc -zv -w3 $1 $2 <<< '' &> /dev/null
then
    echo -e "TCP-Port $1/$2 is open"
    CHECKRESULT="ok"
else
    echo -e "TCP-Port $1/$2 is closed" 
    CHECKRESULT="error"
    # missing return 1
fi
 # always returns 0 by default on end of function
}

您需要您的函数来打印任何东西吗?只:

if ssh -q $host -- nc -zv -w3 $1 $2 <<<'' &> /dev/null; then
   CHECKRESULT="ok"
else
   CHECKRESULT="error"
fi

如果你想要你的函数,让你的函数在失败时退出 - 在错误路径上添加缺失。return 1