如果条件里面有 ssh 命令

如果条件里面有 ssh 命令

我正在编写一个 bash 脚本来将我的计算机备份到本地服务器。我需要压缩档案,但我找不到一种方法来使 if 条件与内部 ssh 命令一起工作:

if [ ssh [email protected] '$(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"' ]
then
    ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
    && rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
fi

我遇到了“参数过多”(在 if 内)错误。

我究竟做错了什么?

答案1

我建议您简化构造,并让下一个阅读代码的人有机会了解发生了什么。您的主要问题是您似乎将间接执行$( ... )[ ... ]测试操作员混淆了。如果我误解了流程,请道歉,但我认为这就是您的意图:

# Count files on the remote system and confirm that there is at least one
DATE7=$(date -v -7d '+%Y%m%d')
NFILES=$(ssh [email protected] "ls -d '/snapshots/$DATE7'* 2> /dev/null | wc -l")

# If the ssh worked and we have found files then archive them
if [ $? -eq 0 && 0 -lt $NFILES ]
then
    # Archive the files
    ssh [email protected] "
        tar -czf '$ARCHIVES_DIR/$YESTERDAY.tar.gz' '$SNAPSHOT_DIR/$YESTERDAY'* &&
        rm -rf '$SNAPSHOT_DIR/$YESTERDAY'
    "
fi

这假设ARCHIVES_DIRSNAPSHOT_DIRYESTERDAY在脚本的其他地方本地定义。

请记住,它将"..."立即插入变量的值,而'...'会将文本视为$WIDGET以美元符号开头的文字七个字符字符串。鉴于我在这段代码中有类似" '...' "和 的序列,这一点值得注意。' "..." '

答案2

可以将命令的返回状态用作 if 条件,但正确的语法是不带括号。另一方面,您需要在远程主机上使用括号或“test”命令。 (我更喜欢对此进行测试。)试试这个:

if ssh [email protected] 'test $(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"'
then
    ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
    && rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
fi

您可能还想检查日期命令。至少在我的 Linux 系统上,我得到了date: invalid option -- 'v'.

答案3

该形式if [ ... ]是对 的调用test:根据 的语法规则计算括号内的表达式test,并发出返回码,这就是if解释的内容。您可能只想去掉括号:

if ssh ... | grep -q .

如果有任何成功匹配,该命令grep将返回成功返回代码(“true” );if在当前情况下,如果 ssh 命令的输出非空。原始代码的更直译是:

if [ $(ssh ... | wc -l) != 0 ]

在运行时,$(...)表达式将替换为所包含命令输出的文本;一个整数,这意味着test可以看到该整数和零之间的正确比较。

答案4

由于您的问题只是关于条件表达式,所以我只测试了 if 部分。

你可以这样做:

if [ $(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l') != "0" ]
then
    # do something
fi

对我的回答做一点补充:

您可能还必须考虑无法建立 SSH 连接(而不是仅检查行数是否非零)。

因为如果你的连接失败那么结果也将是“不为零”。

为了更好地处理错误,你可以使用这样的东西:

lines=$(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l')
result=$?
# If 'ssh'-command succesful:
if [ $result == "0" ]
then
    # If number of lines is non-zero:
    if [ $lines != "0" ]
    then
        # do something
    fi
else
    # handle error based on $result
fi

相关内容