Running a script as a login user

swaroopmj
New Contributor

I'm trying to update the hot corners using a script pushed as policy from JSS. The script runs as the management user and doesnot set the hot corners for the user. When I run the script on the mac as user, it seems to work. Here is part of the snippet. The su currentuser prompts for a password. Is there a way to run the snippet below without a password prompt

!/bin/bash

currentuser=/bin/ls -la /dev/console | /usr/bin/cut -d " " -f 4
su "$currentuser" -c 'defaults read /Users/$currentuser/Library/Preferences/com.apple.dock | grep corner'

1 ACCEPTED SOLUTION

jholland
New Contributor III

@swaroopmj You need the -l flag for your su command, and the pound sign for your shebang line. Try this:

#!/bin/bash
currentuser=$(/bin/ls -la /dev/console | /usr/bin/cut -d ' ' -f 4)
su -l $currentuser -c "defaults read /Users/$currentuser/Library/Preferences/com.apple.dock | grep corner"

Then chmod/chown as needed.

View solution in original post

33 REPLIES 33

davidacland
Honored Contributor II
Honored Contributor II

Hi,

If you're running this at login you can use $3 for the logging in user.

You shouldn't need the su part for a defaults read.

stevewood
Honored Contributor II
Honored Contributor II

@swaroopmj you are also missing the grave ticks to make your currentuser call work:

#!/bin/sh

currentuser=`/bin/ls -la /dev/console | /usr/bin/cut -d " " -f 4`
defaults read /Users/$currentuser/Library/Preferences/com.apple.dock | grep corner

Grave ticks are on the tilde (~) key.

mm2270
Legendary Contributor III

No, I don't think he was missing the grave marks. The forum treats them as the single line code formatting from Markdown, so they don't appear in the post. The way to preserve them is to wrap the entire script in the script code with ``` at the start and end.

stevewood
Honored Contributor II
Honored Contributor II

Ah, yes, I see what you mean @mm2270 . My mistake.

Changing the defaults read line to what I have there should work. At least it did in my quick testing.

mm2270
Legendary Contributor III

Yes, thats right. Since the logged in user name is being grabbed, there's no need to run the command as the user. Just do a default read against the user's plist file. Its being run as root so it won't have a problem reading a plist from a user's home directory. So both @davidacland and @stevewood have the right answer for you.

swaroopmj
New Contributor

Thanks for the quick reply @stevewood and @davidacland

I'll explain my problem a little more. I'm implementing the CIS benchmarks for hot corners. One of them is to ensure that the user never sets a hot corner to disable the screensaver. So I've to ensure that none of the corners have a value of 6. I've two problems when I use the command in the script above
1. The default file permission for com.apple.dock.plist is rw-------. So I cant even read the file as a different user
2. I do intend to run this script with a Login hook. The policy still runs under the jss management account on the box. So unless I can run a chmod to allow read on the plist, I wont be able to read/write into the plist if I do find the value 6.

I'm new to JSS and maybe there is an easier way to accomplish this? Also, in the actual script I do use the ` key.

stevewood
Honored Contributor II
Honored Contributor II

Unless I'm mistaken, running as root you should be able to read that plist file even if it is set to 600. So using the defaults command as @davidacland and I mentioned, should work.

mm2270
Legendary Contributor III

@swaroopmj The JSS runs scripts as "root", so it can in fact read into another user's plist file without issue. The only problem you may run into is if your script is making changes to another account's plist files, you'll probably to make sure to set the permissions on the plist file after the write is done so the account can read it. Generally speaking, when a defaults write command is done under the root context, root becomes the owner of the file and is typically the only account that can read it back, meaning the user's account will ignore the preference at login since it can't read the contents.

You can fix this by adding something along these lines after you make the change to the plist:

chown $currentuser /Users/$currentuser/Library/Preferences/com.apple.dock.plist
chmod 600 /Users/$currentuser/Library/Preferences/com.apple.dock.plist

dan-snelson
Valued Contributor II

You may want to try …

sudo -u $currentuser /usr/bin/defaults write /Users/$currentuser/Library/Preferences/com.apple.dock.plist

… which theoretically shouldn't hose the user's permissions.

jholland
New Contributor III

