2011-10-25 10 views
5

Tengo un LaunchDaemon. Cuando se ejecuta, comprueba si SIMBL está instalado. Si SIMBL no está instalado, usa NSTask para ejecutar/usr/sbin/installer en SIMBL.pkg.¿Cómo se puede iniciar un LaunchAgent por primera vez sin reiniciar cuando su código se ejecuta como LaunchDaemon?

guión después del vuelo de SIMBL luego trata de ejecutar un comando de carga launchctl para comenzar LaunchAgent de SIMBL inmediato:

sudo -u "$USER" -- /bin/launchctl load -F -S Aqua -D user "${LAUNCHD_PLIST}" 

Esta falla, porque el medio ambiente NSTask de mi LaunchDaemon no tiene establecido por el usuario $.

Si tengo a mi demonio de detectar que el usuario actual con el marco de configuración del sistema y pasarlo a NSTask con setEnvironment, insectos launchctl hacia fuera en mí:

Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1 

realizo un demonio, por definición, no deben operar en una sesión de usuario. De la misma manera, Apple parece recomendar LaunchAgents como objetos auxiliares para LaunchDaemons, para hacer que esa sesión de usuario funcione. ¿Hay alguna manera de poner en marcha a ese agente de inmediato?

Tengo todas las listas .plists en los lugares correctos (comienzan a ejecutarse después de un reinicio, la próxima vez que launchctl hace su carga normal) así que mi primer pensamiento fue simplemente decirle a launchctl que vuelva a cargar. Pero all the code to do that is commented out in launchctl.c:

// { "reload",   reload_cmd,    "Reload configuration files and/or directories" }, 

...

* In later versions of launchd, I hope to load everything in the first pass, 
* then do the Bonjour magic on the jobs that need it, and reload them, but for now, 
* I haven't thought through the various complexities of reloading jobs, and therefore 
* launchd doesn't have reload support right now. 

Respuesta

6

Oh cómo launchd me vuelve loco ....

Para ir al grano, después de mucho estudio y experimentación, así es como yo hacerlo en 10.5+:

# If possible, tell launchd to start the LaunchAgent. This will fail on 10.4. 
# $F[0] is the pid 
# $F[1] is the username 
# $F[2] is the first word of the command 
ps -ww -A -opid,user,command | \ 
    perl -nae 'if($F[2] =~ /\bloginwindow\b/) { system(
    qq(launchctl bsexec $F[0] su $F[1] -c "launchctl load -w <your_plist>")) 
}' 

No he encontrado ninguna manera de lograr esto directamente en 10.4. Hago trampa en 10.4 y solo ejecuto lo que el LaunchAgent habría ejecutado, a pesar de que tiene una GUI y se supone que usted no puede hacer eso (puede hacerlo de todos modos en 10.4-10.6; no puede en 10.7). En 10.4, LaunchAgent funciona correctamente después del próximo reinicio.

El código anterior busca procesos loginwindow y usa bsexec para ejecutar comandos en esos contextos. Tenga en cuenta que con el Cambio rápido de usuario, puede haber contextos múltiples.

Algunos enlaces útiles:

IMO, launchd es una de las peores "grandes ideas" que Apple ha implementado. La idea es muy útil, pero la API es horrible.

+1

Con OS X "El Capitan" 10.11 (15A204h) parece que "launchctl bsexec" ya no funciona.¿Hay alguna razón por la cual se requiera este paso? – yairchu

+1

Esa es la parte que reinicia el agente en el contexto correcto. Sin eso, no estás reiniciando como solicitó el OP. No sé de qué manera (si es que hay alguno) esto es posible en 10.11. –

+0

parece que hay una manera de hacerlo en 10.11: 'launchctl bootstrap gui/\' stat -f% u \ ''. de http://stackoverflow.com/questions/1106638/starting-stopping-a-launchd-agent-for-all-users-with-gui-sessions#comment51143118_31534614 – yairchu

Cuestiones relacionadas