Run pkg installation as the user

ndeal
New Contributor III

I'm working on a silent deployment of an agent that needs to install to and run as a service in the user context. Running the .pkg installer as the user via a bash script produces an error from the installer process when recurring checkin is used as the trigger:

PackageKit: XPC error in __43-[_PKInstallClientConnection blockingProxy]_block_invoke (Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.installd.user was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.installd.user was invalidated.})

The installation, however, works if run via "sudo jamf policy" in terminal as well as through Self Service.

Workarounds such as using a custom plist that at load calls script that runs the installation as well as copying files down via dmg and using a sudo -u $user launchtl load command via bash script do work - but only for users with administrative privileges. As it stands, I haven't found a way to successfully install and start the service for a standard user silently.

Wondering if anyone has ever had a need to do something similar with regard to installing something in the user profile that also needs to load a plist in the user context as well (an agent that just runs all the time as the user, not in the system/root context). That or if anyone has any suggestions of other wacky things to try in order to get a workaround going. Any recommendations would be helpful. I've also been primarily a windows admin/syseng historically, so please excuse my OS X/bash/etc. ignorance if/when it is displayed.

1 ACCEPTED SOLUTION

ndeal
New Contributor III

Made some more progress, building in the su suggestion, I found a link to another thread where the -l switch was suggested... https://www.jamf.com/jamf-nation/discussions/18627/running-a-script-as-a-login-user

su -l $current_user -c

This allows me to successfully load the plist for both admin and non admin users. There is more than that that needs to happen pre/post file deployment, so I was hoping I'd get really lucky and that I could just use su -l $current_user to call the installer command but sadly I just get a command not found error back... I wonder if explicitly calling the path to the installer command would work (like calling /bin/launchctl for example). So far i haven't found if Installer is actually a file somewhere that I can specify an explicitly path to in OSX. If anyone knows where or if it exists, that'd be mighty helpful.

Edit: found it via RTFM, /usr/sbin/installer. It works with the su -l! So much time of my life gone on this issue, but I'm glad to have found something that seems like a simple method. Will be doing some more rigorous testing on fresh machines tomorrow. Thanks for those that responded and nudged me the right directions.

View solution in original post

17 REPLIES 17

mm2270
Legendary Contributor III

You may want to look at using launchctl asuser (starting with 10.10 & up) or launchctl bsexec (10.9 and lower)
I've been able to use those commands pretty successfully to run commands as a user on the system, like for example, loading a user level LaunchAgent (installed at /Library/LaunchAgents/) for example.

Here's some sample code for you to use

#!/bin/bash

## Get the logged in user
loggedInUser=$(stat -f%Su /dev/console)

## Get the logged in user's UID
loggedInUID=$(id -u $loggedInUser)

## Load global user LaunchAgent as the logged in user (using the 10.10 and above syntax)
/bin/launchctl asuser $loggedInUID sudo -iu $loggedInUser "/bin/launchctl load /Library/LaunchAgents/com.somelaunchdjob.plist"

Of course, the above would only work effectively if someone is logged in since its getting the logged in user's name and UID and trying to use that. You could put some extra code in there to see if the "loggedInUser" turns out to be "root", meaning the Mac is likely sitting at a login screen, and just exit. There would be no need to try to load it in that case since it will get loaded naturally once someone logs in.

One last note, in case it wasn't obvious, the example script above would need to be run with admin privs or as root to work at all.

ndeal
New Contributor III

Thanks for the reply! I've been testing with launchctl asuser today, but haven't been successful thus far. For what it's worth i'm testing on 10.12.X as well.

Here is what I'm trying..

#!/bin/bash current_user=$(stat -f%Su /dev/console) user=$(id -u $current_user) /bin/launchctl asuser $user /usr/bin/sudo -iu $current_user "/bin/launchctl load /Users/$current_user/Library/LaunchAgents/com.AgentName.plist"

The error I get back is:

-bash: /bin/launchctl load /Users/test5/Library/LaunchAgents/com.AgentName.plist: No such file or directory

Only real difference I can see here is that the plist that is put down by the agent installation is located in the user's ~/Library/LaunchAgents folder, not in /Library/LaunchAgents. I suppose I could try moving it to the latter, it shouldn't really matter as long as the plist is launched as the user... the plist itself just references file paths in the user profile where the agent files actually exist, which should still be legitimate regardless of the location of the plist, unless that's just crazy talk .

Update: Same error if I try placing the plist in /Library/LaunchAgents instead of in the user profile.

mm2270
Legendary Contributor III

