如何在 ssh/远程 bash 命令中转义单引号字符?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20498599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:30:50  来源:igfitidea点击:

How to escape the single quote character in an ssh / remote bash command?

bashsshquoting

提问by SkyWalker

I'm building a small set of scripts for remotely starting, stopping and checking the status of a process. The stopof these scripts should look for a process and kill it. Therefore I do:

我正在构建一小组脚本,用于远程启动、停止和检查进程的状态。在stop这些脚本应该寻找一个过程,并杀死它。因此我这样做:

ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '{print }' | head -n 1`'

The problem here is that the awk tokenization step needs single quotes and these clash with the single quote utilized for executing the remote command via ssh. How can these single quotes be escaped?

这里的问题是 awk 标记化步骤需要单引号,而这些与用于通过 ssh 执行远程命令的单引号冲突。如何转义这些单引号?

回答by RedX

Use

ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '"'"'{print }'"'"' | head -n 1`'

Explanation:

解释:

ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '"'"'{print }'"'"' | head -n 1`'
                >                               1                                   <>2<>    3     <>4<>      5      <

1) First string with beginning of command: 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '

1) 以命令开头的第一个字符串: 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '

2) Second string with only a single ' char: "'"

2) 只有一个 ' 字符的第二个字符串: "'"

3) Third string with the print command: '{print $2}'

3) 带有打印命令的第三个字符串: '{print $2}'

4) Fourth string with another single quote: "'"

4) 带有另一个单引号的第四个字符串: "'"

5) Fifth string with rest of command: ' | head -n 1`'

5) 带有其余命令的第五个字符串: ' | head -n 1`'

回答by Yann Vernier

This is not sshor awkhandling the quotes, it is the shell (and they are necessary to keep the shell from handling other characters specially, like $). Nesting them is not supported (although other structures, such as $()may nest even while containing quotes), so you'll need to escape the single quotes separately. Here are a couple of methods:

这不是sshawk处理引号,而是外壳(并且它们是防止外壳特别处理其他字符所必需的,例如$)。不支持嵌套它们(尽管其他结构,例如$()即使包含引号也可能嵌套),因此您需要单独转义单引号。这里有几个方法:

$ echo 'Don'"'"'t mess with this apostrophe!'
Don't mess with this apostrophe!
$ echo 'Don'\''t mess with this apostrophe!'
Don't mess with this apostrophe!

回答by rici

You can't include a single quote in a single-quoted string. However, that doesn't matter because a single argument can have more than one quoted segment (as long as there is no unquoted whitespace or other self-delimiting characters.)

您不能在单引号字符串中包含单引号。但是,这并不重要,因为单个参数可以有多个带引号的段(只要没有未加引号的空格或其他自定界字符。)

For example:

例如:

ssh deploy@hera 'kill -9 `ps -ef |
                 grep MapReduceNode |
                 grep -v "grep" |
                 awk -F " " '\''{print }'\'" |
                 head -n 1`"

However, that command line is veryclunky. If possible, you should use the pkillutility, which would reduce all that to ssh deploy@hera 'pkill -SIGKILL MapReduceNode'.

但是,该命令行非常笨拙。如果可能,您应该使用该pkill实用程序,它将所有内容减少到ssh deploy@hera 'pkill -SIGKILL MapReduceNode'.

Otherwise you could do all the string manipulation in a single awkinvocation (untested, but I think it will work):

否则,您可以在一次awk调用中完成所有字符串操作(未经测试,但我认为它会起作用):

ssh deploy@hera 'ps -ef |
                 awk "/[M]apReduceNode/{system(\"kill -9 \")}"'

(unlike the original, this will kill all MapReduceNode tasks rather than some arbitrary first one. If you really want to just do in one task, add ; exitto the awk action.)

(与原来的不同,这将杀死所有 MapReduceNode 任务,而不是一些任意的第一个任务。如果您真的只想在一个任务中完成,请添加; exit到 awk 操作。)

回答by Benjamin W.

There are two more options I don't see mentioned in any of the other answers. I've left the grep/grep/awk/head pipeline intact for demonstration purposes, even though (as alluded to in rici's answer) it could be reduced to something like

我在其他任何答案中都没有提到还有两个选项。出于演示目的,我将 grep/grep/awk/head 管道保持完整,即使(如rici 的回答中所提到)它可以简化为类似

awk -F ' ' '/MapReduceNod[e]/ {print ; exit}'
  1. Using double quotes for the whole ssh command:

    ssh deploy@hera "kill -9 $(ps -ef |
    grep MapReduceNode | grep -v \"grep\" | awk -F ' ' '{print $2}' | head -n 1)"
    

    Notice that I can use single quotes in the command now, but I have to escape other things I don't want expanded yet: \$()(which I've used instead of backticks), double quotes \", and print \$2.

  2. A here-doc with quoted delimiter:

    ssh -T deploy@hera <<'EOF'
    kill -9 $(ps -ef | grep MapReduceNode | grep -v 'grep' |
    awk -F ' ' '{print }' | head -n 1)
    EOF
    

    The -Tprevents ssh from complaining about not allocating a pseudo-terminal.

    The here-doc with quoted delimiter is extra nice because its contents don't have to be modified at all with respect to escaping things, andit can contain single quotes.

  1. 对整个 ssh 命令使用双引号:

    ssh deploy@hera "kill -9 $(ps -ef |
    grep MapReduceNode | grep -v \"grep\" | awk -F ' ' '{print $2}' | head -n 1)"
    

    请注意,我现在可以在命令中使用单引号,但我必须转义其他我不想扩展的内容:(\$()我用它代替了反引号)、双引号\"print \$2.

  2. 带有引用分隔符的此处文档:

    ssh -T deploy@hera <<'EOF'
    kill -9 $(ps -ef | grep MapReduceNode | grep -v 'grep' |
    awk -F ' ' '{print }' | head -n 1)
    EOF
    

    -T可以防止 ssh 抱怨没有分配伪终端。

    带引号分隔符的 here-doc 非常好,因为它的内容根本不需要修改,而且它可以包含单引号。

回答by Pipo

Another example is to deal with simple or double quotes because for me for example I needed interpretation and variable replacements. If I want to make a function to display a msg to the macOS of my woman I can do followings:

另一个例子是处理简单或双引号,因为例如我需要解释和变量替换。如果我想创建一个函数来向我女人的 macOS 显示 msg,我可以执行以下操作:

ssh womanLptp "osascript -e 'tell app \"System Events\" to display dialog \"\"'"