引用和转义 ssh 命令行 [重复]
Posted
技术标签:
【中文标题】引用和转义 ssh 命令行 [重复]【英文标题】:quoting and escaping of a ssh command line [duplicate] 【发布时间】:2016-08-25 14:21:43 【问题描述】:以下命令看起来正确引用和转义:
$ echo -e ssh -q rmthost 'bash -c "ps -ef|grep '\'''\\\<'defunct'\\\>''\''|grep -v grep|awk '\'''print \$1''\'' "'
ssh -q sbpsvrwm757 bash -c "ps -ef|grep '\<defunct\>'|grep -v grep|awk 'print $1' "
但是当执行时,结果不是预期的:
$ ssh -q rmthost 'bash -c "ps -ef|grep '\'''\\\<'defunct'\\\>''\''|grep -v grep|awk '\'''print \$1''\'' "'
root16986 16982 0 - ? 0:01 <defunct>
awk 命令似乎没有提取正确的列。
现在我点击了 Siguza 提供的链接并想出了:
$ echo ssh -q rmthost "'"bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk 'print \$1'"'"'"'"
ssh -q rmthost 'bash -c "ps -ef|grep '\<defunct\>'|grep -v grep|awk 'print $1'"'
看起来也完美逃脱了,但仍然不起作用:
$ ssh -q rmthost "'"bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk 'print \$1'"'"'"'"
Missing
或者,
$ echo ssh -q rmthost bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk 'print \$1'"'"'
ssh -q rmthost bash -c "ps -ef|grep '\<defunct\>'|grep -v grep|awk 'print $1'"
$ ssh -q rmthost bash -c '"ps -ef|grep '"'\<defunct\>'|grep -v grep|awk 'print \$1'"'"'
root 16986 16982 0 - ? 0:01 <defunct>
或者,
$ echo ssh -q rmthost "bash -c \"ps -ef |grep '\<defunct\>'|grep -v grep| awk 'print \$1'\""
ssh -q rmthost bash -c "ps -ef |grep '\<defunct\>'|grep -v grep| awk 'print $1'"
$ ssh -q rmthost "bash -c \"ps -ef |grep '\<defunct\>'|grep -v grep| awk 'print \$1'\""
root 16986 16982 0 - ? 0:01 <defunct>
知道为什么吗?
请注意,我需要 bash -c 来启用 bash 样式的输出重定向,如命令的 >/var/tmp/1.ouy 2>&1。
感谢您的帮助。
【问题讨论】:
谢谢。我遵循该规则,但仍然无法使其工作。查看上面的更新ssh rmthost "ps -ef |grep \"\<defunct\>\"|grep -v grep| awk 'print \$1' "
有什么问题 - 还是我在这里遗漏了什么?即,通过将 ssh 的参数用双引号括起来,可以避免所有的尴尬。
bash -c
在这里也是多余的。 ssh 会将命令字符串发送到 shell 本身,从而为您节省整个转义级别。
我忘了说我需要 bash -c 来启用 bash 样式的输出重定向 > /var/tmp/1.out 2>&1.用户的登录 shell 是 rmthost 上的 csh
我强烈建议学习 awk 以避免过多的`grep | grep | awk
。 awk
可以为您完成所有这些工作。
【参考方案1】:
说实话,我看不懂你写的代码。它太模糊了,我没有半小时的时间来弄清楚。为此,它很可能不是好的代码。
当您尝试理解多层解码时,这样的引用会变得非常混乱。因此,我不会尝试更正您的报价,而是尝试提供具有相同结果的更简洁的代码。
ssh rmthost "bash -c \"ps -ef | grep '<defunct>' | grep -v grep | awk 'print \\\$2'\""
# The remote system will execute this:
bash -c "ps -ef | grep '<defunct>' | grep -v grep | awk 'print \$2'"
# Which in tells bash to execute this:
ps -ef | grep '<defunct>' | grep -v grep | awk 'print $2'
但是,为什么不尝试删除一些过多的 grep 管道。 awk
可以为你做过滤。我假设<defunct>
出现在行尾。如果是这样,那么您可以使用:
ssh rmthost "bash -c \"ps -ef | awk '/<defunct>\\\$/ print \\\$2'\""
# the remote system executes this:
bash -c "ps -ef | awk '/<defunct>\$/ print \$2'"
# bash executes this:
ps -ef | awk '/<defunct>$/ print $2'
或者更好的是,使用ps -el
中的第二列,这将是Z
用于僵尸进程:
ssh rmthost "bash -c \"ps -el | awk '/^. Z / print \\\$4'\""
# the remote system executes this
bash -c "ps -el | awk '/^. Z / print \$4'"
# bash executes this:
ps -el | awk '/^. Z / print $4'
【讨论】:
第一个命令出现“变量语法”错误,第二个命令出现“awk:第 1 行附近的语法错误 awk:第 1 行附近的非法语句”。 这很奇怪,它在我的系统上运行良好。我在扁平示例中进行了编辑。我建议登录到远程系统并检查它们是否首先工作。这是非常简单的awk
语法,所以我不相信 awk 有什么问题,但听起来好像是在扁平化引号时发生了一些奇怪的事情。【参考方案2】:
这是一个使用引号的有效解决方案:
ssh -q rmthost "bash -c 'ps -ef|grep ''''\<'defunct'\>''''|grep -v grep|awk "'"print \$2"'" '"
但是,我自己不太了解机制:-)。如果你交换单引号和双引号,它就不起作用。
【讨论】:
无法重现您的“不匹配”错误。既然您似乎有一个可行的解决方案,我现在放弃了。以上是关于引用和转义 ssh 命令行 [重复]的主要内容,如果未能解决你的问题,请参考以下文章