我正在编写一个在跳转服务器上运行的 bash shell 脚本。它有一个参数,代表要搜索的字符串。该参数被输入到一个 `-surrounded 命令(命令替换)中,该命令对目录中的一堆文件中的搜索参数执行 grep 操作,并将结果通过管道传输到wc -l
.然后将其转换为带引号的字符串,该字符串作为命令参数传递:
ssh server "[grep command]"
该 ssh 命令在一个循环中执行,该循环遍历我们要检查的所有服务器。
让所有的引用都正确,以便每个元素在适当的时间之前都不会被评估,这是一个很大的痛苦,但我几乎已经让这个疯狂的事情开始工作了。
所有内容都通过 ssh 传递到正确的服务器,但是当命令在服务器上运行时,结果是
bash: /bin/echo "26520 instances of [xyz]": No such file or directory
26520是成功运行的结果
/bin/grep xyz /path/to/logfiles/*access*|wc -l
这是通过 ssh 作为命令的一部分传递的:
ssh server [command]
如果我实际上 ssh 到远程服务器之一并运行
$ /bin/echo "26490 instances of [xyz]"
26520 instances of [xyz]
bash 当然没有问题。
如果我实际上 ssh 到远程服务器之一并运行
$ /bin/echo "`/bin/grep xyz /path/to/logfiles/*access*|wc -l` instances of [xyz]"
26520 instances of [xyz]
bash也没有问题。
但是当命令通过 ssh 传递时,它会出现这个问题 - 即使 grep 命令被执行并产生了正确的结果
bash: /bin/echo "26520 instances of [xyz]": No such file or directory
bash 到底反对什么?我该如何解决这个问题?
更新:为了简化,我发现我可以通过一行命令行来复制问题当地的服务器,抽象出由脚本、变量替换等引起的所有复杂性。
$ ssh {remoteserver} "echo `/bin/grep xyz /path/to/logfiles/*access*|wc -l`"
grep: /path/to/logfiles/*access*: No such file or directory
26520
bash 再次抱怨没有这样的文件(尽管如此,它仍然存在),然后继续运行 grep 命令并打印正确的结果。
实际上,我现在已经通过重写脚本将远程服务器的所有命令写入本地服务器上的文件来解决问题,在解析命令行参数后,然后将文件的内容通过管道传输到 ssh:
echo ... > commandfile
cat commandfile | ssh -T ${SERVER}
我也尝试过<
但我仍然想知道 bash 反对什么。
答案1
跑步
ssh {remoteserver} "echo `/bin/grep xyz /path/to/logfiles/*access*|wc -l`"
导致在本地计算机上运行子命令,而不是在远程计算机上。可以使用简单地验证
$ ssh host "echo `hostname`"
the local hostname
如果要在远程服务器上运行子命令,请使用撇号
$ ssh host 'echo `hostname`'
the remote hostname
但更新中的错误与原始错误不同......
答案2
ssh server "[grep command]"
变量和命令替换 ( , , ) 在双引号内执行,因此如果或出现在 中,则它会在调用 之前由本地 shell 执行。然后,一旦执行了替换(在本地运行命令),就调用远程主机上的字符串。$variable
$(command)
`command`
$
`
[grep command]
ssh
grep
ssh
echo
将要在远程主机上执行的命令放在单引号(即撇号)中:
ssh server '[grep command]'
为简单起见,请勿在命令中包含任何单引号。如果您确实需要单引号,则可以将其包含为'\''
(单引号,反斜杠,单引号,单引号)。