【问题标题】:How to escape the single quote character in an ssh / remote bash command?如何在 ssh / 远程 bash 命令中转义单引号字符?
【发布时间】:2013-12-28 05:07:43
【问题描述】:

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

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

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

【问题讨论】:

  • 尝试> ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " "'"{打印 $2}"'" |头 -n 1`'
  • @RedX 这工作谢谢!用它作为答案,我会接受。

标签: bash ssh quoting


【解决方案1】:

使用

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

解释:

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

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

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

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

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

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

【讨论】:

  • 一个解释会比仅仅解决这个特定问题的一个班轮更好。
【解决方案2】:

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

$ 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!

【讨论】:

    【解决方案3】:

    我在其他任何答案中都没有看到另外两个选项。出于演示目的,我已将 grep/grep/awk/head 管道完好无损,即使(如 rici's answer 中提到的那样)它可能会简化为类似

    awk -F ' ' '/MapReduceNod[e]/ { print $2; exit }'
    
    1. 对整个 ssh 命令使用双引号:

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

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

    2. 带引号分隔符的 here-doc:

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

      -T 防止 ssh 抱怨未分配伪终端。

      带有引号分隔符的 here-doc 非常好,因为它的内容根本不需要修改关于转义的东西,并且它可以包含单引号。

    【讨论】:

    • here-doc 示例非常有用,因为它提醒您引用 EOF 会影响以下文本是否由 bash 评估。
    【解决方案4】:

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

    例如:

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

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

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

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

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

    【讨论】:

      【解决方案5】:

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

      ssh womanLptp "osascript -e 'tell app \"System Events\" to display dialog \"${1}\"'"
      

      【讨论】:

        猜你喜欢
        • 2013-03-12
        • 2014-08-21
        • 1970-01-01
        • 1970-01-01
        • 2018-10-19
        • 1970-01-01
        • 2014-07-20
        • 2013-05-29
        • 2021-07-11
        相关资源
        最近更新 更多