J'ai un script bash qui démarre un script python3 (appelons-le startup.sh
), avec la ligne de clé:
nohup python3 -u <script> &
Lorsque j'entre ssh
directement et appelle ce script, le script python continue de s'exécuter en arrière-plan après ma sortie. Cependant, lorsque je lance ceci:
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
Le processus se termine dès qu'il ssh
a fini de l'exécuter et ferme la session.
Quelle est la différence entre les deux?
EDIT: Le script python exécute un service Web via Bottle.
EDIT2: J'ai également essayé de créer un script d'initialisation qui appelle startup.sh
et s'exécute ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "sudo service start <servicename>"
, mais obtient le même comportement.
EDIT3: C'est peut-être autre chose dans le script. Voici l'essentiel du 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: Lorsque je lance la dernière ligne avec un sommeil à la fin:
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"
Il n'atteint jamais echo "Finished"
, et je vois le message du serveur de bouteille, que je n'ai jamais vu auparavant:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
Je vois "Terminé" si j'ouvre manuellement SSH et tue le processus moi-même.
EDIT5: En utilisant EDIT4, si je fais une demande à n'importe quel point de terminaison, je récupère une page, mais les erreurs de bouteille sortent:
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)
la source
strace
si vous utilisez Linux outruss
si vous exécutez Solaris et voyez comment / pourquoi il se termine. Comme par exemplessh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> strace -fo /tmp/debug ./startup.sh
.&
à la fin du script de démarrage? L'ajout du&
supprime la dépendance de votre session ssh d'être l'ID parent (lorsque les ID parents meurent, leurs enfants aussi). Je pense également que c'est une question en double basée sur ce post précédent. Le message que je vous ai soumis dans la phrase précédente est un double de ce message qui pourrait fournir de meilleurs détails.nohup ./startup.sh &
, mais il avait le même comportement.startup.sh
contient déjà un fork (nohup python3 -u <script> &
), donc je suis sûr que je n'ai pas besoin de fork encore.Réponses:
Je voudrais déconnecter la commande de ses flux d'entrée / sortie standard et d'erreur:
ssh
a besoin d'un indicateur qui n'a plus de sortie et qui ne nécessite plus d'entrée. Le fait d'avoir autre chose comme entrée et de rediriger les moyens de sortiessh
peut sortir en toute sécurité, car l'entrée / sortie ne vient pas ou ne va pas au terminal. Cela signifie que l'entrée doit provenir d'un autre endroit et que la sortie (STDOUT et STDERR) doit aller ailleurs.La
</dev/null
pièce spécifie/dev/null
comme entrée pour<script>
. Pourquoi cela est utile ici:Alternativement, la redirection à partir d'une autre source d'entrée devrait être relativement sûre tant que la
ssh
session en cours n'a pas besoin d'être maintenue ouverte.Avec la
>/dev/null
partie, le shell redirige la sortie standard vers / dev / null en la rejetant essentiellement.>/path/to/file
fonctionnera également.La dernière partie
2>&1
redirige STDERR vers STDOUT.la source
nohup python3 -u <script> >/dev/null 2>&1 &
etnohup python3 -u <script> > nohup.out 2>&1 &
travaillé. Je pensais que nohup redirige automatiquement toutes les sorties - quelle est la différence?nohup
avez-vous sur votre hôte distant? Un POSIXnohup
n'est pas requis pour redirigerstdin
, ce que j'ai manqué, mais il doit toujours redirigerstdout
etstderr
.nohup (GNU coreutils) 8.21
.nohup
imprime-t-il des messages commenohup: ignoring input and appending output to ‘nohup.out’
?Regardez
man ssh
:Lorsque vous exécutez,
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
vous exécutez le script shell startup.sh en tant que commande ssh.D'après la description:
Sur cette base, il devrait exécuter le script à distance.
La différence entre cela et l'exécution
nohup python3 -u <script> &
dans votre terminal local est que cela s'exécute en tant que processus d'arrière-plan local tandis que la commande ssh tente de l'exécuter en tant que processus d'arrière-plan distant.Si vous avez l'intention d'exécuter le script localement, n'exécutez pas startup.sh dans le cadre de la commande ssh. Vous pourriez essayer quelque chose comme
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> && "./startup.sh"
Si votre intention est d'exécuter le script à distance et que vous souhaitez que ce processus se poursuive après la fin de votre session ssh, vous devez d'abord démarrer une
screen
session sur l'hôte distant. Ensuite, vous devez exécuter le script python dans l'écran et il continuera à fonctionner après la fin de votre session ssh.Voir le manuel d'utilisation de l'écran
Bien que je pense que l'écran est votre meilleure option, si vous devez utiliser nohup, envisagez de définir
shopt -s huponexit
sur l'hôte distant avant d'exécuter la commande nohup. Alternativement, vous pouvez utiliserdisown -h [jobID]
pour marquer le processus afin que SIGHUP ne lui soit pas envoyé. 1Consultez également ce résumé du
huponexit
fonctionnement d'un shell lorsque vous le quittez, le tuez ou le lâchez. Je suppose que votre problème actuel est lié à la fin de la session shell. 2Enfin, voici quelques exemples d'utilisation de shopt huponexit. 3
la source
bash
page de manuel, celahuponexit
ne devrait affecter que les shells interactifs et non les scripts - 'Si l'option de shell huponexit a été définie avec shopt, bash envoie un SIGHUP à toutes les tâches lorsqu'un shell de connexion interactif se termine.'Peut-être vaut-il la peine d'essayer une
-n
option lors du démarrage d'unssh
? Cela empêchera la dépendance des processus distants à un localstdin
, qui se ferme bien sûr dès lassh session
fin. Et cela entraînera la résiliation à distance des prix chaque fois qu'il tentera d'accéder à sonstdin
.la source
Je soupçonne que vous avez une condition de course. Cela ressemblerait à quelque chose comme ceci:
Si ssh n'avait pas raccourci les choses, les événements suivants se seraient produits (je ne suis pas sûr de l'ordre de ces deux):
Ainsi, les deux dernières étapes critiques ne se produisent pas, car startup.sh et ssh se terminent avant que nohup n'ait le temps de faire son travail.
J'espère que votre problème disparaîtra si vous mettez quelques secondes de sommeil à la fin de startup.sh. Je ne sais pas exactement combien de temps vous avez besoin. S'il est important de le garder au minimum, alors vous pouvez peut-être regarder quelque chose dans proc pour voir quand il est sûr.
la source
/proc/$!/comm
pasnohup
ou plus facilement la sortie deps -o comm= $!
.Cela ressemble plus à un problème avec ce que le
python
script oupython
lui-même fait. Tout cenohup
qui fait vraiment (barre simplifiant les redirections) est simplement de définir le gestionnaire duHUP
signal surSIG_IGN
(ignorer) avant d'exécuter le programme. Il n'y a rien pour empêcher le programme de le réinitialiserSIG_DFL
ou d'installer son propre gestionnaire une fois qu'il a démarré.Une chose que vous voudrez peut-être essayer est de placer votre commande entre parenthèses afin que vous obteniez un effet de double fork et que votre
python
script ne soit plus un enfant du processus shell. Par exemple:Une autre chose qui peut également valoir la peine d'être essayée (si vous utilisez
bash
et non un autre shell) est d'utiliser la fonctiondisown
intégrée à la place denohup
. Si tout fonctionne comme indiqué, cela ne devrait pas faire de différence, mais dans un shell interactif, cela empêcherait leHUP
signal de se propager vers votrepython
script. Vous pouvez ajouter le désaveu sur la ligne suivante ou le même que ci-dessous (notez que l'ajout d'un;
après un&
est une erreurbash
):Si ce qui précède ou une combinaison de ceux-ci ne fonctionne pas, le seul endroit pour résoudre le problème est sûrement dans le
python
script lui-même.la source
huponexit
choses, l'exécution dans un sous-shell devrait avoir le même effetdisown
que le processus ne sera pas ajouté à la liste des travaux.disown
. Ne vous attendez pas à ce que cela fasse beaucoup de différence. Je pense que votre meilleur pari est de modifier lepython
script afin qu'il vous explique pourquoi il se termine.nohup
faire.Je pense que c'est parce que le travail est lié à la session. Une fois cela terminé, tous les travaux utilisateur sont également terminés.
la source
Si
nohup
peut ouvrir son fichier de sortie, vous pouvez avoir un indicenohup.out
. Il est possiblepython
que vous ne soyez pas sur le chemin lorsque vous exécutez le script viassh
.J'essaierais de créer un fichier journal pour la commande. Essayez d'utiliser:
la source
ssh
pour exécuter le script manuellement, donc je suppose que python3 est dans le chemin.