我正在构建一小组脚本,用于远程启动,停止和检查进程的状态。这些脚本的stop
应该查找进程并将其终止。所以我这样做:
ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '{print $2}' | head -n 1`'
这里的问题是awk标记化步骤需要单引号,并且这些单引号与用于通过ssh执行远程命令的单引号冲突。这些单引号如何被转义?
答案 0 :(得分:23)
使用
ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '"'"'{print $2}'"'"' | head -n 1`'
答案 1 :(得分:13)
这不是处理引号的ssh
或awk
,而是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!
答案 2 :(得分:8)
您不能在单引号字符串中包含单引号。但是,这并不重要,因为单个参数可以有多个带引号的段(只要没有未引用的空格或其他自定义字符。)
例如:
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任务而不是任意的第一个任务。如果你真的只想做一个任务,请在awk动作中添加; exit
。)
答案 3 :(得分:5)
在其他任何答案中我都没有提到另外两个选项。我已经完整地保留了grep / grep / awk / head管道以用于演示目的,即使(如rici's answer中提到的那样)它也可以简化为
awk -F ' ' '/MapReduceNod[e]/ {print $2; exit}'
对整个ssh命令使用双引号:
ssh deploy@hera "kill -9 \$(ps -ef |
grep MapReduceNode | grep -v \"grep\" | awk -F ' ' '{print \$2}' | head -n 1)"
请注意,我现在可以在命令中使用单引号,但我必须逃避其他我想要扩展的内容:\$()
(我已经使用了而不是反引号),双引号\"
和print \$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非常好用,因为它的内容不需要根据转义内容进行修改,和它可以包含单引号。
答案 4 :(得分:0)
另一个例子是处理简单或双引号,因为对我来说,例如我需要解释和变量替换。如果我想创建一个函数来向我女人的macOS显示一个消息,我可以做以下事情:
ssh womanLptp "osascript -e 'tell app \"System Events\" to display dialog \"${1}\"'"