можно ли использовать переменные в удаленной команде 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`  &/dev/null ) & )"' &
jabref_dir: Undefined variable.

таким образом, всякий раз, когда jabref обновляется до новой версии на сервере, мне не придется вручную обновлять путь к файлу jar. Программе jabref исполняемый файл не принимает аргументы, но запускает его с помощью java -jar делает, поэтому я должен немного жонглировать пути.

на данный момент у меня есть список команд в отдельный файл сценария и вызвать

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

который работает, но поскольку вызов ssh уже находится внутри одного файла сценария, было бы неплохо иметь все вместе.

2 ответов


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. Эта строка захватывается и сохраняется в переменной на локальном хосте.


С некоторым вдохновением от chepner у меня теперь есть решение, которое работает, но только при вызове из оболочки bash или скрипта bash. Он не работает от tcsh.

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

исходя из этого, приведенный ниже код является локальным скриптом, который запускает jabref на удаленном сервере (хотя с X-forwarding по умолчанию и без пароля пользователь не может сказать, что он удален):

#!/bin/bash
if [ -f "" ]
then
    fname_start=$(echo ${1:0:4})
    if [ "$fname_start" = "/tmp" ]
    then
        scp  my_server:
        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 )'" &
    else
        echo input argument must be a file in /tmp.
else
    echo this function requires 1 argument
fi

и это 1-строчный скрипт load_module, так как modulecmd устанавливает переменные среды и I не мог понять, как это сделать без поиска сценария.

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

Я также посмотрел на heredocs, вдохновленный как использовать 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