У меня есть скрипт bash, который запускает скрипт python3 (давайте назовем его startup.sh
) с ключевой строкой:
nohup python3 -u <script> &
Когда я ssh
вызываю этот скрипт напрямую, скрипт python продолжает работать в фоновом режиме после выхода. Тем не менее, когда я запускаю это:
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
Процесс заканчивается, как только ssh
он завершится, и закрывает сеанс.
Какая разница между двумя?
РЕДАКТИРОВАТЬ: скрипт Python запускает веб-сервис через бутылку.
РЕДАКТИРОВАТЬ 2: Я также попытался создать сценарий инициализации, который вызывает startup.sh
и работает ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "sudo service start <servicename>"
, но получил то же самое поведение.
EDIT3: Может быть, это что-то еще в сценарии. Вот основная часть скрипта:
chmod 700 ${key_loc}
echo "INFO: Syncing files."
rsync -azP -e "ssh -i ${key_loc} -o StrictHostKeyChecking=no" ${source_client_loc} ${remote_user}@${remote_hostname}:${destination_client_loc}
echo "INFO: Running startup script."
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart"
EDIT4: когда я запускаю последнюю строку со сном в конце:
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart; sleep 1"
echo "Finished"
Он никогда не достигает echo "Finished"
, и я вижу сообщение сервера Bottle, которого я никогда раньше не видел:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
Я вижу «Закончено», если я вручную запускаю SSH и убиваю процесс сам.
EDIT5: Используя EDIT4, если я делаю запрос к любой конечной точке, я получаю страницу назад, но бутылка выдает ошибку:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
----------------------------------------
Exception happened during processing of request from ('<IP>', 55104)
источник
strace
если вы используете Linux илиtruss
Solaris и посмотрите, как и почему он завершается. Как напримерssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> strace -fo /tmp/debug ./startup.sh
.&
в конце сценария запуска? Добавление&
оператора удаляет зависимость вашего ssh-сеанса от родительского идентификатора (когда родительские идентификаторы умирают, это делают и их дети). Также я думаю, что это дублирующий вопрос, основанный на этом предыдущем посте. Пост, который я представил вам в предыдущем предложении, является дубликатом этого поста, который может дать более подробные сведения.nohup ./startup.sh &
раньше, но у него было такое же поведение.startup.sh
уже содержит форк (nohup python3 -u <script> &
), так что я уверен, что мне не нужно снова форкать.Ответы:
Я бы отключил команду от стандартного потока ввода / вывода и ошибок:
ssh
нужен индикатор, который больше не выводит и не требует ввода. Имея что-то еще на входе и перенаправляя средства вывода,ssh
можно безопасно выйти, так как ввод / вывод не поступает или не идет к терминалу. Это означает, что ввод должен происходить откуда-то еще, а вывод (как STDOUT, так и STDERR) должен идти куда-то еще.</dev/null
Часть определяет в/dev/null
качестве входных данных для<script>
. Почему это полезно здесь:В качестве альтернативы, перенаправление из другого входного источника должно быть относительно безопасным, если текущий
ssh
сеанс не нужно держать открытым.С этой
>/dev/null
частью оболочка перенаправляет стандартный вывод в / dev / null, по существу отбрасывая его.>/path/to/file
тоже будет работать.Последняя часть
2>&1
перенаправляет STDERR в STDOUT.источник
nohup python3 -u <script> >/dev/null 2>&1 &
иnohup python3 -u <script> > nohup.out 2>&1 &
работал. Я думал, что nohup автоматически перенаправляет весь вывод - какая разница?nohup
у вас на удаленном хосте? POSIXnohup
не требуется для перенаправленияstdin
, что я пропустил, но он все равно должен перенаправитьstdout
иstderr
.nohup (GNU coreutils) 8.21
.nohup
печатает ли какие-нибудь сообщения, какnohup: ignoring input and appending output to ‘nohup.out’
?Посмотрите на
man ssh
:При запуске
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
вы запускаете сценарий оболочки startup.sh как команда ssh.Из описания:
Исходя из этого, он должен запускать скрипт удаленно.
Разница между этим и выполнением
nohup python3 -u <script> &
в локальном терминале заключается в том, что он запускается как локальный фоновый процесс, в то время как команда ssh пытается запустить его как удаленный фоновый процесс.Если вы собираетесь запустить скрипт локально, не запускайте startup.sh как часть команды ssh. Вы можете попробовать что-то вроде
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> && "./startup.sh"
Если вы намерены запустить скрипт удаленно и хотите, чтобы этот процесс продолжался после завершения сеанса ssh, вам сначала нужно будет запустить
screen
сеанс на удаленном хосте. Затем вы должны запустить скрипт python на экране, и он продолжит работать после того, как вы завершите сеанс ssh.Смотрите Руководство пользователя экрана
Хотя я думаю, что screen - ваш лучший вариант, если вы должны использовать nohup,
shopt -s huponexit
перед запуском команды nohup рассмотрите возможность установки на удаленном хосте. Кроме того, вы можете использовать,disown -h [jobID]
чтобы отметить процесс, чтобы SIGHUP не отправлялся на него. 1Кроме того, ознакомьтесь с кратким описанием того, как
huponexit
работает, когда оболочка закрывается, удаляется или удаляется. Я предполагаю, что ваша текущая проблема связана с тем, как завершается сеанс оболочки. 2Наконец, вот несколько примеров того, как использовать купированный гупонексит. 3
источник
bash
странице, этоhuponexit
должно влиять только на интерактивные оболочки, а не на скрипты - «Если опция оболочки huponexit была установлена с помощью shopt, bash отправляет SIGHUP всем работам при выходе из интерактивной оболочки входа».Может стоит попробовать
-n
вариант при запускеssh
? Это предотвратит зависимость удаленного процесса от локальногоstdin
, который, конечно же, закроется, как толькоssh session
закончится. И это приведет к удаленному прекращению цен, когда он попытается получить к нему доступstdin
.источник
Я подозреваю, что у вас есть состояние гонки. Было бы что-то вроде этого:
Если бы ssh не сократил ситуацию, произошло бы следующее (не уверен насчет порядка этих двух):
Таким образом, последние два критических шага не выполняются, потому что startup.sh и ssh заканчивают работу до того, как nohup успевает сделать свое дело.
Я ожидаю, что ваша проблема исчезнет, если вы поместите несколько секунд сна в конец файла startup.sh. Я не уверен, сколько именно вам нужно времени. Если важно свести это к минимуму, то, возможно, вы можете посмотреть что-то в proc, чтобы увидеть, когда это безопасно.
источник
/proc/$!/comm
, нет лиnohup
или более переносимо использовать выводps -o comm= $!
.Это больше похоже на проблему с тем, что делает
python
скрипт илиpython
сам по себе. Все, что наnohup
самом деле делает (исключая перенаправления), это просто устанавливает обработчик дляHUP
сигналаSIG_IGN
(игнорировать) перед запуском программы. Ничто не мешает программе установить ее обратноSIG_DFL
или установить собственный обработчик после запуска.Одна вещь, которую вы, возможно, захотите попробовать, - заключить вашу команду в круглые скобки, чтобы получить эффект двойной вилки, и ваш
python
сценарий больше не является дочерним процессом процесса оболочки. Например:Еще одна вещь, которую также стоит попробовать (если вы используете,
bash
а не другую оболочку), это использоватьdisown
вместо встроеннойnohup
. Если все работает так, как задокументировано, это на самом деле не должно иметь никакого значения, но в интерактивной оболочке это остановит распространениеHUP
сигнала в вашpython
сценарий. Вы можете добавить disown на следующей строке или на той же, что и ниже (обратите внимание, что добавление;
после a&
означает ошибку вbash
):Если вышеперечисленное или какая-то его комбинация не работает, то, безусловно, единственное место, где можно решить проблему, - это
python
сам скрипт.источник
huponexit
материал, выполнение в подоболочке должно иметь тот же эффект,disown
что и процесс не будет добавлен в список заданий.disown
. Не ожидайте, что это будет иметь большое значение все же. Я думаю, что вам лучше всего изменитьpython
сценарий, чтобы он объяснил вам, почему он выходит.nohup
.Я думаю, что это потому, что работа связана с сессией. Как только это заканчивается, любые пользовательские задания также заканчиваются.
источник
Если вы
nohup
можете открыть его выходной файл, вы можете иметь подсказкуnohup.out
. Это возможноpython
не по пути, когда вы запускаете скрипт черезssh
.Я хотел бы попытаться создать файл журнала для команды. Попробуйте использовать:
источник
ssh
для запуска сценария вручную, поэтому я предполагаю, что Python3 находится в пути.