SSHとsudoを使用するときにシェルで引用符をエスケープする方法は?

SSHとsudoを使用するときにシェルで引用符をエスケープする方法は?

全体的に:

質問と例はローカルでテストできます。

sh -c "echo 'how to print single quote here'"

詳細:

次の構成があります。

upload_server = ('192.168.1.1', 10051)

これで、サーバー構成を置き換えるにはシェルスクリプトが必要です。ローカルでは、sedを使用して次のことができます。

sed -E 's/(    upload_server = ).*/\\1('\"'$a'\"', 10051)/g' config.py

ただし、構成を変更する必要があるシステムがたくさんあります。

正しい計画はsshfor..inで使用することです。

for i in `cat hosts`; do ssh $i "cmd"; done

ただし、設定を変更するにはもう1つ必要ですsudo。次のようになります。

for i in `cat hosts`; do ssh $i "sudo -c \"cmd\""; done

今sedで:

upload_server=123.123.123.123
upload_server_port=1000
cmd="sed -E 's/(    upload_server = ).*/\\1('\"\"'\"'${upload_server}'\"'\"\"', ${upload_server_port})/g' config.py"
ssh $i "sudo -c \"${cmd}\""

構成結果:

upload_server = (123.123.123.123, 1000)

次のようにする必要があります。

upload_server = ('123.123.123.123', 1000)

今、引用符の使い方について混乱しました。 :(

ベストアンサー1

この場合、標準入力にsedスクリプトを渡すと、引用の問題を完全にバイパスできます。 SSHはローカル標準入力をリモートプロセスにルーティングし、sudoはそれを開いたままにし、sedはstdinからスクリプトを読み取ることができます。以下を使用して、標準入力の内容を渡すことができます。ここのドキュメント

for i in `cat hosts`; do
  ssh "$i" 'sudo sed -f - …' <<'EOF'
s/(    upload_server = ).*/\1("$a", 10051)/g
EOF
done

より一般的には、stdinにデータを渡す必要がない限り、引用を心配することなくSSHを介してstdinのシェルフラグメントを渡すことができます。

for i in `cat hosts`; do
  ssh "$i" sudo sh <<'EOF'
sed 's/(    upload_server = ).*/\1("$a", 10051)/g' …
EOF
done

"$a"設定ファイルを挿入するか、"something"変数の値がローカルシェルにあるかは、あなたの質問からは明確ではありません。ローカル変数を参照するには、hereドキュメントを補間と組み合わせて使用​​し、hereドキュメントからバックスラッシュで保護します。 sedと2番目のコードスニペットのリモートシェルによる解析のため、変数の値には文字や改行を含めないでください。asomething$\`\/'

  ssh "$i" sudo sh <<EOF
sed 's/(    upload_server = ).*/\\1("$a", 10051)/g' …
EOF

おすすめ記事