is it possible to use variables in remote ssh comm

2020-01-27 07:41发布

I'd like to execute several commands in sequence on a remote machine, and some of the later commands depend on earlier ones. In the simplest possible example I get this:

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

For a bit of background info, what I actually want to do is piece together a path and launch a java application:

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.

That way, whenever jabref gets updated to a new version on the server, I won't have to manually update the path to the jar file. The jabref executable doesn't take arguments, but launching it with java -jar does, which is why I have to juggle the path a bit.

At the moment I have the list of commands in a separate script file and call

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

which works, but since the ssh call is already inside one script file it would be nice to have everything together.

2条回答
Root(大扎)
2楼-- · 2020-01-27 08:11

In this example

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

abc is set on the remote side, so it should be clear why it is not set on your local machine.

In the next example,

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

your local shell tries to expand $abc in the argument before it is ever sent to the remote host. A slight modification would work as you expected:

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

The single quotes prevent your local shell from trying to expand $abc, and so the literal text makes it to the remote host.


To finally address your real question, try this:

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

This will run the quoted string as a command on your remote server, and output exactly one string: $jabref_dir. That string is captured and stored in a variable on your local host.

查看更多
虎瘦雄心在
3楼-- · 2020-01-27 08:28

With some inspiration from chepner, I now have a solution that works, but only when called from a bash shell or bash script. It doesn't work from tcsh.

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

Based on this, the code below is a local script which runs jabref on a remote server (although with X-forwarding by default and passwordless authentication the user can't tell it's remote):

#!/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

and this is the 1-line script load_module, since modulecmd sets environment variables and I couldn't figure out how to do that without sourcing a script.

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

I also looked at heredocs, inspired by How to use SSH to run a shell script on a remote machine? and http://tldp.org/LDP/abs/html/here-docs.html. The nice part is that it works even from tcsh. I got this working from the command line, but not inside a script. That's probably easy enough to fix, but I've got a solution now so I'm happy :-)

ssh my_server 'bash -s' << EOF
echo this is \$HOSTNAME; abc=2; echo abc is \$abc;
EOF
查看更多
登录 后发表回答