リモートsshコマンドで変数を渡す


99

sshを使用して自分のマシンからコマンドを実行し、環境変数を通過できるようにしたい $BUILD_NUMBER

これが私が試していることです:

ssh pvt@192.168.1.133 '~/tools/myScript.pl $BUILD_NUMBER'

$BUILD_NUMBER はssh呼び出しを行うマシンで設定され、変数はリモートホストに存在しないため、取得されません。

の値を渡すにはどうすればよい$BUILD_NUMBERですか?


1
ハドソンとは無関係で、タグを削除しました。(ハドソンは変数を作成するだけです)
Peter Schuetze 2010

回答:


188

使用する場合

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

の代わりに

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

シェルは$BUILD_NUMBER、コマンド文字列をリモートホストに送信する前にを補間します。


8
誰かが単一引用符を使用する必要があるため、引用符に含まれているコマンドがローカルで評価されない場合は、「 '$ VARIABLE'」を使用する必要があります。例:ssh pvt@192.168.1.133 '〜/ tools / run_pvt.pl "' $ BUILD_NUMBER '"'
dr.doom

3
bashが単一引用符と二重引用符で異なる反応をすることを知りませんでした。ありがとう!
silgon 2017

1
Linuxコアの開発者は地獄で燃やす必要があります
goldstar

@goldstar、シェルでの単一引用符と二重引用符の動作の違いは、Linuxよりも数十年前から存在していることに注意してください。
sarnold

3
PSA:文字列にユーザー入力が含まれている場合、これは非常に悪い考えであり、コードインジェクション攻撃を受ける可能性があります。
ブライアンマカッション

27

単一引用符内の変数は評価されません。二重引用符を使用します。

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

シェルは変数を二重引用符で展開しますが、単一引用符では展開しません。これは、sshコマンドに渡される前に目的の文字列に変更されます。


2

(この答えは不必要に複雑に見えるかもしれませんが、私が知る限り、それは空白と特殊文字に関して簡単に拡張可能で堅牢です。)

sshコマンドの標準入力とreadリモートの場所から直接データをフィードできます。

次の例では、

  1. インデックス付き配列には、(便宜上)リモート側で値を取得する変数の名前が入ります。
  2. これらの変数のそれぞれについて、変数sshの名前と値を示すヌル終了行を指定します。
  3. ではshhコマンド自体、私たちは、これらの線をループに必要な変数を初期化します。
# Initialize examples of variables.
# The first one even contains whitespace and a newline.
readonly FOO=$'apjlljs ailsi \n ajlls\t éjij'
readonly BAR=ygnàgyààynygbjrbjrb

# Make a list of what you want to pass through SSH.
# (The “unset” is just in case someone exported
# an associative array with this name.)
unset -v VAR_NAMES
readonly VAR_NAMES=(
    FOO
    BAR
)

for name in "${VAR_NAMES[@]}"
do
    printf '%s %s\0' "$name" "${!name}"
done | ssh user@somehost.com '
    while read -rd '"''"' name value
    do
        export "$name"="$value"
    done

    # Check
    printf "FOO = [%q]; BAR = [%q]\n" "$FOO" "$BAR"
'

出力:

FOO = [$'apjlljs ailsi \n ajlls\t éjij']; BAR = [ygnàgyààynygbjrbjrb]

exportそれらが必要ない場合は、のdeclare代わりに使用できるはずですexport

本当に簡易版(あなたがなど、プロセスに単一の変数を持って、拡張性を必要としない場合)のようになります。

$ ssh user@somehost.com 'read foo' <<< "$foo"

2

デフォルトでSSHDで受け入れられる環境変数のリストには、が含まれますLC_*。したがって:

LC_MY_BUILDN="1.2.3" ssh -o "SendEnv LC_MY_BUILDN" ssh-host 'echo $LC_MY_BUILDN'
1.2.3

0

以前に回答したように、リモートホストで環境変数を設定する必要はありません。代わりに、ローカルホストでメタ拡張を実行し、値をリモートホストに渡すだけです。

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

リモートホストで環境変数を設定して使用する場合は、envプログラムを使用できます。

ssh pvt@192.168.1.133 "env BUILD_NUMBER=$BUILD_NUMBER ~/tools/run_pvt.pl \$BUILD_NUMBER"

この場合、これは少しやりすぎです。

  • env BUILD_NUMBER=$BUILD_NUMBER ローカルホストでメタ拡張を行います
  • リモートBUILD_NUMBER環境変数は
    リモートシェルによって使用されます

0

sshを介して環境変数を明示的に渡すことも可能です。サーバー側の設定が必要なので、これは普遍的な答えではありません。

私の場合、バックアップリポジトリの暗号化キーをそこに保存せずにバックアップストレージサーバーのコマンドに渡したかったのですが、環境変数はps!stdinでキーを渡すという解決策も機能しますが、面倒すぎます。いずれにせよ、sshを介して環境変数を渡す方法は次のとおりです。

サーバーでsshd_config、通常はファイルを編集し、渡す変数に一致/etc/ssh/sshd_configするAcceptEnvディレクティブを追加します。を参照してくださいman sshd_config。私の場合、変数をボーグバックアップに渡したいので、次のように選択しました。

AcceptEnv BORG_*

ここで、クライアントで-o SendEnvオプションを使用して環境変数を送信します。次のコマンドラインは、環境変数BORG_SECRETを設定してから、クライアントマシン(と呼ばれるbackup)に送信されるようにフラグを立てます。次に、printenvそこで実行され、BORG変数の出力をフィルタリングします。

$ BORG_SECRET=magic-happens ssh -o SendEnv=BORG_SECRET backup printenv | egrep BORG
BORG_SECRET=magic-happens

デフォルトのサーバー側設定を使用して変数を「密輸」できます私の回答を参照してください。要点は、デフォルトのOpenSSHd構成にはLC_*送信可能な変数が含まれているため$LC_TvE_foo、またはを使用する$LC_BORG_SECRETだけで、組み込み変数と「衝突」しないようにしてください。
Alex Stragies

-2

sshセッションの外で変数にアクセスするために変数をエスケープします:ssh pvt@192.168.1.133 "〜/ tools / myScript.pl \ $ BUILD_NUMBER"


2
これは、質問が求めていることを達成しません。
Patrick Trentin 2017

2
シェルの観点からは、'$FOO'と同等"\$FOO"です。問題は、「SSHでシェル変数を渡す方法」でした。@PatrickTrentinですでに述べたように、BUILD_NUMBER環境変数がリモートで設定されていないため、これは正しい答えではありません。
Gilles Gouaillardet 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.