Назад | Перейти на главную страницу

удаленная команда SSH работает, но не при использовании в сценарии bash

Я пытаюсь остановить tomcat на удаленном сервере с помощью сценария bash. Вот функция:

function stop_remote_tomcat () {
    CURRENT_SERVER=$1
    CURRENT_USER=$2
    CURRENT_PEM_FILE=$3

    COMMAND="ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER \"/bin/sh sudo /etc/init.d/tomcat stop\""
    echo $COMMAND
    $COMMAND
}

Затем внутри оператора case вызывается эта функция.

Моя проблема в том, что я просто копирую вывод echo $COMMAND оператор и запустить его как независимую команду, он отлично работает. Но при запуске в скрипте выдает ошибку:

sudo /etc/init.d/tomcat stop: No such file or directory

Может кто-нибудь объяснить, как этого можно достичь в сценарии bash?

Краткий ответ: см. BashFAQ # 50: Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!.

Длинный ответ: помещение команд в переменные работает неправильно из-за порядка, в котором оболочка анализирует вещи. В частности, он анализирует кавычки, экранирование и тому подобное, прежде чем расширять переменные, поэтому встраивание кавычек в переменные не работает - к тому времени, когда они находятся в командной строке, им уже слишком поздно делать что-нибудь полезное.

Можно было бы сохранить команду в массиве вместо простой переменной, а затем использовать printf %q процитировать любые части, которые нуждаются в нем для печати:

[...]
COMMAND=(ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER "/bin/sh sudo /etc/init.d/tomcat stop")
printf "%q " "${COMMAND[@]}"
echo    # Because printf won't add a linefeed
"${COMMAND[@]}"

Проблема в том, что есть много способов заключить переменную в кавычки / избежать пробелов и %q не можете выбрать то, что вам нравится. Другой вариант - пропустить сохранение команды и просто распечатать ее «вручную»:

[...]
echo "ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER \"/bin/sh sudo /etc/init.d/tomcat stop\""
ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER "/bin/sh sudo /etc/init.d/tomcat stop"