在 shell 脚本中使用 exec 通过 ssh 查找

在 shell 脚本中使用 exec 通过 ssh 查找

因此,我尝试从 shell 脚本中执行以下命令;

ssh -q $CUR_HOST "cd $LOGS_DIR; echo cd $LOGS_DIR; find . -name *.log -mmin +1440 -exec gzip {} \; exit"

运行时,会生成以下错误;

find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]

我根据谷歌上发现的内容尝试了多种变体,但似乎都没有解决这个问题。谁能告诉我这有什么问题吗?

附带说明一下,当我手动登录目标主机并在那里运行相同的 find 命令时,它工作得很好。因此,我认为这与嵌入 ssh 命令的双引号中的命令有关。

答案1

有几个语法问题,其中之一是致命的并且其他这可能会在某个时候咬你一口。

顺便说一句,您可以使用+代替来;结束该-exec指令;这种方式gzip会分批执行,速度稍快一些。

LOGS_DIR如果的值为/somewhere/with/logs,则在远程主机上执行以下命令:

cd /somewhere/with/logs; echo cd /somewhere/with/logs; find . -name *.log -mmin +1440 -exec gzip {} \; exit

或者,用换行符替换等效的分号运算符:

cd /somewhere/with/logs
echo cd /somewhere/with/logs
find . -name *.log -mmin +1440 -exec gzip {} \; exit

当在指令后find看到虚假内容时,它不知道如何处理它;它可能会(错误)猜测您的意思是它是一条要穿越的路径。您需要一个命令分隔符:在后面放置另一个命令分隔符(前面有或没有空格)。exit-exec … ;;\;

第二个问题是通配符模式*.log将在目录中扩展/somewhere/with/logs。如果存在匹配文件(即存在 形式的文件/somewhere/with/logs/something.log),则该模式将被该匹配文件替换。仅当*.log远程 shell 没有保持不变且 find 可以看到的匹配项时,才会出现这种情况。在模式周围添加引号以防止这种情况发生。

第三个问题是 的值LOGS_DIR。它在本地扩展为字符串,并在远程端作为 shell 脚本执行。因此,如果其中有任何 shell 特殊字符(空格、$等),则可以执行任意远程命令。引用大多数字符的一种快速而肮脏的方法是在变量扩展周围放置单引号;仅当值包含单引号时才会中断。如果您的本地脚本正在运行 bash,您可以用 4 个字符序列替换单引号'\''以保护 的值LOGS_DIR

ssh -q "$CUR_HOST" "cd '${LOGS_DIR//\'/\'\\\'\'}'; find . -name '*.log' -mmin +1440 -exec gzip {} +; exit"

答案2

您忘记添加“;”:

ssh -q $CUR_HOST "cd $LOGS_DIR; echo cd $LOGS_DIR; find . -name *.log -mmin +1440 -exec gzip {} \;; exit"

由于缺少;, find 解释exit为路径。

相关内容