提案に基づいてコマンドを編集しました

提案に基づいてコマンドを編集しました

リモートシステムにPS1を追加しようとしています/etc/profile。現在、この文字列を70台以上のサーバーに追加する必要があるため、sshこのPS1文字列をすべてのサーバーに追加します。しかし、PS1を送信しようとするとハングし、コマンドを強制終了する必要があります。

これはコマンドです

ssh -v admin@remserv  "sed  '/002/a \ PS1=" \[\e[31m\]\n------------------------------------------------------------------------------------------------------------------------------ \n\n[\u@\h \W]\\$ - \# \[\e[0m\] " /etc/profile' "

ここに画像の説明を入力してください

ここで何が欠けているのでしょうか?

提案に基づいてコマンドを編集しました

> ssh -vt admin@remserv printf "%s\n" "sudo sed -i.bak '/002/a \
> PS1="
> '\[\e[31m\']'\'n------------------------------------------------------------------------------------------------------------------------------ '\'n'\'n'[\u@\h \W']'\\'$ - '\'# '\[\e[0m\']  " /etc/profile' "

答え1

ssh ... "sed  '/002/a \ PS1=" \[\e[31m\]\n--...- \# \[\e[0m\] " /etc/profile' "
              ^             ^                                 ^             ^

引用符で囲まれた文字列内に引用符で囲まれていない二重引用符が 2 つありますが、これらはシェルによって削除されます (ssh 接続のローカル側)。また、内側の一重引用符はコマンドsedとファイル名の両方にまたがっているように見えるため、リモート シェルが引用符の処理を行った後、sedで 1 つの引数を取得します/002/a \ ... /etc/profile。これは実際にイメージ内の ssh の出力に表示されます。

(まあ、少なくとも頭に浮かぶのはそういうことです。二重引用符の問題は、少なくとも十分なコーヒーを飲まないと私の脳ではうまく機能しません。)

次のようなコマンドを実行することでデバッグできるはずです。

ssh somewhere printf '"%s\n"'  "sed '/002/... /etc/profile' "

printf、取得した引数を 1 行に 1 つずつ出力します。これにより、文字列が実際に分割される場所がわかりやすくなります (echo はスペースで結合されるため、foo, bar, は と同じように見えますfoo bar)。フォーマット文字列を二重引用符で囲むと、リモートに対してバックスラッシュがそのまま保持されます。

答え2

OK、'\'文字を使ってこれを解決します

正しいコマンド

for i in `cat serverslist`; do  ssh -t admin@$i  "sudo sed -i.bak '/002/a \ PS1="\" '\\'['\\'e[31m'\\']'\\n'------------------------------------------------------------------------------------------------------------------------------  '\\'n'\\'n['\\'u@'\\'h '\(''\\'W'\)']'\\''\\'$ - '\\'# '\\'['\\'e[0m'\\']   \"" ' /etc/profile " ;done ;

関連情報