Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

From a script run as root I copy a LaunchAgent .plist to /Users/xyz/Library/LaunchAgents.

If I load that via launchctl logged in as user xyz it works without problems. If I try to load it from the script with the following command:

sudo -u xyz launchctl load /Users/xyz/Library/LaunchAgents/x.y.z.plist

it doesn't work. The error message is

Could not open job overrides database at /private/var/db/launchd.db/com.apple.launchd.peruser.0/overrides.plist: 13: Permission denied  
launch_msg(): Socket is not connected

Is there any other way to accomplish my task?

share|improve this question
    
Could you move it to /Library/LaunchAgents/ and add a UserName key? –  Lauri Ranta Aug 24 '12 at 21:10
add comment

2 Answers

It looks to me like the permissions error is just a symptom of a much deeper problem: you're trying to load the item into the wrong mach bootstrap context. Specifically, you're running the launchctl command as xyz, but it's trying to load the item into root's context, which xyz doesn't have permissions to do. What you want is to load the item into xyz's context instead (which xyz should have permissions to do).

Ok, let me back up a bit, and give you a bit of a summary of the launchd hierarchy in OS X. When the OS boots, it starts a master instance of launchd (the "system" launchd), which loads items from the various Library/LaunchDaemons folders.

When a user logs in (or otherwise starts a "session"), a new "bootstrap context" is created, a new instance of launchd (the "user" launchd) is started (in that new context) which loads items from the various Library/LaunchAgents folders (all within that new context).

When you use sudo -u xyz ..., it switches user IDs to xyz, but doesn't switch to xyz's context.

Now, there are a couple of cases here: first, if xyz isn't logged in (i.e. doesn't have an active session), they don't have a bootstrap context or a launchd instance, so you can't load a LaunchAgent as them. Basically, LaunchAgents load into user sessions, so if there's no session there's nothing to load it into. On the other hand, this shouldn't be a problem: next time xyz logs in, your item will be loaded automatically (as long as it's in the right place).

If xyz is logged in, you can get the process ID of some process within their session, and use launchctl bsexec to switch to that process's bootstrap context (and then use sudo -u xyz to switch UIDs to xyz, and then load the item):

loadUser=xyz
loadPID=$(ps -axj | awk "/^$loadUser / {print \$2;exit}")
launchctl bsexec $loadPID sudo -u $loadUser launchctl load /Users/xyz/Library/LaunchAgents/x.y.z.plist
share|improve this answer
add comment

I discovered that you can do this in two steps.

First sudo into root

sudo -s

Then impersonate the user

su -l user

Apparently that establishes the correct context and launchctl works.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.