【问题标题】:Check for zero lines output from command over SSH通过 SSH 检查命令输出的零行
【发布时间】:2013-09-26 21:05:06
【问题描述】:

如果我执行以下操作,并且网络中断,那么将执行零情况,它不应该这样做。

case "$(ssh -n $host zfs list -t snapshot -o name -H | grep "tank/fs" | wc -l | awk '{print $1}')" in
    0)  # do something
        ;;
    1)  # do something else
        ;;
    *)  # fail
esac

在脚本的前面,我检查了我可以通过 SSH 连接到 $host,但今天我发现了这个问题,在我检查后网络立即出现故障。

如果我检查 SSH 命令的返回值,那么我将始终从 awk 获取返回值,因为它是最后执行的。

问题

我如何确保我实际上计算了 zfs 输出的零行,而不是失败的 SSH 连接产生的零行?

【问题讨论】:

    标签: linux bash error-handling ssh


    【解决方案1】:

    说:

    set -o pipefail
    

    在脚本的开头(或在case 语句之前)。

    另外,在执行case语句之前检查命令的返回码:

    set -o pipefail
    $value=$(ssh -n $host zfs list -t snapshot -o name -H | grep "tank/fs" | wc -l | awk '{print $1}')
    if [ $? == 0 ]; then
       case $value in
         ...
       esac
    fi
    

    来自manual

    pipefail

    如果设置,则管道的返回值是最后一个的值 (最右边)命令以非零状态退出,如果全部退出则为零 管道中的命令成功退出。此选项被禁用 默认。

    【讨论】:

    • 对我不起作用,它仍然通过case 0编辑:添加代码后,$? == 0 逻辑应该可以工作。
    • 我认为这是一个丑陋的解决方案。 grep/wc/awk 命令将被执行locally 而不是远程when ssh 失败,这就是它没有按预期工作的原因。我的解决方案应该更强大。
    【解决方案2】:

    这个怎么样(ssh 之后的命令不应该在本地执行):

    "$(ssh -n $host 'zfs list -t snapshot -o name -H | grep "tank/fs" | wc -l | awk \'{print $1}\')'"
    

    请注意我是如何单引用 ssh 以在远程机器上运行的命令的。还为awk 转义了',例如\'。检查调用的返回值,只有在返回成功时才动作。

    【讨论】:

    • 不能解决问题,因为整个管道可能会失败,并且在未检查退出状态而不是更早地短路时会发生空情况。
    • @CharlesDuffy 我在本地尝试了原始行。 ssh 失败意味着管道命令在本地执行,case 0wc -l 回显0 而触发。在我的解决方案中,'' 之间的所有内容都成为 ssh 的参数,而ssh 失败时case 0 不会触发。但是,在进行字符串比较时恰好是这种情况。如果ssh 会打印0 行,它也会匹配case 0 太ofc。只对返回值 0 执行操作听起来是个好主意,我原本计划添加它,但由于某种原因取消了编辑:)
    猜你喜欢
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2011-09-19
    • 2015-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多