2015-04-21 1 views
0

Depuis des années, nous avons un script de surveillance/contrôle de processus dans le cadre de notre application. Le comportement par défaut du script est de se démoniser. Souvent, le script est lancé, par nécessité, par des utilisateurs non privilégiés. Pour des raisons que je ne développerai pas, nous devons garder à la fois le script et ce comportement.Comment démoniser un script non-privilégié dans OSX Yosemite 10.10.3+

Sur OSX systèmes, nous avons toujours eu le script lui-même redémarrer en arrière-plan via le /usr/libexec/StartupItemContext script de lancement fourni par Apple. Ceci place notre processus dans le contexte bootstrap Mach StartupItem plutôt que dans le contexte bootstrap de connexion. Cela est nécessaire car sans ce changement de contexte, si et quand l'utilisateur se déconnecte, ce qui est souvent nécessaire, le script perd l'accès aux services d'annuaire, getpwuid(), services DNS, etc. Les lignes internes originales qui ont démonisé le script comme celui-ci (en Perl):

my $cmd = "/usr/libexec/StartupItemContext myscript @Commandline > logs/startup 2>&1" ;   
system("$cmd &") ; 
exit 0 ; 

Lorsque OSX Yosemite est sorti, que scénario StartupItemContext a disparu, donc nous sommes passés à diriger l'invocation de launchctl:

my $cmd = "/usr/launchctl bsexec/myscript @Commandline > logs/startup 2>&1" ;   
system("$cmd &") ; 
exit 0 ; 

Avec la récente OSX 10.10.3 cependant, mise à niveau, le bsexec sous-commande de launchctl exige tout à coup les privilèges root:

% launchctl bsexec 
This subcommand requires root privileges: bsexec 
% 

Cela crée pour nous le problème Showstopper que les utilisateurs non privilégiés ne peuvent plus obtenir notre script de surveillance/contrôle pour se démoniser.

Il semble que Glassfish has encountered this problem et adressée avec a patch qui remplace

/bin/launchctl bsexec/

avec

nohup 

Cela peut fonctionner pour la mise en œuvre Glassfish, mais je ne pense pas que pour nous. Nonobstant le fait que je ne le comprenne pas - pourquoi un simple blocage de SIGHUP empêcherait un processus dans un contexte de bootstrap désaffecté de perdre des services - il ne semble pas non plus fonctionner dans nos tests pour tous les services système dont nous avons besoin .

Quelle est la nouvelle façon canonique daemonize un processus sur OSX à partir d'un non-privilégié, Mach « login » contexte d'amorçage, sans perdre l'accès aux services système critiques comme DNS, etc. lorsque l'utilisateur se déconnecte?

Répondre

3

"d'un non-privilégié, Mach" login "contexte bootstrap" est malheureusement très peu susceptible d'avoir une "manière canonique". La seule façon canonique est de lancer des services à la demande via launchd. Même "bsexec" est à peine supporté et difficilement documenté. D'après mon expérience, il n'est pas possible de suivre les changements d'OS X et de ne jamais revoir la conception de vos systèmes de lancement. Je repense le système démon à propos de toutes les autres versions car Apple le casse, et ils vont continuer à le casser. La seule réponse est de continuer à essayer de simplifier vos exigences. Mais à peu près tout processus qui veut fonctionner tout le temps, plutôt que sur demande, est en violation directe de l'intention déclarée d'Apple, donc il va avoir tendance à casser.

La solution proposée par Apple est de créer un LaunchDaemon et de lui affecter un UserName dans votre lancement plist. Vous devez commencer par privilégier, puis passer à l'utilisateur (et il doit être un utilisateur fixe, pas "l'utilisateur connecté" puisqu'il s'agit d'un LaunchAgent). Vous ne pouvez pas améliorer votre accès de cette façon. Vous ne devez pas vous démoniser (encore une fois, la réponse canonique est: ne faites pas cela.)

Je pense que la solution Glassfish nohup est juste une esquive qui ne les met pas vraiment dedans. le contexte Mach. Ils essayent juste d'éviter d'être tué quand le shell parent se termine. Cela ne vous aidera probablement pas. D'après mon expérience, les solutions les plus robustes sont multi-parties. Vous finissez avec une pièce exécutée comme un LaunchDaemon système (avec KeepAlive), et une autre pièce qui est un utilisateur LaunchAgent, et vous les laissez communiquer sur IPC afin que vous puissiez accéder au contexte dont vous avez besoin pour chaque activité que vous devez faire . Oui, c'est généralement beaucoup plus compliqué à mettre en œuvre. Les solutions plus simples ont tendance à ne pas fonctionner.

Et bien sûr, vous devez constamment vous demander "est-il de toute façon que je pourrais réaliser cela en faisant les choses comme Apple veut que je le fasse." Cela signifie que XPC est fortement préféré, suivi par LaunchDaemons et LaunchAgents à la demande. Si vous construisez votre système pour utiliser les composants XPC, vous survivrez probablement à plus de mises à niveau OS X. Tout travail autour de vous comprendre que n'utilise pas ces pièces devra probablement être corrigé à nouveau en 10.11.

+0

Merci beaucoup à @Rob pour l'esquisse informée de la façon de le reconfigurer. Afin de créer une marge de manœuvre pour poursuivre dans cette voie, connaissez-vous une esquive à court terme pour notre prochain délai de publication (d'une semaine), autre que le _sudo_ qui brise les exigences? Par exemple, [old technical notes] (https://developer.apple.com/library/mac/technotes/tn2083/_index.html) suggère qu'il existe un contexte bootstrap «utilisateur» en plus du contexte «login». Existe-t-il un moyen de lancer un processus de manière à ce qu'il atterrisse dans un contexte "utilisateur" au lieu de "connexion", et survit donc, espérons-le, à la déconnexion de la session? Nous avons été aveuglés par le changement d'Apple ici, merci – lcikgl

+1

Ce TN est la carte que vous voulez. J'y reviens tout le temps. Je crois que ce que vous regardez est un LaunchAgent non-GUI. Je ne pense pas que ceux-ci survivront à la déconnexion. Tout ce qui "par utilisateur" va vouloir s'arrêter quand l'utilisateur part. Vous pouvez l'essayer en plaçant une plist dans/Library/LaunchAgents. Vous pourriez essayer de forker et de détacher de votre parent (setsid ou peut-être une double-fourchette peut être nécessaire). Il est possible que cela puisse vous protéger de la déconnexion. –