10

リモート マシンで複数のコマンドを順番に実行したいのですが、後のコマンドの一部は前のコマンドに依存しています。最も単純な例では、次のようになります。

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 つのスクリプト ファイル内にあるため、すべてをまとめておくとよいでしょう。

4

2 に答える 2

10

この例では

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' )

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

于 2013-03-06T13:46:21.560 に答える
6

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`;

How to use SSH to run a shell script on a remote machine?に触発されて、ヒアドキュメントも見ました。および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
于 2013-03-11T13:27:47.323 に答える