我正在编写一个 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_DIR
,SNAPSHOT_DIR
和YESTERDAY
在脚本的其他地方本地定义。
请记住,它将"..."
立即插入变量的值,而'...'
会将文本视为$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