Eu tenho um script bash que inicia um script python3 (vamos chamá-lo startup.sh
), com a linha de chave:
nohup python3 -u <script> &
Quando eu entro ssh
diretamente e chamo esse script, o script python continua sendo executado em segundo plano depois que eu saio. No entanto, quando eu executo isso:
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
O processo termina assim que ssh
terminar de executá-lo e fecha a sessão.
Qual é a diferença entre os dois?
EDIT: O script python está executando um serviço da web via Bottle.
EDIT2: Também tentei criar um script init que chame startup.sh
e execute ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "sudo service start <servicename>"
, mas tenha o mesmo comportamento.
EDIT3: Talvez seja algo mais no script. Aqui está a maior parte do script:
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: Quando corro a última linha com um sono no final:
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"
Ele nunca chega echo "Finished"
e vejo a mensagem do servidor Bottle, que nunca vi antes:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
Eu vejo "Concluído" se eu fizer o SSH manualmente e matar o processo pessoalmente.
EDIT5: Utilizando EDIT4, se eu fizer uma solicitação para qualquer terminal, eu recebo uma página de volta, mas o Bottle erro:
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)
fonte
strace
se você estiver usando Linux outruss
se estiver executando o Solaris e ver como / por que ele termina. Como por exemplossh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> strace -fo /tmp/debug ./startup.sh
.&
no final do script de inicialização? A adição de&
remove a dependência da sua sessão ssh de ser o ID pai (quando os IDs pais morrem, seus filhos também). Também acho que essa é uma pergunta duplicada com base neste post anterior. A postagem que enviei para você na frase anterior é uma duplicata desta postagem, que pode fornecer mais detalhes.nohup ./startup.sh &
antes, mas tinha o mesmo comportamento.startup.sh
já contém um garfo (nohup python3 -u <script> &
), então tenho certeza de que não preciso bifurcar novamente.Respostas:
Eu desconectaria o comando de seus fluxos padrão de entrada / saída e erro:
ssh
precisa de um indicador que não tenha mais saída e que não exija mais entrada. Ter outra coisa como entrada e redirecionar os meios de saídassh
podem sair com segurança, pois a entrada / saída não vem nem vai para o terminal. Isso significa que a entrada precisa vir de outro lugar e a saída (STDOUT e STDERR) deve ir para outro lugar.A
</dev/null
peça especifica/dev/null
como a entrada para<script>
. Por que isso é útil aqui:Como alternativa, o redirecionamento de outra fonte de entrada deve ser relativamente seguro, desde que a
ssh
sessão atual não precise ser mantida aberta.Com a
>/dev/null
parte, o shell redireciona a saída padrão para / dev / null, descartando-a essencialmente.>/path/to/file
também irá funcionar.A última parte
2>&1
está redirecionando STDERR para STDOUT.fonte
nohup python3 -u <script> >/dev/null 2>&1 &
enohup python3 -u <script> > nohup.out 2>&1 &
trabalhou. Eu pensei que o nohup redireciona automaticamente toda a saída - qual é a diferença?nohup
você tem no seu host remoto? Um POSIXnohup
não é necessário para redirecionarstdin
, o que eu perdi, mas ainda deve redirecionarstdout
estderr
.nohup (GNU coreutils) 8.21
.nohup
imprime alguma mensagem, comonohup: ignoring input and appending output to ‘nohup.out’
?Veja
man ssh
:Quando você executa,
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
você está executando o shell script startup.sh como um comando ssh.A partir da descrição:
Com base nisso, ele deve executar o script remotamente.
A diferença entre isso e a execução
nohup python3 -u <script> &
no terminal local é que isso é executado como um processo local em segundo plano, enquanto o comando ssh tenta executá-lo como um processo remoto em segundo plano.Se você pretende executar o script localmente, não execute startup.sh como parte do comando ssh. Você pode tentar algo como
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> && "./startup.sh"
Se sua intenção é executar o script remotamente e você desejar que esse processo continue após o término da sua sessão ssh, você deverá primeiro iniciar uma
screen
sessão no host remoto. Então você deve executar o script python na tela e ele continuará sendo executado após o término da sessão ssh.Consulte o manual do usuário da tela
Enquanto eu acho que a tela é sua melhor opção, se você deve usar nohup, considere a configuração
shopt -s huponexit
no host remoto antes de executar o comando nohup. Como alternativa, você pode usardisown -h [jobID]
para marcar o processo para que o SIGHUP não seja enviado a ele. 1 1Além disso, consulte este resumo de como
huponexit
funciona quando um shell é encerrado, morto ou descartado. Suponho que o seu problema atual esteja relacionado ao final da sessão do shell. 2Finalmente, aqui estão alguns exemplos de como usar o shopt huponexit. 3
fonte
bash
página do manual,huponexit
deve afetar apenas shells interativos e não scripts - 'Se a opção do shell huponexit tiver sido definida com o shopt, o bash envia um SIGHUP para todos os trabalhos quando um shell de logon interativo sai.'Talvez valha a pena tentar a
-n
opção ao iniciar umssh
? Isso evitará a dependência remota do processo em um localstdin
, que é claro que fecha assim quessh session
termina. E isso causará o cancelamento remoto dos preços sempre que ele tentar acessar seusstdin
.fonte
Eu suspeito que você tem uma condição de corrida. Seria algo como isto:
Se o ssh não abreviasse, o seguinte teria acontecido (não tenho certeza sobre a ordem dos dois):
Portanto, as duas etapas críticas finais não acontecem, porque o startup.sh e o ssh terminam antes que o nohup tenha tempo para fazer suas coisas.
Espero que seu problema desapareça se você colocar alguns segundos de sono no final do startup.sh. Não sei exatamente quanto tempo você precisa. Se é importante reduzi-lo ao mínimo, talvez você possa ver algo em proc para ver quando é seguro.
fonte
/proc/$!/comm
se não énohup
ou de forma mais portável a saída deps -o comm= $!
.Isso parece mais um problema com o que o
python
script oupython
ele próprio está fazendo. Tudo o quenohup
realmente faz (bar simplificando os redirecionamentos) é apenas definir o manipulador para oHUP
sinalSIG_IGN
(ignorar) antes de executar o programa. Não há nada para parar o programa de configurá-lo novamenteSIG_DFL
ou instalar seu próprio manipulador quando ele começar a ser executado.Uma coisa que você pode querer tentar é colocar seu comando entre parênteses, para obter um efeito de bifurcação dupla e seu
python
script não é mais um filho do processo do shell. Por exemplo:Outra coisa que pode valer a pena tentar (se você estiver usando
bash
e não outro shell) é usar odisown
builtin em vez denohup
. Se tudo estiver funcionando como documentado, isso não deve realmente fazer diferença, mas em um shell interativo isso impediria aHUP
propagação do sinal para o seupython
script. Você pode adicionar o rejeitado na próxima linha ou na mesma linha abaixo (observe que a adição de um;
após a&
é um errobash
):Se as opções acima ou alguma combinação delas não funcionarem, certamente o único lugar para resolver o problema está no
python
próprio script.fonte
huponexit
, a execução em um subshell deve ter o mesmo efeito,disown
pois o processo não será adicionado à lista de tarefas.disown
. Não espere que isso faça muita diferença. Eu acho que sua melhor aposta é alterar opython
script para que ele lhe diga por que está saindo.nohup
fazê-lo.Eu acho que é porque o trabalho está vinculado à sessão. Uma vez terminado, os trabalhos do usuário também serão encerrados.
fonte
Se
nohup
pode abrir seu arquivo de saída, você pode ter uma pistanohup.out
. É possível quepython
não esteja no caminho quando você executa o script viassh
.Eu tentaria criar um arquivo de log para o comando. Tente usar:
fonte
ssh
para executar o script manualmente, então estou assumindo que python3 está no caminho.