Вопрос или проблема
Я хочу выполнить скрипт, start.sh
, на удаленном сервере, который запускает следующее:
nohup node server.js &
Наивно, я вызываю SSH таким образом:
ssh myserver <<EOF
./start.sh &
EOF
Это запускает скрипт, но оставляет сессию подключенной. Я хочу выполнить этот шаг с другими командами в скрипте, так что это не подходит.
Как я могу подключиться по SSH к удаленному компьютеру, запустить команду nohup
в фоновом режиме, а затем отключиться? Полагаю, я мог бы поместить сам процесс SSH в фоновый режим, но это кажется неправильным.
Вы уже нашли правильный способ, как документ здесь.
ПРИМЕЧАНИЕ: вы можете поместить SSH (клиент) в фоновый режим, добавив & в конце, но вы не увидите вывод. Если вы действительно хотите это сделать, перенаправьте stdout/stderr в файл на случай, если вам нужно будет проверить ответ от удаленного хоста.
В основном, вы можете сделать это любым способом:
Непосредственное выполнение команд{,и}
ssh user@host "nohup command1 > /dev/null 2>&1 &; nohup command2; command3"
ИЛИ
ssh user@host "$(nohup command1 > /dev/null 2>&1 &) && nohup command2 >> /path/to/log 2>&1 &"
ПРИМЕЧАНИЕ:
&&
требует, чтобы первая команда вернула 0, прежде чем выполнить вторую
Использовать документ Здесь
ssh user@host << EOF
nohup command1 > /dev/null 2>&1 &
nohup command2 >> /path/to/command2.log 2>&1 &
......
EOF
Любой из трех вышеуказанных вариантов должен сработать для вас.
Кроме того, взгляните на ответ здесь: https://askubuntu.com/a/348921/70270
ssh node "nohup sleep 10 &"
не запускается в режиме демона, оставляя вашу SSH сессию подключенной. Сессия SSH завершится через 10 секунд, несмотря на использование nohup.
Причина в том, что удаленные stdout и stderr все еще подключены к вашей сессии. Это поддерживает сессию SSH в активном состоянии, nohup не помогает.
Это:
ssh node "nohup sleep 10 1>/dev/null 2>/dev/null &"
возвращается немедленно. Он действительно запускает удаленный процесс с использованием nohup и немедленно завершает сессию SSH.
Почему бы просто не использовать tmux или screen и забыть об этом? Например:
$ tmux new -s SessionNameHere
$ nohup /path/to/your/script.sh
Это практично, если это что-то, что будет выполнять циклы или займет некоторое время для завершения. Вы можете отключиться от сессии, и она останется активной.
Короче говоря:
ssh host "(command 1; command 2; ...) &>/dev/null &"
Кажется, что bash сам по себе выполняет отсоединение от терминала, так что nohup не требуется. Я использую Ubuntu 14.04 x86_64, bash 4.3.11.
И последнее, но не менее важное, не забывайте не выделять tty для вашей сессии.
Если вы это сделаете, это не сработает.
Так что если у вас есть -t или -tt или -ttt и так далее в вашей команде. Вот почему это не работает для вас.
Вместо этого
ssh -tt host "(command 1; command 2; ...) &>/dev/null &"
Используйте
ssh host "(command 1; command 2; ...) &>/dev/null &"
Ответ Терри Ванга помог мне прийти к своему решению, но я хотел бы опубликовать это отдельно для тех, кто ищет, как запустить более сложные скрипты:
EXIT_CODE_FILE="/tmp/exit_code_file"
TIMING_FILE="/tmp/timing_file"
LOG_FILE="/tmp/log_file"
ssh "${SSH_USER}@${HOST_ADDRESS}" "nohup bash -c '
# Подключаем .bashrc, потому что это не происходит автоматически для ssh команд
source ~/.bashrc
echo "START: $(date +%s)" > ${TIMING_FILE}
# Выполняем вашу команду/скрипт и записываем его stdout/stderr потоки
my_command.sh --with args > ${LOG_FILE} 2>&1
# Сохраняем код выхода
echo \$? > ${EXIT_CODE_FILE}
echo "END: $(date +%s)" >> ${TIMING_FILE}
' > /dev/null 2>&1 &"
Команда nohup
обеспечивает выполнение всей обернутой команды, предоставленной bash, до окончания, даже когда мы отключаемся, в то время как его стандартные потоки вывода перенаправляются на /dev/null
, а &
выполняет все в фоновом режиме. Таким образом, только команда, которая нас интересует, выводит результаты на указанный журнал.
В этот момент достаточно просто реализовать возобновляемое поведение опроса, опрашивая EXIT_CODE_FILE до получения результата.
echo "Waiting for remote operation to complete..."
while true; do
# Проверяем, существует ли файл с кодом выхода и имеет ли он значение
EXIT_CODE=$(ssh "${SSH_USER}@${HOST_ADDRESS}" "cat ${EXIT_CODE_FILE} 2>/dev/null || echo 'pending'")
if [ "$EXIT_CODE" != "pending" ]; then
break
fi
echo -n "."
sleep 5
done
# Операция завершена
if [ "$EXIT_CODE" -eq 0 ]; then
echo "Удаленная операция завершена успешно"
else
echo "Удаленная операция завершилась с кодом ошибки: $EXIT_CODE"
fi
echo ""
echo "Файл временных данных:"
ssh "${SSH_USER}@${HOST_ADDRESS}" "cat ${TIMING_FILE}"
echo "Вывод удаленного журнала:"
ssh "${SSH_USER}@${HOST_ADDRESS}" "cat ${LOG_FILE}"
if [ "$EXIT_CODE" -ne 0 ]; then
exit $EXIT_CODE
fi
.
Ответ или решение
Запуск процесса на удаленном сервере с использованием SSH и nohup
– это распространенная задача для администраторов и разработчиков, которые работают с удаленными серверами. Однако, часто возникает проблема, когда сессия SSH остается открытой после запуска команды, что может препятствовать выполнению следующих команд в скрипте. В этом ответе рассмотрим, как правильно использовать nohup
и SSH для выполнения задачи, а также предложим альтернативные подходы.
Теория
SSH (Secure Shell) – это протокол, позволяющий безопасно подключаться и управлять удаленными серверами. При помощи SSH можно выполнять различные задачи, такие как передача файлов, запуск команд и управление системами. Одной из основных его задач в контексте запуска скриптов является возможность автоматизировать запуск процессов на удаленной машине.
Команда nohup
(от No Hangup) позволяет запускать процессы, которые продолжают работу даже после выхода из системы или закрытия терминала. Она перенаправляет стандартный вывод в файл nohup.out
, если не указано иное. Это особенно полезно при работе через SSH, когда необходимо запустить длительные процессы и отсоединиться, не прерывая их выполнение.
Пример
Рассмотрим пример использования SSH и nohup
для запуска скрипта start.sh
, который, в свою очередь, запускает сервер Node.js на удаленной машине. Стандартный способ запуска через SSH может выглядеть следующим образом:
ssh myserver <<EOF
./start.sh &
EOF
Однако, такая конструкция оставляет SSH-сессию открытой. Чтобы этого избежать и все же запустить процесс на удаленном сервере, необходимо использовать nohup
и корректно перенаправить потоки вывода:
ssh user@remote-server "nohup bash -c './start.sh &> /dev/null &'"
Применение
Данный подход позволяет автоматически и безопасно запускать процесс на удаленной машине и при этом отключиться от сессии SSH. Процесс будет работать в фоне, а сам SSH-соединение мгновенно закрывается, что позволяет продолжить выполнение других команд в вашем локальном скрипте.
Сложные сценарии
Если ваша задача предполагает более сложные сценарии, такие как выполнение нескольких команд или проверка статуса выполнения, можно использовать конструкции со вложенными и логически более сложными операциями. Например, для последовательного выполнения нескольких команд:
ssh user@remote-server "nohup bash -c 'command1; command2; command3' &> /dev/null &"
В этом примере команды command1
, command2
и command3
будут выполняться последовательно, и все стандартные потоки будут перенаправлены в /dev/null
, что предотвратит блокировку SSH-сеанса.
Альтернативные подходы
Хотя nohup
в таких сценариях с SSH является наиболее распространенной практикой, существуют и другие подходы, такие как использование tmux
или screen
. Эти инструменты создают виртуальные терминальные сессии, которые остаются активными даже после выхода из SSH. Например:
tmux new-session -d -s mysession './start.sh'
Такой метод создает новую сессию tmux
с именем mysession
и запускает команду ./start.sh
. Вы можете вернуть эту сессию позже и просмотреть результаты выполнения.
Заключение
Использование nohup
совместно с SSH – это эффективный способ управления длительными удаленными процессами без постоянного подключения к терминалу. Основное преимущество заключается в возможности автоматизации и освобождении локального терминала для других предприятий. С другой стороны, такие инструменты как tmux
и screen
предоставляют дополнительные возможности управления и мониторинга процессов, оставаясь активными после отключения от SSH.
Таким образом, выбор подхода зависит от специфики задачи, доступных инструментов и требований к мониторингу и управлению процессами. Всегда важно учитывать необходимость перенаправления потоков ввода-вывода, чтобы избежать неожиданного поведения и без необходимости оставления открытых соединений.