web-dev-qa-db-ja.com

ssh / remote bashコマンドで一重引用符をエスケープする方法は?

プロセスのステータスをリモートで開始、停止、確認するための小さなスクリプトセットを作成しています。これらのスクリプトのstopは、プロセスを探して強制終了します。したがって、私は:

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

ここでの問題は、awkトークン化ステップに単一引用符が必要であり、これらがsshを介してリモートコマンドを実行するために使用される単一引用符と衝突することです。これらの単一引用符はどのようにエスケープできますか?

22
SkyWalker

使用する

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

これは、引用符を処理する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!
_
13
Yann Vernier

単一引用符で囲まれた文字列に単一引用符を含めることはできません。ただし、単一の引数に複数の引用符付きセグメントを含めることができるため、それは問題ではありません(引用符で囲まれていない空白やその他の自己区切り文字がない限り)。

例えば:

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

ただし、そのコマンドラインはvery不格好です。可能であれば、 pkill ユーティリティを使用する必要があります。これにより、すべてがssh deploy@hera 'pkill -SIGKILL MapReduceNode'

それ以外の場合は、単一のawk呼び出しですべての文字列操作を実行できます(テストされていませんが、動作すると思います)。

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

(オリジナルとは異なり、任意の最初のタスクではなく、すべてのMapReduceNodeタスクを強制終了します。本当に1つのタスクで実行したい場合は、; exit awkアクションへ。)

8
rici

他の回答のいずれにも記載されていない2つのオプションがあります。 ( rici's answer で示唆されているように)grep/grep/awk/headパイプラインはデモンストレーションの目的でそのままにしておきましたが、

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. 引用符で囲まれたヒアドキュメント:

    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は、内容をエスケープすることに関してまったく変更する必要がないため、余分なニースです。and単一引用符。

5
Benjamin W.

もう1つの例は、単純な引用符または二重引用符を扱うことです。たとえば、私には解釈と変数の置換が必要だったからです。女性のmacOSにメッセージを表示する機能を作成したい場合は、次のことができます。

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