ローカルサーバー(場所1)からリモートサーバー(場所2)に変数を渡そうとします。このコードの目的は、リモートサーバーの事前定義された場所からファイルをコピーすることです。簡単に言えば、事前定義されたパスを使用してlocation2からlocation1にファイルをコピーしたいと思います。ここで、location1 はローカルサーバーにあり、location2 はリモートサーバーです。コードスニペットを見てください。
$location1=somewhere/on/local_server
$location2=somewhere/on/remote_server
sshpass -p "password" \
ssh [email protected] 'su -lc "cp -r $location2 $location1";'
私が得るエラーは、$location1と$location2の両方が定義されていないことです。また、場所のパスはいつでも変更される可能性があり、コードの変更が手動で行われると痛みを伴う可能性があるため、手動で入力したくありません。
ベストアンサー1
シェル変数はまさにシェル変数です。クライアントシェルのこの変数は、このssh
コマンドまたはリモートホストから起動されたシェルとしてアクセスできません。sshd
出口シェル変数は、実行されたコマンドに環境変数として渡されます。したがって、エクスポートするとlocation1
環境変数としてに渡されます。設定ディレクティブ(またはまたは...経由)をssh
使用すると、リモートホストに転送しようとします。SendEnv
ssh
-o
~/.ssh/config
/etc/ssh/ssh_config
ssh
sshd
ただし、これを機能させるには、この変数を受け取るための設定ディレクティブsshd
が必要ですAcceptEnv
。しかし、セキュリティ上の理由から、通常はそうではありません。
ただし、多くのデフォルトのssh / sshd展開では、LC_
名前が(ローカライズのために)で始まる変数渡しを許可します。したがって、次の利点を享受できます。
LC_location1=$location1 LC_location2=$location2 ssh host
'su -lc '\''cp -r -- "$LC_location2" "$LC_location1"'\''
あるいは、ローカルシェル拡張変数をリモートシェルのコマンドラインに渡すこともできます。
ssh host "su -lc 'cp -r -- $location2 $location1'"
ただし、これは以下を実行するのと同じです。
eval eval "cp -r -- $location2 $location1"
つまり、これらの変数は引数として渡されず、シェル(リモートユーザーのログインシェルで始まる)コードcp
として解釈されます(2回)。したがって、変数がある場合、劇的な結果が発生します。sh
su
$location1
/somewhere;rm -rf /
正しい方法は、リモートシェルを正しくエスケープすることです。シェルには2つのレベルがあるため、単一引用符を2回エスケープする必要があります(ksh93
ここでは//構文が使用されています)。bash
zsh
escaped_location1=\'${location1//\'/\'\\\'\'}\'
escaped_location1=${escaped_location1//\'/\'\\\'\'}
escaped_location2=\'${location2//\'/\'\\\'\'}\'
escaped_location2=${escaped_location2//\'/\'\\\'\'}
ssh host "su -lc 'cp -r -- $escaped_location2 $escaped_location1'"
リモートユーザーのログインシェルはBourneに似ていると仮定します。