SSH リモートに変数を渡そうとしても機能しません。私のコードは次のとおりです
#!/bin/bash
set -x
conexion="[email protected]"
parameter="$1"
ssh -T $conexion <<'ENDSSH'
clear
echo "$parameter"
ENDSSH
私は次を実行します:
./script.sh try
それは私に言った:
parameter: Undefined variable.
助けが必要ですか?
答え1
変数(環境変数)渡すことはssh
可能ですが、通常は制限されます。
クライアントに送信するように言う必要があります。 OpenSSHを例にすると、次のようになります。
ssh -o SendEnv=parameter host cmd...
ただし、これを受け入れるにはサーバーも必要です(AcceptEnv
OpenSSHの設定ディレクティブを使用)。変数を受け入れるとかなりのセキュリティリスクが発生するため、一部のSSH展開では特定の名前空間(LC_*
一部のOpenSSH展開など)で特定の変数を許可しますが、通常はデフォルトでは実行されません。
また、を呼び出す前に変数をエクスポートする必要がありますssh
。たとえば、次のようになります。
LC_parameter="$parameter" ssh -o SendEnv=LC_parameter host csh << 'END'
echo $LC_parameter:q
END
上記では、シェル変数の内容を環境変数$parameter
bash
に渡し、これを受け入れると、環境変数としてユーザーのログインシェルに渡してからコマンドに渡します(それから拡張できます)。 )。LC_parameter
ssh
ssh
sshd
csh
host
ただし、前述のように、コンピュータ管理者が設定にAcceptEnv LC_parameter
またはを追加しない限りAcceptEnv LC_*
(時々デフォルトで実行されます)、この操作は機能しませんsshd
。
例のエラーメッセージUndefined variable
は、リモートユーザーのログインシェルがあることをcsh
示しますtcsh
。予期しない状況を避けるために、シェルを明示的に呼び出すことをお勧めしssh host csh
ます-T
。$LC_parameter:q
構文に注意してください。これは、変数に改行文字が含まれている場合に機能しないのとは対照的に、csh
変数の内容を文字通り渡す方法です。"$LC_parameter"
変数の使用LC_*
がオプションでない場合は、次のものも使用できます。顧客シェル(bash
あなたの場合)は変数を拡張します。素朴なアプローチは
ssh host csh << END
echo "$variable"
END
しかし、これは変数の内容がリモートシェルによって解釈されるので危険です。例を$variable
含める`reboot`
か提示すると、"; reboot; : "
悪い結果につながります。
したがって、まずリモートシェルの構文で変数が正しく参照されていることを確認する必要があります。ここではcsh
、安定して実行するのが難しい場所を避け、代わりにsh
//を使用します。bash
ksh
sh 参照にヘルパー関数を使用します。
shquote() {
awk -v q=\' -v b='\\' '
BEGIN{
for (i=1; i<ARGC; i++) {
gsub(q, q b q q, ARGV[i])
printf "%s ", q ARGV[i] q
}
print ""
exit
}' "$@"
}
次のように呼び出されますssh
。
ssh host sh << END
parameter=$(shquote "$parameter")
echo "\$parameter"
END
ローカルシェルではなくリモートシェルで$
拡張が行われるように3番目のアイテムをエスケープする方法を見てください。$parameter
答え2
環境変数の転送などの他のトリックに加えて、LC_*
次のこともできます。
PARAMETER="123"
ssh user@host PARAMETER="$PARAMETER" bash -s <<- 'EOF'
echo $PARAMETER
EOF
この方法の利点は、リモートホスト(名前が次に始まらない場合)、ローカルホスト(宛先または宛先)export PARAMETER
の設定に名前を追加する必要がないことです。AcceptEnv
LC_
/etc/ssh/sshd_config
SendEnv
-o
/etc/ssh/ssh_config
答え3
ENDSSH
4行目から引用符を削除すると役に立ちます。
提供:質問に対する@Archemarのコメント。
警告するこの回答の説明で@StéphaneChazelasが述べたように、このソリューションを使用すると、ここのドキュメントの変数は$parameter
ローカルシェルによって拡張されます。つまり、変数の内容はリモートシェルによってシェルコードとして解釈されます。これは、コマンド注入の脆弱性が発生することを意味します。したがって、これは通常推奨されません。
答え4
二重引用符の中に一重引用符を挿入します。
$ file_name="one two"
$ ssh remote ls "'$file_name'"
ls: cannot access 'one two': No such file or directory
一重引用符を削除せずに変数が最初に置き換えられます。このようにして、コンテンツは一重引用符で囲まれ、sshに送信されます。