Подтвердить что ты не робот

Как избежать символа одиночной кавычки в команде ssh/remote bash?

Я создаю небольшой набор сценариев для удаленного запуска, остановки и проверки состояния процесса. stop этих сценариев должен искать процесс и убивать его. Поэтому я:

ssh [email protected] 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '{print $2}' | head -n 1`'

Проблема заключается в том, что для шага маркера awk нужны одинарные кавычки, и это столкновение с единственной цитатой, используемой для выполнения удаленной команды через ssh. Как можно избежать этих одиночных кавычек?

4b9b3361

Ответ 1

Использование

ssh [email protected] 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '"'"'{print $2}'"'"' | head -n 1`'

Ответ 2

Это не ssh или awk обработка кавычек, это оболочка (и они необходимы, чтобы оболочка не обрабатывала другие символы, например $). Вложенность их не поддерживается (хотя другие структуры, такие как $(), могут вставляться даже при сохранении кавычек), поэтому вам нужно будет избежать одиночных кавычек отдельно. Вот несколько способов:

$ 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

Вы не можете включить одну цитату в строку с одним кавычком. Однако это не имеет значения, потому что один аргумент может иметь более одного цитированного сегмента (если нет некотируемых пробелов или других символов с саморазграничением.)

Например:

ssh [email protected] 'kill -9 `ps -ef |
                 grep MapReduceNode |
                 grep -v "grep" |
                 awk -F " " '\''{print $2}'\'" |
                 head -n 1`"

Однако эта командная строка очень неуклюжая. Если возможно, вы должны использовать утилиту pkill, которая уменьшит все до ssh [email protected] 'pkill -SIGKILL MapReduceNode'.

В противном случае вы могли бы выполнить все манипуляции с строкой в ​​одном вызове awk (непроверенный, но я думаю, что он будет работать):

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

(в отличие от оригинала, это убьет все задачи MapReduceNode, а не какое-то произвольное первое. Если вы действительно хотите сделать только одну задачу, добавьте ; exit в действие awk.)

Ответ 4

Есть еще два варианта, о которых я не упоминал ни в одном из других ответов. Я оставил конвейер grep/grep/awk/head неповрежденным для демонстрационных целей, хотя (как упоминалось в rici answer) его можно было свести к чему-то вроде

awk -F ' ' '/MapReduceNod[e]/ {print $2; exit}'
  • Использование двойных кавычек для всей команды ssh:

    ssh [email protected] "kill -9 \$(ps -ef |
    grep MapReduceNode | grep -v \"grep\" | awk -F ' ' '{print \$2}' | head -n 1)"
    

    Обратите внимание, что теперь я могу использовать одинарные кавычки в команде, но мне нужно избежать других вещей, которые я еще не хочу расширять: \$() (которые я использовал вместо обратных ссылок), двойные кавычки \", и print \$2.

  • Здесь-doc с цитируемым разделителем:

    ssh -T [email protected] <<'EOF'
    kill -9 $(ps -ef | grep MapReduceNode | grep -v 'grep' |
    awk -F ' ' '{print $2}' | head -n 1)
    EOF
    

    -T запрещает ssh жаловаться на то, чтобы не выделять псевдотерминал.

    Здесь-doc с цитированным разделителем является дополнительным приятным, потому что его содержимое не нужно изменять вообще в отношении экранирования вещей, и оно может содержать одинарные кавычки.

Ответ 5

Другим примером является рассмотрение простых или двойных кавычек, потому что для меня, например, мне нужны интерпретации и замены переменных. Если я хочу сделать функцию, чтобы отобразить сообщение для macOS моей женщины, я могу сделать следующее:

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