2011-10-25 21 views
5

Mam LaunchDaemon. Po uruchomieniu sprawdza, czy SIMBL jest zainstalowany. Jeśli SIMBL nie jest zainstalowany, używa NSTask do uruchomienia/usr/sbin/installer w SIMBL.pkg.Jak uruchomić LaunchAgent po raz pierwszy bez ponownego uruchamiania, gdy twój kod działa jako LaunchDaemon?

skrypt postflight SIMBL jest następnie próbuje uruchomić polecenie obciążenia launchctl aby natychmiast rozpocząć SIMBL za LaunchAgent:

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

nie to, bo NSTask środowisko mojego LaunchDaemon nie ma $ Set User.

Jeśli mam mój demon wykrywać bieżącą użytkownikowi ramach konfiguracji systemu i przekazać go do NSTask z setEnvironment, launchctl błędy na mnie:

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

uświadamiam sobie demona, z definicji, nie powinien działać w sesji użytkownika. Z tego samego powodu firma Apple wydaje się polecać LaunchAgents jako obiekty pomocnicze dla LaunchDaemons, aby wykonać tę sesję użytkownika. Czy istnieje sposób na natychmiastowe uruchomienie takiego agenta?

Mam wszystkie. Plists we właściwych miejscach (zaczynają działać po ponownym uruchomieniu, następnym razem, gdy launchctl wykona normalne ładowanie), więc moją pierwszą myślą było, aby po prostu powiedzieć launchctl, aby przeładować. Ale 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. 

Odpowiedz

6

Och jak launchd doprowadza mnie do szaleństwa ....

Aby przejść do sedna, po wielu badań i eksperymentów, to jak ja zrób to na 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>")) 
}' 

Nie znalazłem sposobu, aby osiągnąć to bezpośrednio na 10.4. Oszukuję na 10.4 i po prostu uruchomię to, co uruchomił LaunchAgent, mimo że ma GUI i nie powinieneś tego robić (możesz to zrobić w 10.4-10.6, nie możesz w 10.7). W wersji 10.4 LaunchAgent działa poprawnie po ponownym uruchomieniu komputera.

Powyższy kod wyszukuje loginwindow procesów i używa bsexec do uruchamiania poleceń w tych kontekstach. Należy pamiętać, że przy szybkim przełączaniu użytkowników może istnieć wiele kontekstów.

Przydatne linki:

IMO, launchd to jeden z najgorszych "wspaniałych pomysłów", które firma Apple kiedykolwiek wdrożyła. Pomysł jest bardzo przydatny, ale interfejs API jest okropny.

+1

W systemie OS X "El Capitan" 10.11 (15A204h) wygląda na to, że "launchctl bsexec" już nie działa.Czy istnieje powód, dla którego ten krok jest wymagany? – yairchu

+1

To część, która ponownie uruchamia agenta we właściwym kontekście. Bez tego nie uruchamiasz ponownie, gdy żądasz PO. Nie wiem, w jaki sposób (jeśli to możliwe) jest to możliwe 10.11. –

+0

wydaje się, że jest sposób, aby to zrobić 10.11: 'launchctl bootstrap gui/\' stat -f% u \ ''. z http://stackoverflow.com/questions/1106638/starting-stopping-a-launchd-agent-for-all-users-with-gui-sessions#comment51143118_31534614 – yairchu

Powiązane problemy