Hmm, that's odd. I agree it technically shouldn't matter which directory its in, but if its even failing when you try loading it from the root Library, folder, only thing I can think is, have you tried loading that same LaunchAgent manually with a regular launchctl load command? And does it work that way? Launchd jobs (plists) need to have specific permissions and ownership on them to work correctly. Although the error you usually get if they aren't set correctly is something other than what you're seeing.
Still, I'd double check that the plist loads when doing it normally as the user thru Terminal to rule out anything there.

iJake
Valued Contributor
su - $loggedInUser -c "SOME COMMAND HERE"

That will work for you

ndeal
New Contributor III

Yeah, I just manually ran "launchctl load /Users/test5/Library/LaunchAgents/com.AgentName.plist" and I did not receive any error and I can confirm the service is running with a launchctl -list command. Frustrating, to say the least!

donmontalvo
Esteemed Contributor III

ndeal
New Contributor III

Thanks @donmontalvo , I have actually seen that and have tried a number of the items in there but they don't seem to always work as expected when being called from a JSS policy with the intention of having things load in the logged in user context. Some of the things do work with a sudo -u or using bootstrap to load a custom plist that then calls an installation package but they only work if the user is an administrator.

ndeal
New Contributor III

@iJake , thanks for the suggestion but with the su $user -c, I still run into all of the same problems I see using sudo -u (error installing pkg file, operation not permitted for launchctl -load command) on a recurring checking triggered policy.

Things that work from terminal (or even via Self Service) are not working the same way when run in the recurring checkin policy... so for none of the few workarounds I've found work for standard users as far as getting a silent installation to deploy properly.

ndeal
New Contributor III

Made some more progress, building in the su suggestion, I found a link to another thread where the -l switch was suggested... https://www.jamf.com/jamf-nation/discussions/18627/running-a-script-as-a-login-user

su -l $current_user -c

This allows me to successfully load the plist for both admin and non admin users. There is more than that that needs to happen pre/post file deployment, so I was hoping I'd get really lucky and that I could just use su -l $current_user to call the installer command but sadly I just get a command not found error back... I wonder if explicitly calling the path to the installer command would work (like calling /bin/launchctl for example). So far i haven't found if Installer is actually a file somewhere that I can specify an explicitly path to in OSX. If anyone knows where or if it exists, that'd be mighty helpful.

Edit: found it via RTFM, /usr/sbin/installer. It works with the su -l! So much time of my life gone on this issue, but I'm glad to have found something that seems like a simple method. Will be doing some more rigorous testing on fresh machines tomorrow. Thanks for those that responded and nudged me the right directions.

bpavlov
Honored Contributor

@ndeal just curious, what package is it that you need to install as the user?

ndeal
New Contributor III

Sorry for the delayed response. Aternity, a user experience monitoring tool.

nicktong
New Contributor III

@ndeal Suggested to Adi M. (you all know each other, right :) that y'all make this a global LaunchAgent (/Library/LaunchAgents). Somewhat frustrating that the provided PKGs install the plist to ~/Library/LaunchAgents and even Aternity itself to ~/Library/Aternity. I have no problem with it running as the user, but it should run as any user who logs into the machine. May repackage and just install to /Library/LaunchAgents and /Library/Aternity if I can get Riverbed to agree that's supportable. Thoughts or do you see issues with that approach?

@iJake SmartSupport Forever.

ndeal
New Contributor III

@nicktong, yes I do know Adi. I'll follow up with your offline about this, I believe there are some dependencies on the ~/Library install location, but I'm not sure if they run deeper than a few of the scripts that come with the agent. Checking with PM team, will reach out to you on LinkedIn.

nicktong
New Contributor III

@ndeal Thanks!

KarmaLama
New Contributor

@ndeal can u suggest on on Aternity installation . How did ur final script look like ?

ndeal
New Contributor III

@KarmaLama,

The script should be pretty simple. I've included an example below. Please note that the script relies on the installation files for Aternity already existing on the machine somewhere (you can package them up via composer to be copied down to /tmp or another directory of your choosing). Make sure that the pkg and script file are executable for all users since Aternity installs in the user context.

#!/bin/bash current_user=$( ls -la /dev/console | cut -d " " -f 4 ) su -l $current_user -c "/usr/sbin/installer -verboseR -dumplog -pkg /path/to/files/mac-agent.pkg -target CurrentUserHomeDirectory" /path/to/files/Install-Chrome-Ext

KarmaLama
New Contributor

@ndeal Thank you very much.