Loading LaunchAgents for users in postinstall
When an installer package contains a LaunchAgent we typically try to load it into any current user sessions, to avoid requiring a logout or restart. Through trial and error we've arrived at using launchctl bsexec with chroot in a loop like this: if [[ "$3" == "/" ]]; then # Load agent for all logged in users. for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do pid=$(echo $pid_uid | cut -d, -f1) uid=$(echo $pid_uid | cut -d, -f2) if [[ "$uid" -ne 0 ]]; then launchctl bsexec "$pid" chroot -u "$uid" / launchctl unload "$AGENT" launchctl bsexec "$pid" chroot -u "$uid" / launchctl load "$AGENT" fi done fi It's not perfect but it got the job done, but it looks like it breaks in the 10.11 betas if SIP is enabled (launchctl exits with code 5). Is there a better/proper/supported way of loading LaunchAgents for users in a background script running as root? -- Per Olofsson, IT-service, University of Gothenburg
You should take a look at the asuser and bootstrap commands of launchctl. The last one will only work on 10.11.
On 17 Jul 2015, at 17:11, Per Olofsson <per.olofsson@gu.se> wrote:
When an installer package contains a LaunchAgent we typically try to load it into any current user sessions, to avoid requiring a logout or restart. Through trial and error we've arrived at using launchctl bsexec with chroot in a loop like this:
if [[ "$3" == "/" ]]; then # Load agent for all logged in users. for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do pid=$(echo $pid_uid | cut -d, -f1) uid=$(echo $pid_uid | cut -d, -f2) if [[ "$uid" -ne 0 ]]; then launchctl bsexec "$pid" chroot -u "$uid" / launchctl unload "$AGENT" launchctl bsexec "$pid" chroot -u "$uid" / launchctl load "$AGENT" fi done fi
It's not perfect but it got the job done, but it looks like it breaks in the 10.11 betas if SIP is enabled (launchctl exits with code 5). Is there a better/proper/supported way of loading LaunchAgents for users in a background script running as root?
-- Per Olofsson, IT-service, University of Gothenburg
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
Per, You should be able to use `launchctl asuser` for this purpose, eg. $ launchctl asuser launchctl unload /Path/to/plist $ launchctl asuser launchctl load /Path/to/plist On El Capitan, you can use `launchctl bootstrap` and `launchctl bootout`, eg. $ launchctl bootout user/$uid /path/to/plist $ launchctl bootstrap user/$uid /path/to/plist Note that both of these will load your job into the user's background session and *not* the user's GUI session. This means that your job must have a LimitLoadToSessionType value of "Background". If you want to load your agent into the user's GUI session, your approach below will work just fine, though I'm not sure why you're chroot(2)ing. On El Capitan, you can modify the above commands to be $ launchctl bootout gui/$uid /path/to/plist $ launchctl bootstrap gui/$uid /path/to/plist if you want to load the job into the user's GUI session, and you won't have to go through any weird tricks like below. Before you ask, yes, we know it's a mess. Unfortunately, we're very constrained by 10+ years of legacy behavior. -damien On 17 Jul, 2015, at 08:11, Per Olofsson <per.olofsson@gu.se> wrote:
When an installer package contains a LaunchAgent we typically try to load it into any current user sessions, to avoid requiring a logout or restart. Through trial and error we've arrived at using launchctl bsexec with chroot in a loop like this:
if [[ "$3" == "/" ]]; then # Load agent for all logged in users. for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do pid=$(echo $pid_uid | cut -d, -f1) uid=$(echo $pid_uid | cut -d, -f2) if [[ "$uid" -ne 0 ]]; then launchctl bsexec "$pid" chroot -u "$uid" / launchctl unload "$AGENT" launchctl bsexec "$pid" chroot -u "$uid" / launchctl load "$AGENT" fi done fi
It's not perfect but it got the job done, but it looks like it breaks in the 10.11 betas if SIP is enabled (launchctl exits with code 5). Is there a better/proper/supported way of loading LaunchAgents for users in a background script running as root?
-- Per Olofsson, IT-service, University of Gothenburg
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
It is really a good news that $ launchctl bootstrap gui/$uid /path/to/plist will work also, thanks for this info! I assume they need to load the agent into a GUI session "though I'm not sure why you're chroot(2)ing." In some cases we also needed to use chroot to get loaded in the correct user context with the appropriate uid/gui Although $ launchctl bsexec "$pid" launchctl load -S Aqua "$AGENT” and $ launchctl bsexec "$pid” open /Applications/Your.app will load into the correct context with the perfect rights, but $ launchctl bsexec "$pid” /PathToMyExecutable will start your executable as user root, so generally we always use the chroot approach. ——————————————————— Hofi – Istvan Hoffmann http://hofione.wix.com/memyselfandi On 7/17/15, 22:03 , "Damien Sorresso" <launchd-dev-bounces@lists.macosforge.org on behalf of dsorresso@apple.com> wrote:
Per,
You should be able to use `launchctl asuser` for this purpose, eg.
$ launchctl asuser launchctl unload /Path/to/plist $ launchctl asuser launchctl load /Path/to/plist
On El Capitan, you can use `launchctl bootstrap` and `launchctl bootout`, eg.
$ launchctl bootout user/$uid /path/to/plist $ launchctl bootstrap user/$uid /path/to/plist
Note that both of these will load your job into the user's background session and *not* the user's GUI session. This means that your job must have a LimitLoadToSessionType value of "Background".
If you want to load your agent into the user's GUI session, your approach below will work just fine, though I'm not sure why you're chroot(2)ing.
On El Capitan, you can modify the above commands to be
$ launchctl bootout gui/$uid /path/to/plist $ launchctl bootstrap gui/$uid /path/to/plist
if you want to load the job into the user's GUI session, and you won't have to go through any weird tricks like below.
Before you ask, yes, we know it's a mess. Unfortunately, we're very constrained by 10+ years of legacy behavior. -damien
On 17 Jul, 2015, at 08:11, Per Olofsson <per.olofsson@gu.se> wrote:
When an installer package contains a LaunchAgent we typically try to load it into any current user sessions, to avoid requiring a logout or restart. Through trial and error we've arrived at using launchctl bsexec with chroot in a loop like this:
if [[ "$3" == "/" ]]; then # Load agent for all logged in users. for pid_uid in $(ps -axo pid,uid,args | grep -i "[l]oginwindow.app" | awk '{print $1 "," $2}'); do pid=$(echo $pid_uid | cut -d, -f1) uid=$(echo $pid_uid | cut -d, -f2) if [[ "$uid" -ne 0 ]]; then launchctl bsexec "$pid" chroot -u "$uid" / launchctl unload "$AGENT" launchctl bsexec "$pid" chroot -u "$uid" / launchctl load "$AGENT" fi done fi
It's not perfect but it got the job done, but it looks like it breaks in the 10.11 betas if SIP is enabled (launchctl exits with code 5). Is there a better/proper/supported way of loading LaunchAgents for users in a background script running as root?
-- Per Olofsson, IT-service, University of Gothenburg
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org https://lists.macosforge.org/mailman/listinfo/launchd-dev
17 juli 2015 kl. 22:03 skrev Damien Sorresso <dsorresso@apple.com>:
Per,
You should be able to use `launchctl asuser` for this purpose, eg.
$ launchctl asuser launchctl unload /Path/to/plist $ launchctl asuser launchctl load /Path/to/plist
Thanks, I got some replies off list as well, and asuser is pretty much a drop-in replacement. It wasn't documented until 10.10, but opensource.apple.com (yay!) confirms that it appeared in 10.7, so I guess it should be safe to use even if you need to support older releases?
On El Capitan, you can use `launchctl bootstrap` and `launchctl bootout`, eg.
$ launchctl bootout user/$uid /path/to/plist $ launchctl bootstrap user/$uid /path/to/plist
Note that both of these will load your job into the user's background session and *not* the user's GUI session. This means that your job must have a LimitLoadToSessionType value of "Background".
If you want to load your agent into the user's GUI session, your approach below will work just fine, though I'm not sure why you're chroot(2)ing.
We're basically cargo culting Quinn's reply here: https://lists.macosforge.org/pipermail/launchd-dev/2011-January/000890.html chroot -u just executes a command though, and you don't have to deal with the shell as you have to if you use su, and as a bonus there's no quoting involved.
On El Capitan, you can modify the above commands to be
$ launchctl bootout gui/$uid /path/to/plist $ launchctl bootstrap gui/$uid /path/to/plist
if you want to load the job into the user's GUI session, and you won't have to go through any weird tricks like below.
It'll be a few years before we can target 10.11+, but that's excellent!
Before you ask, yes, we know it's a mess. Unfortunately, we're very constrained by 10+ years of legacy behavior.
Don't I know it, but heck, it's cleaner and more explicit now than it's ever been. -- Per Olofsson, IT-service, University of Gothenburg
On 18 Jul, 2015, at 01:41, Per Olofsson <per.olofsson@gu.se> wrote:
17 juli 2015 kl. 22:03 skrev Damien Sorresso <dsorresso@apple.com>:
Per,
You should be able to use `launchctl asuser` for this purpose, eg.
$ launchctl asuser launchctl unload /Path/to/plist $ launchctl asuser launchctl load /Path/to/plist
Thanks, I got some replies off list as well, and asuser is pretty much a drop-in replacement. It wasn't documented until 10.10, but opensource.apple.com (yay!) confirms that it appeared in 10.7, so I guess it should be safe to use even if you need to support older releases?
Yes, it is there. In Yosemite, we actually improved the fidelity of "asuser" substantially. The process adopts not only the proper bootstrap context but also the right exception context and audit session.
On El Capitan, you can use `launchctl bootstrap` and `launchctl bootout`, eg.
$ launchctl bootout user/$uid /path/to/plist $ launchctl bootstrap user/$uid /path/to/plist
Note that both of these will load your job into the user's background session and *not* the user's GUI session. This means that your job must have a LimitLoadToSessionType value of "Background".
If you want to load your agent into the user's GUI session, your approach below will work just fine, though I'm not sure why you're chroot(2)ing.
We're basically cargo culting Quinn's reply here:
https://lists.macosforge.org/pipermail/launchd-dev/2011-January/000890.html
chroot -u just executes a command though, and you don't have to deal with the shell as you have to if you use su, and as a bonus there's no quoting involved.
Oh I see.
On El Capitan, you can modify the above commands to be
$ launchctl bootout gui/$uid /path/to/plist $ launchctl bootstrap gui/$uid /path/to/plist
if you want to load the job into the user's GUI session, and you won't have to go through any weird tricks like below.
It'll be a few years before we can target 10.11+, but that's excellent!
You could always conditionalize based on the availability of the bootout subcommand if you really wanted to use it I suppose.
Before you ask, yes, we know it's a mess. Unfortunately, we're very constrained by 10+ years of legacy behavior.
Don't I know it, but heck, it's cleaner and more explicit now than it's ever been.
Yeah, that was the intent. ;) -damien
participants (4)
-
Damien Sorresso
-
Hofi
-
Per Olofsson
-
Thomas Clement