web-dev-qa-db-ja.com

リモートsshコマンドで変数を使用することは可能ですか?

リモートマシンでいくつかのコマンドを順番に実行したいのですが、後のコマンドのいくつかは前のコマンドに依存しています。最も単純な例では、これを取得します。

ssh my_server "echo this is my_server; abc=2;"
this is my_server
abc=2: Command not found.
ssh my_server "echo this is my_server; abc=2; echo abc is $abc"
abc: undefined variable

少し背景情報として、私が実際にやりたいのは、パスをつなぎ合わせてJavaアプリケーション:

ssh my_server 'Nohup sh -c "( ( echo this is my_server; jabref_exe=`which jabref`; jabref_dir=`dirname $jabref_exe`; Java -jar $jabref_dir/../jabref.jar` $1 &/dev/null ) & )"' &
jabref_dir: Undefined variable.

そうすれば、jabrefがサーバー上で新しいバージョンに更新されるたびに、jarファイルへのパスを手動で更新する必要がなくなります。 jabref実行可能ファイルは引数を取りませんが、Java -jarを使用して起動すると引数を取ります。そのため、パスを少し調整する必要があります。

現時点では、別のスクリプトファイルにコマンドのリストがあり、

ssh my_server 'Nohup sh -c "( ( my_script.sh &/dev/null ) & )"' &

これは機能しますが、ssh呼び出しはすでに1つのスクリプトファイル内にあるため、すべてをまとめておくと便利です。

8
craq

Chepnerからのインスピレーションを受けて、bashシェルまたはbashスクリプトから呼び出された場合にのみ機能するソリューションができました。 tcshからは機能しません。

ssh my_server "bash -c 'echo this is \$HOSTNAME; abc=2; echo abc is \$abc;'"

これに基づいて、以下のコードはリモートサーバーでjabrefを実行するローカルスクリプトです(ただし、デフォルトでX転送が使用され、パスワードなしの認証では、ユーザーはリモートであるとは言えません)。

#!/bin/bash
if [ -f "$1" ]
then
    fname_start=$(echo ${1:0:4})
    if [ "$fname_start" = "/tmp" ]
    then
        scp $1 my_server:$1
        ssh my_server "bash -c 'source load_module jdk; source load_module jabref; Java_exe=\$(which Java); jabref_exe=\$(which jabref); jabref_dir=\$(echo \${jabref_exe%/bin/jabref});eval \$(Java -jar \$jabref_dir/jabref.jar $1)'" &
    else
        echo input argument must be a file in /tmp.
else
    echo this function requires 1 argument
fi

modulecmdは環境変数を設定し、スクリプトを入手せずにそれを行う方法を理解できなかったため、これは1行のスクリプトload_moduleです。

eval `/path/to/modulecmd bash load $1`;

SSHを使用してリモートマシンでシェルスクリプトを実行する方法 および http://tldp.org/LDP/abs/html/here-)に触発されたヒアドキュメントも調べました。 docs.html 。良い部分は、tcshからでも機能することです。これはコマンドラインから機能しましたが、スクリプト内では機能しませんでした。それはおそらく修正するのに十分簡単ですが、私は今解決策を持っているので私は幸せです:-)

ssh my_server 'bash -s' << EOF
echo this is \$HOSTNAME; abc=2; echo abc is \$abc;
EOF
6
craq

この例では

ssh my_server "echo this is my_server; abc=2;"

abcはリモート側で設定されているため、ローカルマシンで設定されていない理由を明確にする必要があります。

次の例では、

ssh my_server "echo this is my_server; abc=2; echo abc is $abc"

ローカルシェルは、リモートホストに送信される前に、引数の$abcを展開しようとします。わずかな変更が期待どおりに機能します。

ssh my_server 'echo this is my_server; abc=2; echo abc is $abc'

一重引用符は、ローカルシェルが$abcを展開しようとするのを防ぎます。そのため、リテラルテキストはリモートホストに到達します。


最終的にあなたの本当の質問に取り組むために、これを試してください:

jabref_dir=$( ssh my_server 'jabref_exe=$(which jabref); jabref_dir=$(dirname $jabref_exe);
               Java -jar $jabref_dir/../jabref.jar > /dev/null; echo $jabref_dir' )

これにより、引用符で囲まれた文字列がリモートサーバー上でコマンドとして実行され、$jabref_dirという1つの文字列が出力されます。その文字列はキャプチャされ、ローカルホストの変数に格納されます。

9
chepner