How do I run a script from JSS as the logged in user in Self Service?

itupshot
Contributor II

I'm trying to figure out how I can run a script from Self Service as the user who is triggering it. By default, the scripts are being run as root (or the service account, I think).

For background, it's a script to re-direct screenshots from being saved to the Desktop to another folder. I'd like this script to run as the user who is logged into Self Service so they have ownership of the folder created. Here's an example of what I got so far:

#!/bin/bash

    mkdir -p $HOME/New_SCREEN_SHOTS_Folder
    defaults write com.apple.screencapture location $HOME/New_SCREEN_SHOTS_Folder
    killall SystemUIServer

exit 0
7 REPLIES 7

mm2270
Legendary Contributor III

There isn't an easy way to run the entire script as the user, unless you deployed it as a local script and called it via a LaunchAgent, but you can run portions of the script as the logged in user, or, in your case, simply determine who the logged in user is and make sure to direct the command at their files and preferences.

So using what you have above, the following should work to ensure the logged in user's plist is being written to.

#!/bin/bash

loggedInUser=$(stat -f%Su /dev/console)

mkdir -p /Users/$loggedInUser/New_SCREEN_SHOTS_Folder

/usr/bin/defaults write /Users/$loggedInUser/Library/Preferences/com.apple.screencapture.plist location /Users/$loggedInUser/New_SCREEN_SHOTS_Folder

## Make sure the plist we just wrote to as root is owned by the user and not root
/usr/sbin/chown $loggedInUser /Users/$loggedInUser/Library/Preferences/com.apple.screencapture.plist

killall SystemUIServer

EDIT: Looking at it again, you may also want to throw in an extra chown -R command against the new folder the script creates, just to ensure the user also owns that directory and not root.

bentoms
Release Candidate Programs Tester

If running via Self Service, $3 works to get the username.

No idea why I didn't do it, here but seems a similar script.

itupshot
Contributor II

@bentoms @mm2270 Thanks for you guidance. I remembered that $3 outputs the current user logged in. So, do you think adding an "su -c $3" line at the beginning should work?

#!/bin/bash

    su -c $3
    mkdir -p $HOME/New_SCREEN_SHOTS_Folder
    defaults write com.apple.screencapture location $HOME/New_SCREEN_SHOTS_Folder
    killall SystemUIServer

exit 0

Otherwise, more like your suggestions:

#!/bin/bash

    mkdir -p $HOME/New_SCREEN_SHOTS_Folder
    defaults write $HOME/Library/Preferences/com.apple.screencapture location $HOME/New_SCREEN_SHOTS_Folder
    chown $3 /Users/$HOME/Library/Preferences/com.apple.screencapture.plist
    chown -R $3 /Users/$HOME/New_SCREEN_SHOTS_Folder

    killall SystemUIServer

exit 0

I know you both defined the home folder path more specifically as "/Users/$loggedInUser/folderpath," but $HOME does the same, correct? Do you think I would also have to include a couple of "chmod" lines for the plist and folder being created?

I'm just trying to use as few lines as possible.

rtrouton
Release Candidate Programs Tester

You can use launchctl to run commands using the logged-in user's privileges. I discuss how to do that as part of the post linked below:

https://derflounder.wordpress.com/2016/03/25/running-processes-in-os-x-as-the-logged-in-user-from-ou...

For a practical example of how I've used it, please see the link below:

[https://derflounder.wordpress.com/2016/11/10/providing-website-links-via-casper-self-service-policies/](lhttps://derflounder.wordpress.com/2016/11/10/providing-website-links-via-casper-self-service-policies/)

mm2270
Legendary Contributor III

I don't believe the $HOME variable will work in a case of the script being run by another account, like the service account or root. For example, if you simply switch to another account on the Mac in Terminal, like su administrator and then run echo $HOME you'll see the path it prints is of the account you just logged into, not your home path. Because it doesn't work in that context, you would need to use something like /Users/$3/ or /Users/$loggedInUser/, meaning the full path to the home directory.

As for whether to use $3 or a separate logged in user variable, that is entirely up to you. $3 certainly works for your case scenario, but I tend to write scripts to be as portable as possible (at least most times). I never know if I'll end up running the script in a different context, like not from Self Service. In that case, a separate variable that would always get the logged in user would work in those extras cases, not just from Self Service or the login/logout trigger. But its really up to you. If you're pretty confident you'll only be running this from Self Service, then $3 should be fine to use.

ndeal
New Contributor III

Are the users always going to run it from Self Service?

I've had to run package installers before as the user and ended putting the package within a package using Composer to copy the file locally then ran a script using the su command to run the pkg as the user. This was all being done silently/in the background using a checkin as a trigger (vs. initiation from Self Service). I noticed differences in launching via Self Service and launching via recurring checkin when using sudo vs. su -c, just a heads up. That was mostly related to running the pkg installation, though.

Snippet:
current_user=$( ls -la /dev/console | cut -d " " -f 4 )
su -l $current_user -c "/usr/sbin/installer -verboseR -dumplog -pkg /path/to/packag/installer.pgk -target CurrentUserHomeDirectory"

I don't think your use case would warrant copying a separate script down, just run the commands requiring user privileges with su. Sudo -u $current_user can also work as a prefix to the command you're trying to run but like I said, I saw odd behaviors with that so just something to keep in mind. Hope this helps.

Buraq
New Contributor III

**@mm2270 "There isn't an easy way to run the entire script as the user, unless you deployed it as a local script and called it via a LaunchAgent"

Could you please elaborate on that or maybe some step-by-step guide? I have a script that has to be run completely by the user and your way seems to be the only one.

Thanks