$3 parameter username

winningham_2
Contributor

I have a syntax issue I am hoping someone can help me with...

I am trying to write to $HOME/fubar upon user login with a BASH script ran as a policy within JAMF.

I was thinking that $3 would return a username of the user logging in (lets say the local user is smith.1 who has just logged in, so $3=smith.1 and his homedir is /Users/smith.1/).

Now if I say, ```
touch ~$3/jamf.txt

I would then expect in the root of smith.1's  homedir to see jamf.txt, aka /Users/smith.1/jamf.txt

Alas, this is not working and it seems that while *3=smith.1* an ```
ls ~smith.1

returns "No such file or directory" within a debugging phase of my script and thus the rest of the script fails.

My question is, how does one create a script within JAMF that understands who just logged in and writes a file to that user's homedir and what then does $3 do for me?

To borrow another post's code, for example sake, why does the following fail?

defaults write ~$3/Library/Preferences/com.apple.screensaver.plist askForPassword -int 1
2 ACCEPTED SOLUTIONS

bentoms
Release Candidate Programs Tester

The $3 variable only works at login, you can use the below at anytime to get the logged in users username:

# Get the Username of the currently logged user
loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`

As for managing screensavers: http://macmule.com/2010/11/19/how-to-set-osxs-screen-saver-via-script/

View solution in original post

Josh_S
Contributor III

http://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html
You can use the tilde character to reference the home directory of the user currently executing commands:

whoami      # username
echo ~/      # /Users/username/

You can also use it to reference the home directory of an arbitrary user, even if the home directory exists in an unusual location.

echo ~administrator/      # /Users/administrator/
echo ~casperadmin/      # /private/var/casperadmin/
echo ~_www/      # /Library/WebServer/

So, given that, you would think that "~$3" would give the directory of the username specified in variable $3. Unfortunately this doesn't work since tilde expansion is done before variable substitution. Since the literal "$3" doesn't match any username, it is not expanded. In your test with "ls ~smith.1", I assume you're actually doing "ls ~$3". The tilde expansion is failing and then the variable substitution is being done, generating the error.

You can do something similar to to the following:

echo $3      # administrator
userDir=`eval "echo ~$3/"`
echo $userDir      # /Users/administrator/

View solution in original post

10 REPLIES 10

bentoms
Release Candidate Programs Tester

The $3 variable only works at login, you can use the below at anytime to get the logged in users username:

# Get the Username of the currently logged user
loggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`

As for managing screensavers: http://macmule.com/2010/11/19/how-to-set-osxs-screen-saver-via-script/

denmoff
Contributor III

I think the problem is in the use of the "~". You could try ```
defaults write /Users/$3/Library/Preferences/com.apple.screensaver.plist askForPassword -int 1
```

mm2270
Legendary Contributor III

Both @bentoms][/url][/url and @denmoff][/url][/url are 100% correct. The $3 built in variable only works with login and some Self Service policies. It sounds from your description that you are trying to use this with login, so it should work.
But per denmoff's point, you can't use a combination of ~ and $3 together because the tilde character denotes the current user's home directory path all by itself, as in /Users/smith.1. So ~$3 would be like saying /Users/smith.1smith.1 as a path which doesn't make sense of course. To make matters worse, when running from a Casper Suite policy it would be using ~ to indicate the root account, not the logged in user's account.

Personally I don't ever use $3 unless I'm 100% certain it will work, as in a script run from a login policy only. Otherwise I use something like what bentom's posted above to grab the current user's name

Josh_S
Contributor III

http://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html
You can use the tilde character to reference the home directory of the user currently executing commands:

whoami      # username
echo ~/      # /Users/username/

You can also use it to reference the home directory of an arbitrary user, even if the home directory exists in an unusual location.

echo ~administrator/      # /Users/administrator/
echo ~casperadmin/      # /private/var/casperadmin/
echo ~_www/      # /Library/WebServer/

So, given that, you would think that "~$3" would give the directory of the username specified in variable $3. Unfortunately this doesn't work since tilde expansion is done before variable substitution. Since the literal "$3" doesn't match any username, it is not expanded. In your test with "ls ~smith.1", I assume you're actually doing "ls ~$3". The tilde expansion is failing and then the variable substitution is being done, generating the error.

You can do something similar to to the following:

echo $3      # administrator
userDir=`eval "echo ~$3/"`
echo $userDir      # /Users/administrator/

c0n0r
Contributor

I never trust the $3 (I mainly write packages, so I think of $3 as install location, not logged in user) or $USER variables, as they can change depending on how the script is executed. Similarly, I don't trust tilde expansion, for all of the same reasons. Instead, I manually grab the name of the current console user and use that as a variable in future paths.

ConsoleUser=$(stat -f %Su "/dev/console")
touch /Users/$ConsoleUser/jamf.txt

winningham_2
Contributor

@bentoms That screensaver script will come in handy, thank you.

@Josh_S I used ```
userDir=`eval "echo ~$3/"
``
For login username capture, especially for the path of their homedir, this seems to be the better choice since we have some homes in /Users, some in /home, and some with both it appears. Scripting that out, while doable, seemed to be too complex for what I wanted. Your tip did the trick, thank you.

winningham_2
Contributor

@bentoms That screensaver script will come in handy, thank you.

@Josh_S I used ```
userDir=`eval "echo ~$3/"
``
For login username capture, especially for the path of their homedir, this seems to be the better choice since we have some homes in /Users, some in /home, and some with both it appears. Scripting that out, while doable, seemed to be too complex for what I wanted. Your tip did the trick, thank you.

@c0n0r I didn't see yours until today but I could see that working for us as well considering we are only administering GUI logins with Casper.

c0n0r
Contributor

This should net you the home folder directory of any actively logged in user.

ConsoleUser=$(stat -f %Su "/dev/console")
UserHome=$(dscl . -read /Users/ConsoleUser NFSHomeDirectory | cut -f 2 -d " ")

If you get REALLY desperate, you can always SU to a specific user, and have them spin off an isolated shell where you KNOW the variable $USER and $HOME will report back the content you need. You can then pass that data back to the main script (I would use defaults read/write and a plist in /tmp but whatever works for you) to do with as you will.

c0n0r
Contributor

WHOOPS... typo in that last bit, forgot a $!

ConsoleUser=$(stat -f %Su "/dev/console")
UserHome=$(dscl . -read /Users/"$ConsoleUser" NFSHomeDirectory | cut -f 2 -d " ")

I also forgot to mention that, while there has been times where it has been impossible, I actively try to avoid eval. I'm simply had too many bad bad bad things happen with it.
eval = evil

mm2270
Legendary Contributor III

Although I use a different command for grabbing the logged in user, I use essentially the same command for getting the logged in user's home directory path as @c0n0r][/url][/url does. To each his own of course, but I think the advantage of this is that you don't need to rely on $3, which, again, will only work with login policies and Self Service, and with the latter, I believe it only works if you force users to log into Self Service. If it doesn't ask for authentication I don't think $3 resolves properly.
So getting the logged in user, then their home directory path like above always seems like the safest method to me, personally, and is also the most portable since it will work even outside of a Casper Suite environment.