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