是否可以在远程ssh命令中使用变量?

cra*_*raq 8 ssh shell variable-assignment nohup

我想在远程机器上按顺序执行几个命令,后面的一些命令依赖于之前的命令.在最简单的例子中,我得到了这个:

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
Run Code Online (Sandbox Code Playgroud)

有关背景信息,我实际想要做的是拼凑一个路径并启动一个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.
Run Code Online (Sandbox Code Playgroud)

这样,每当jabref更新到服务器上的新版本时,我就不必手动更新jar文件的路径.jabref可执行文件不接受参数,而是使用do启动它java -jar,这就是为什么我必须稍微改变路径.

目前,我在单独的脚本文件中有命令列表并调用

ssh my_server 'nohup sh -c "( ( my_script.sh &/dev/null ) & )"' &
Run Code Online (Sandbox Code Playgroud)

这是有效的,但由于ssh调用已经在一个脚本文件中,所以将所有内容放在一起会很不错.

che*_*ner 9

在这个例子中

ssh my_server "echo this is my_server; abc=2;"
Run Code Online (Sandbox Code Playgroud)

abc 设置在远程端,因此应该清楚为什么它没有在本地计算机上设置.

在下一个例子中,

ssh my_server "echo this is my_server; abc=2; echo abc is $abc"
Run Code Online (Sandbox Code Playgroud)

在将本地shell $abc发送到远程主机之前,它会尝试在参数中展开.稍作修改可以按预期工作:

ssh my_server 'echo this is my_server; abc=2; echo abc is $abc'
Run Code Online (Sandbox Code Playgroud)

单引号可以防止本地shell尝试扩展$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' )
Run Code Online (Sandbox Code Playgroud)

这将在远程服务器上将带引号的字符串作为命令运行,并输出一个字符串:$jabref_dir.捕获该字符串并将其存储在本地主机上的变量中.

  • 谢谢,这让我走上了正轨。防止通过引号或“\$”进行扩展是关键。事实证明,服务器上的默认 shell 是 tcsh,这是 `abc=2` 不起作用的另一个原因。 (2认同)

cra*_*raq 6

从chepner获得一些灵感,我现在有一个可行的解决方案,但只有从bash shell或bash脚本调用时才有效.它不适用于tcsh.

ssh my_server "bash -c 'echo this is \$HOSTNAME; abc=2; echo abc is \$abc;'"
Run Code Online (Sandbox Code Playgroud)

基于此,下面的代码是一个本地脚本,它在远程服务器上运行jabref(虽然默认情况下使用X-forwarding和无密码身份验证,但用户无法告诉它是远程服务器):

#!/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
Run Code Online (Sandbox Code Playgroud)

这是1行脚本load_module,因为modulecmd设置环境变量,我无法弄清楚如何在不获取脚本的情况下执行此操作.

eval `/path/to/modulecmd bash load $1`;
Run Code Online (Sandbox Code Playgroud)

我还看了heredocs,受如何使用SSH在远程机器上运行shell脚本的启发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
Run Code Online (Sandbox Code Playgroud)