@swaroopmj You need the -l flag for your su command, and the pound sign for your shebang line. Try this:

#!/bin/bash
currentuser=$(/bin/ls -la /dev/console | /usr/bin/cut -d ' ' -f 4)
su -l $currentuser -c "defaults read /Users/$currentuser/Library/Preferences/com.apple.dock | grep corner"

Then chmod/chown as needed.

Fairly old thread but after trying numerous ways to do this, yours ended up working for me.

For hiding the bluetooth icon in the top bar:

defaults write ~/Library/Preferences/ByHost/com.apple.controlcenter.plist Bluetooth -int 24

Above doesn't work as sudo or admin, only works as logged in user.

#!/bin/bash

currentuser=$(/bin/ls -la /dev/console | /usr/bin/cut -d ' ' -f 4)

su -l $currentuser -c "defaults write ~/Library/Preferences/ByHost/com.apple.controlcenter.plist Bluetooth -int 24"

The above is working in 12.2 Monterey. 

swaroopmj
New Contributor

So, I ran the chown and chmod in the end to make sure the plist file has the same permissions as it did before. My output says the file permissions were set right. But I see the hot corner still set to old value in the new file. The default write was suppose to set the value to 0 instead of 6. Seems the plist gets overwritten by whatever the values were before.

swaroopmj
New Contributor

@jholland That fixed my problem. Thanks a lot everyone.

scottb
Honored Contributor

@swaroopmj - I'd be curious to know what you find in your results on this one! I've thought about that too, and it seems folks have not figured out that little work-around...

swaroopmj
New Contributor

@scottb Not sure I follow the question.

scottb
Honored Contributor

@swaroopmj -

I'll explain my problem a little more. I'm implementing the CIS benchmarks for hot corners. One of them is to ensure that the user never sets a hot corner to disable the screensaver.

Just curious to see how many clients know to use this to bypass the setting to avoid being sent to screensaver...

swaroopmj
New Contributor

Oh ok. I don't have any hard data on that. But I work in Finance and Insurance sector so it is a mandatory thing to implement irrespective of how many know how to do bypass it.

mm2270
Legendary Contributor III

I just remembered that a long time ago I worked on something similar, but my approach was a bit different. I had created a combination LaunchAgent and script if my memory serves. The LaunchAgent would detect changes to the dock plist or something like that, and would fire a script that checked if hot corners had been enabled and would disable them if so.
I honestly can't even remember now why I worked on that. It must have been a possible requirement for us to prevent those settings from being changed or something, but was later dropped.

But to back up a sec, have you looked at the possibility of a Configuration Profile for this? If you can get your settings as you want them, you may be able to use mcxToProfile to convert it into a user level profile that would apply the settings and lock them into place, but I'm just guessing since I can't say I've even tried doing it that. Might be worth exploring though, instead of mucking around with repeatedly run scripts.

milesleacy
Valued Contributor

ndeal
New Contributor III

@jholland your post in this thread solved a very frustrating issue I've been having with a user-context based install/agent. Wish I'd found it in earlier searches and saved more time, but I thought you deserved a shoutout/thanks as I was putting together some pretty rube goldberg type stuff to try to accomplish the installation.

BCPeteo
Contributor II

So I'm trying to run a command as the logged in user at login with Jamf 10.8 on high sierra (10.13.6) but I'm noticing that the currentuser=$(/bin/ls -la /dev/console | /usr/bin/cut -d ' ' -f 4) is getting root and not the user who is logging in.
This does not happen on macOS 10.12.
When running this from a terminal window using sudo jamf policy -event login it works fine and gets the correct user.

Any ideas?

Update: turns out you have to have login logout hooks set to preform in the background
https://www.jamf.com/jamf-nation/discussions/9360/login-script-command-run-as-user-not-working-anymore

Buraq
New Contributor III

Hi @mm2270

I have a script that must be run as user. I'm trying to create a launch demon to call it but when I run it using launchctl load -w My daemon path nothing happens.
I've placed the daemon and script under ~/Library/LaunchAgent/
I've also chmod 755 both files
The Daemon is:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict> <key>Label</key> <string>com.zerowidth.launched.run_data_science_bash</string> <key>LaunchOnlyOnce</key> <true/> <key>ProgramArguments</key> <array> <string>sh</string> <string>~/LaunchAgents/Data Science/Datascience_High_Sierra.sh</string> </array> <key>RunAtLoad</key> <true/>
</dict>
</plist>

