引用和转义 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 \"\&lt;defunct\&gt;\"|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 | awkawk 可以为您完成所有这些工作。 【参考方案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 可以为你做过滤。我假设&lt;defunct&gt; 出现在行尾。如果是这样,那么您可以使用:

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 命令行 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

MySQL Linux命令行工具和正确格式化的结果[重复]

转义 .NET 命令行参数的规范解决方案

Linux命令行非法字符处理

命令行特殊字符名字转义

Shell命令行中特殊字符与其转义详解(去除特殊含义)

如何阻止我的命令行参数在 Maven 插件中被转义?