J'ai reçu plusieurs rapports à ce sujet sur IRC, ainsi qu'un commentaire sur le # 350, et maintenant un fil de discussion sur la liste de diffusion .
Aucune cause claire pour le moment, et bien que cela ait été signalé plusieurs fois, je ne pense pas que ce soit un problème constant ou que nous en entendrions beaucoup plus. Dans certains tests très limités de mon côté jusqu'à présent, je peux recréer le problème peut-être 30 à 50% du temps - mais il est reproductible.
Le symptôme est simplement que les scripts de style init chargés de démarrer les démons puis de les renvoyer immédiatement, renverront OK, le code de retour de 0 et le message d'état "success" seront imprimés sur stdout - mais ne feront pas tourner le démon en question.
Mon test personnel a été effectué via le dernier master ciblant une VM Ubuntu 10.04 (Lucid) et le script d'initialisation du package Apache2.
Présentée à l' origine par Jeff Forcier ( bitprophet ) sur 2011-07-23 à 19:25 EDT
Jeff Forcier ( bitprophet ) a publié:
J'ai instrumenté le script init que je teste et tout semble fonctionner de la même manière (c'est-à-dire un vrai succès ou de faux scénarios de réussite), ce qui implique que le problème se situe dans l'appel apachectl
le script lui-même fait.
Commencer à réfléchir à ce que pourrait être la cause de notre côté:
ssh -t <hostname> <command>
et de voir si cela reproduit également le problème.sur 2011-07-23 à 19:45 EDT
Jeff Forcier ( bitprophet ) a publié:
apache2ctl
lui-même est aussi simplement un script Bash wrapper appelant /usr/sbin/apache2
, qui est un lien symbolique vers un exécutable binaire réel dans l'emplacement d'installation d'Apache mpm-worker. Plus précisément, dans l'utilisation normale de start
, il appelle /usr/sbin/apache2 -k start
. Comme précédemment, apache2ctl
ne semble pas se comporter différemment dans les deux scénarios différents, re: return value ou quelles sections sont exécutées.
/usr/sbin/apache2
sont relativement limités (même sur le site d'Apache), indiquant uniquement que vous devriez utiliser apachectl pour configurer des variables d'environnement (ce qui est précis - l'exécution de apache2
par elle-même est assez évidemment avec des erreurs concernant ces variables n'étant pas définies.)
L'examen de la sortie de env
juste avant l'invocation de apache2ctl
de apache2
ne donne que quelques éléments: utilisateur, groupe, emplacement du fichier pid et langue. Celles-ci ne changent pas entre les situations de réussite et d'échec. J'espérais un peu qu'il y aurait quelque chose dans les divers paramètres de sourcings et d'env var dans les wrappers qui changerait parfois, mais non.
Jusqu'à présent, cela ne va nulle part utile. Il est temps de tester les idées ci-dessus (pty, ssh) pour voir ce qui change là-bas.
sur 2011-07-23 à 20:46 EDT
Jeff Forcier ( bitprophet ) a publié:
Avec pty=False
, cela semble fonctionner beaucoup mieux (comme le laisse entendre le commentaire de Max au # 350). Avec le paramètre True par défaut, je voyais des échecs environ 5/10 fois, parfois quelques plus ou moins. Avec False, je viens de l'exécuter environ 15 fois de suite sans échec. Pas un statisticien mais cela me semble plutôt bien.
L'exécution manuelle de ssh
donne des résultats similaires: ssh -t <host> sudo /etc/init.d/apache2 start
échouera silencieusement à démarrer Apache environ 50% du temps. La même chose avec -T
(force no pty) et ça démarre 100% du temps.
Ce n'est donc pas la faute de Fabric; c'est quelque chose de plus profond où ces scripts d'initialisation se comportent mal quand un pseudo-tty de style SSH est en jeu.
Je vais creuser un peu plus pour la curiosité, mais il semble que la "solution" voici une nouvelle FAQ indiquant d'utiliser pty=False
lorsque ce problème est rencontré.
le 23/07/2011 à 20h59 HAE
Jeff Forcier ( bitprophet ) a publié:
Oui, ne trouvant rien qui explique ce comportement, malheureusement. Compte tenu des résultats ci-dessus, je pense qu'une FAQ est certainement la voie à suivre.
le 23/07/2011 à 22h35 HAE
Hugo Garza (hiro2k) a posté:
Ughh je viens de rencontrer ça hier, j'aurais aimé voir ce bug, heureusement j'ai essayé de régler pty = False et cela a fonctionné aussi. Merci pour l'explication, au moins ce n'est pas une faute de tissus. Maintenant, vous me demandez vraiment pourquoi cela échoue.
le 02/08/2011 à 13h27 HAE
Êtes-vous sûr que ce n'est pas seulement un problème de script bash? Je veux dire avec mon fil de liste de diffusion. C'étaient juste des scripts bash qui ont lancé java et weblogic.
FWIW, j'obtiens ce comportement horrible sur à peu près toutes les machines Ubuntu que je fais tourner sur EC2.
Il est également reproductible avec les tâches lancées via un écran détaché screen -d -m someBackgroundTask
.
Je dois mentionner que généralement pty=False
résout le problème, mais j'ai vu des cas où ce n'était pas le cas.
@yuvadm - dans les cas où pty = False ne résout pas le problème, le problème peut-il encore être recréé en utilisant une commande ssh régulière (comme mentionné ci-dessus)? Pour autant que j'ai vu, c'est un problème SSH et non un problème Fabric, mais il serait bon de savoir s'il y a des situations où cela ne correspond pas.
C'est un angle intéressant à vérifier, je vous reviendrai sur celui-là ...
J'ai reproduit ce problème. Le client est Ubuntu 10.04.3 LTS, le serveur est "Ubuntu 8.04.4 LTS (serveur)".
Le client SSH est "OpenSSH_5.3p1 Debian-3ubuntu7, OpenSSL 0.9.8k 25 mars 2009", le serveur ssh est "OpenSSH_4.7p1 Debian-8ubuntu1, OpenSSL 0.9.8g 19 octobre 2007". Le tissu est "1.3.3 final".
Le problème est là à 100% avec pty = True, et il disparaît avec pty = False.
En vous connectant à d'autres serveurs, le problème n'est pas toujours présent lorsque pty = True.
Dans mon cas, pour les tests, j'exécute une commande très simple: "nohup sleep 100> / tmp / xxx 2> & 1
J'ai été mordu par ça, seulement sur EC2 comme il semble (je ne l'ai pas vu sur mon Linode, mais je ne suis pas sûr à 100%). La définition de pty = False semble résoudre ce problème.
Juste face à ce problème.
J'ai eu une situation où je ne peux pas utiliser tty = False parce que j'exécute la commande avec sudo.
L'ajout de >& /dev/null < /dev/null &
s'exécute bien mais le processus n'a pas été lancé.
J'ai résolu le problème de l'ajout d'un sommeil après la ligne d'exécution de la commande: nohup java -jar text.jar & sleep 5; exit 0
Merci spodgruskiy,
Vos conseils fonctionnent pour moi.
J'avais essayé d'écrire fab tp démarrer un cluster strom avec les commandes suivantes.
Mais aucun d'entre eux ne fonctionne, les nimbus n'ont pas du tout commencé. Je ne comprends pas ce qui s'est passé.
Bref, merci.
+1 pour l'astuce du sommeil
nécessaire pour travailler sur des systèmes avec des exigences
sudo ('start service; sleep .5') et tout va bien!
Lorsque vous utilisez 'sudo ()' et que RequireTty est activé sur le système distant pour l'accès sudo, vous pouvez utiliser 'set -m; un service
Voir http://stackoverflow.com/a/14866774 pour une explication plus détaillée sur bash interactif par rapport à non interactif et comment cela affecte le contrôle des tâches.
Je suis curieux, quel est le problème ssh ici?
pty = faux fonctionne pour moi
Ce n'est pas vraiment un problème SSH, c'est plutôt le comportement subtil autour des modes non interactifs / interactifs BASH et de la propagation du signal vers les groupes de processus.
Ce qui suit est basé sur http://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774 et http: //www.itp.uzh.ch/~dpotter/howto/daemonize , avec certaines hypothèses non entièrement validées, mais les tests sur la façon dont cela fonctionne semblent confirmer.
Le shell bash lancé se connecte au stdout / stderr / stdin du processus démarré et continue à s'exécuter jusqu'à ce qu'il n'y ait rien attaché aux sockets et que ses enfants soient sortis. Un bon processus de démon s'assurera qu'il n'attend pas que ses enfants quittent, fourchent un processus enfant puis sortent. Dans ce mode, aucun SIGHUP ne sera envoyé au processus fils par SSH. Je pense que cela fonctionnera correctement pour la plupart des scripts exécutant un processus qui gère la désamonisation et n'a pas besoin d'être mis en arrière-plan. Là où les scripts d'initialisation utilisent '&' pour l'arrière-plan d'un processus, il est probable que le problème principal sera de savoir si le processus en arrière-plan tente jamais de lire à partir de stdin car cela déclenchera un SIGHUP si la session est terminée.
Si le script d'initialisation arrière-plan du processus a commencé, le shell BASH parent retournera un code de sortie à la connexion SSH, qui à son tour cherchera à quitter immédiatement car il n'attend pas qu'un processus enfant se termine et n'est pas bloqué sur stdout / stderr / stdin. Cela entraînera l'envoi d'un SIGHUP au groupe de processus du shell bash parent, qui, puisque le contrôle des travaux est désactivé en mode non interactif dans bash, inclura les processus enfants qui viennent d'être lancés. Lorsqu'un processus démon démarre explicitement une nouvelle session de processus lors du forking ou dans le processus forké, il ou ses enfants ne recevront pas le SIGHUP du processus parent BASH sortant. Notez que ceci est différent des travaux suspendus qui verront un SIGTERM.
Je soupçonne que les problèmes autour de cela ne fonctionnent que parfois avec une légère condition de course. Si vous regardez l'approche standard de la désamonisation - http://www.itp.uzh.ch/~dpotter/howto/daemonize , vous verrez que dans le code la nouvelle session est créée par le processus forké qui peut ne pas être s'exécuter avant la sortie du parent, ce qui entraîne le comportement aléatoire de réussite / échec mentionné ci-dessus. Une instruction sleep laissera suffisamment de temps au processus forké pour créer une nouvelle session, c'est pourquoi cela fonctionne dans certains cas.
SSH ne se connectera pas au stdout / stderr / stdin du shell bash ou à tout processus enfant lancé, ce qui signifiera qu'il se fermera dès que le shell bash parent a commencé à avoir terminé d'exécuter les commandes demandées. Dans ce cas, avec le contrôle des tâches explicitement activé, tous les processus lancés par le shell bash avec `` & '' en arrière-plan seront placés dans une session distincte immédiatement et ne recevront pas le signal SIGHUP lorsque le processus parent de la session BASH se terminera ( Connexion SSH dans ce cas).
Je pense que les solutions doivent simplement être explicitement mentionnées dans la documentation des opérations run / sudo en tant que cas particulier lorsque vous travaillez avec des processus / services en arrière-plan. En gros, utilisez «pty = false», ou lorsque ce n'est pas possible, activez explicitement le contrôle des travaux comme première commande, et le comportement sera correct.
mise à jour du lien: http://www.ics.uzh.ch/~dpotter/howto/daemonize
Comme je l'ai mentionné ici fabrickit (un emballage de bibliothèques de tissus) https://github.com/HyukjinKwon/fabrickit/commit/cceb8bfb8f960a3ac41b24c64b8358bd6e7a0366
Vous pouvez tout à fait facilement démarrer un programme en tant que démon sans configuration ni paramètres spécifiques.
C'est de toute façon une sorte d'exécution de Shell et il devrait donc y avoir un moyen de faire ce que Shell peut faire.
Essaye ça:
run("sh -c '((nohup %s > /dev/null 2> /dev/null) & )'" % cmd, pty=False)
J'ai essayé cela et cela fonctionne parfaitement bien même s'il n'implémente pas de programmation supplémentaire pour s'exécuter en tant que démon (même juste un programme écrivant «Hello» dans une boucle while fonctionne très bien).
Commentaire le plus utile
Juste face à ce problème.
J'ai eu une situation où je ne peux pas utiliser tty = False parce que j'exécute la commande avec sudo.
L'ajout de
>& /dev/null < /dev/null &
s'exécute bien mais le processus n'a pas été lancé.J'ai résolu le problème de l'ajout d'un sommeil après la ligne d'exécution de la commande:
nohup java -jar text.jar & sleep 5; exit 0