Any idea what am I missing!

mm2270
Legendary Contributor III

@Buraq I think one issue is probably the POSIX permissions. LaunchAgents and LaunchDaemons are supposed to be set to 644, not 755. The script/program it runs can be set to 755 though.

Second, I would consider putting the script in some other more general location than in the ~/Library/LaunchAgents/ folder. While it might work from there, a better place might be in /Users/Shared/ for example, or even in some more hidden location, like /private/var/

Third, are you wanting the LaunchAgent to only run when the one account logs in, and not any other accounts? Because putting it into ~/Library/LaunchAgents/ for the current user means no other accounts will have that run. If you want it to run when any account logs in, it should go into the higher level Library folder, meaning /Library/LaunchAgents/

Outside of these things, I can't say I've looked over your agent plist very carefully. There could be a formatting issue with it, but I don't know without bringing it into another program to check it.

cdenesha
Valued Contributor II

I see a space that isn't escaped

edit @Buraq

mm2270
Legendary Contributor III

@cdenesha If you're referring to this section:

<key>ProgramArguments</key>
<array>
    <string>sh</string>
    <string>~/LaunchAgents/Data Science/Datascience_High_Sierra.sh</string>
</array>

Believe it or not, paths to executables or scripts in the Program or ProgramArguments section of a launchd plist don't need to be escaped. Here's an example from the Box.com Helper LaunchAgent. Notice the three different spaces in the path for the program arguments string. Yet it still works.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.box.desktop.helper</string>
    <key>LimitLoadToSessionType</key>
    <array>
        <string>Aqua</string>
    </array>
    <key>Program</key>
    <string>/Library/Application Support/Box/Box/Autoupdater/Box Helper.app/Contents/MacOS/Box Helper</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>

Buraq
New Contributor III

@mm2270 Thanks for your reply!

I've just set the permission of the Agent to 644, but same blank result when I launchctl load -w MyAgent

You are right in this should be only run for the current user therefore I guess the path is ok.

Any thoughts?

Buraq
New Contributor III

@cdenesha Could you please elaborate?

cdenesha
Valued Contributor II

@Buraq I was wrong about the space, per the next post in the thread. :)

Buraq
New Contributor III

UPDATE:
I managed to load the Agent. The problem was with wrong extension. Now if I launchctl load -w MyAgent nothing happens, and when I run the same command again I get this: service already loaded.
Both times the actual script is not called.
This is how I'm calling it in the launch agent:

<key>ProgramArguments</key> <array> <string>sh</string> <string>-c</string> <string>/Users/buraqalsmadi/Library/LaunchAgents/DataScience/Datascience_High_Sierra.sh</string> </array> <key>RunAtLoad</key> <true/>

mm2270
Legendary Contributor III

@Buraq I'm not sure if it's necessary to put the sh -c in front of your script path. If you make sure the script has the executable bit set (run chmod +x /Users/buraqalsmadi/Library/LaunchAgents/DataScience/Datascience_High_Sierra.sh against it) then simply putting in the path to the script should run it when the agent is loaded. You usually only need to put in things like sh if you want to use a different interpreter than specified in the script or if it's not set as executable. I would try removing the <string>sh</string> <string>-c</string> section and trying again.

But one other thing. If launchctl is saying the plist is already loaded, you'll want to make sure to unload it first before trying to load it again. Just use launchctl unload on it.

Nix4Life
Valued Contributor

if you see yourself doing more of this in the future, you may want to check out outset

  1. Install outset
  2. Place script in applicable folder
  3. Create .pkg with composer for mass deploy
  4. Beer/Pub

Buraq
New Contributor III

@mm2270 I have removed <string>sh</string> <string>-c</string> and tried again, no luck!
The script is executable.
It seems what matter I do, and even when the launch agent loads, it doesn't call the script

gabester
Contributor III

I needed the logged in user to run something similar from Self Service; thanks to tips here ended up using something like this in a script:

sudo -u $3 -i /path/to/binary --parameter $3 --destination /Users/$3/Desktop/$3 --verbose