How to determine if a user is logging in for the first time

dstranathan
Valued Contributor II

Does anyone know of an accurate way (by script or command) to determine if a user has logged into a particular Mac in the past or not?

Im experimenting with a "first-run" type of script that would run once per user per computer, but I only want it to affect new local users login in for the very first time (not existing local accounts). Long story on what Im trying to achieve here.

16 REPLIES 16

gabester
Contributor III

Can you talk a bit more about what you want to accomplish? Specifically, it sounds like you might NOT want this script to run against users who have logged in prior to implementing and deploying it.

I also assume you're deleting accounts/folders periodically from /Users, hence you can't just check the creation date of their home folder.

I assume we're talking about network users here... Depending upon HOW the network account login is configured you could check their ID against the result of "dscl localonly -list /Local/Default/Users" - although by the time the script runs from their account it might be too late; you might need to establish this list ahead of time with a different script (run at startup / user logout) and have each user update it on first logon accordingly.

Hope that helps!
g=

mm2270
Legendary Contributor III

Hmm. Well, you might be able to grab the logged in username and check the last command for lines that begin with that account name, and do a count. if the total is greater than 1, then I'd assume its not the first time the account has logged into the Mac. For example,

#!/bin/bash

sleep 3

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

loginCount=$(last -t console | grep "^${loggedInUser}" | awk 'END {print NR}')

if ((loginCount>1)); then
    echo "Not first login. Exiting..."
    exit 0
else
    echo "First login. Continuing..."
    ## Do something here
fi

To be 100% fair, I haven't tested this against an actual first login, so I don't know for sure how well something like this would work. I assume it would but you'd need to test that out for yourself. The sleep at the beginning is just to ensure the login has time to complete and register with the last command before it runs.

dstranathan
Valued Contributor II

The "big picture" on my scenario is too complicated (and too boring) to go into too much detail on. It tentacles in various directions too, depending on how I try and leverage it.

In a nutshell, it will be the key in determining if certain Finder and Dock settings will or will not be applied at login time. I have a contigent of older users on exisitng Macs who Im not going to affect, but going forward all new Macs and (new users on exisitng Macs) will be affected. The magic will be dertiming if they are logging in for the first time or not.

I'm not deleting user accounts of homedirs. Not data loss concerns here.

I simply want to determine if a user who happens to be logging into a Mac has ever logged into it before.

I'm referring to Active Directory users (who are managed mobile accounts and get local accounts created in OS X's dscl). They all have local homedirs in /Users.

I'm referring to user logging into GUI console sessions (i.e.; not SSH sessions).

One idea I am pondering...

At login time, examine the user's homedir in /Users to verify its creation date, and then make a caluation to the affect of "if the homedir is older than, say, ~1 hour, then exit the script (safe bet that the user is not logging in for the very time), otherwise continue with other tasks in the script as needed.

But Im not sure Id reliably capture (and trust) homedir date stamps. I have played with /usr/bin/stat and other tools but am not getting the right values to make a comparaison to.

ShaunRMiller83
Contributor III

Since the post doesn't go into specifics on what the actual goal is. I do have a script that can check if a user has logged into a system or not and has exclusions for service and local accounts.

This script was to add a mobile user network admin account when they log in with there standard account. It could certianly be adapted for other uses.

#!/bin/sh

### Script Variables###
CD="/Applications/utilities/CocoaDialog.app/Contents/MacOS/CocoaDialog"
userName=$(ls -l /dev/console | awk '{ print $3 }')
adminusername="$userName"admin    
UID1=$(id -u $userName)

if [[ "$UID1" -lt 1000 ]]; then
     echo ""$userName" is a local user. This script will now quit"
     exit 0
else

if [[ $currentUser == *"admin"* ]]; then
  echo ""$currentUser" is an admin account. This script will now quit"
  exit 0  
else 

if [[ $userName == *"adobeinstall"* ]]; then
  echo "The adobeinstall account is a service account. This script will now quit"
  exit 0  
else

if [[ -e /Users/"$adminusername" ]]; then 
        echo ""$userName" already has an admin named "$adminusername" on this system"
        exit 0
else 

if [[ "$UID1" -ge 1000 ]]; 
            then echo "User "$userName" is an Active Directory account"
            /System/Library/CoreServices/ManagedClient.app/Contents/Resources/createmobileaccount -v -n "$adminusername" -h /Users/"$adminusername"
            dscl . -append /Groups/admin GroupMembership "$adminusername"
        fi
    fi
 fi
fi

gabester
Contributor III

I think we're headed in the right direction here... and another recent thread seems to have some good - but different - hints too:

https://jamfnation.jamfsoftware.com/discussion.html?id=4502#responseChild21985

Thank you for clarifying what you needed... besides mostly enjoying the power of jamfnation to bounce ideas off the heads of others!

dstranathan
Valued Contributor II

Im getting closer.

The -mtime switch for the /usr/bin/find command is helpful! Never used it before. May come in handy.

Thank you @Sterritt

iJake
Valued Contributor

FYI to all but specifically @mm2270 Apple has deprecated the last and ac commands so while they continue to work I have seen cases where they stop functioning and are not promised to continue to. Guidance is to pull the login and logout data from these commands respectively:

syslog -F raw -k Facility com.apple.system.lastlog
syslog -F raw -k Facility com.apple.system.utmpx

It is far from ideal and as nice as last. I have an ask in for them to update or recreate what the last command can report on. Just thought I'd give you a heads up.

dstranathan
Valued Contributor II

Paydirt. Maybe.

Running the /usr/bin/last command and filtering on the current console might be helpful. If the user isn't in the last log then it can be assumed that the user is logging in for the first time. That's all I need. No-brainer. I couldn't see the forest from the trees.

I wasnt aware that Apple has deprecated /usr/bin/last in Darwin. Wonder if I should play Russian Roulette with /usr/bin/last or not.

@iJake How did find out that /usr/bin/last is deprecated?

dstranathan
Valued Contributor II

I have found that /usr/bin/last cant be trusted. A "quantum" thing happens - A new user logs in and my script runs. Script queries /usr/bin/last and sees that the new user just logged in (albeit just a few seconds prior), therefore the script thinks the user is an "exisitng user" and not a new user and exits. Its sort of a race condition. Id have get get more surgical at the last data (filter and examine timestamps etc)

@mm2270 sample above (looks for greater than 1 entry in /usr/bin/last ) isnt working for me. It thinks ALL users are new users. Need to play with it more...

Now I'm playing with /usr/bin/syslog (per @iJake advice) , but I suspect that syslog may not be helpful either because the logs can be rolled-up, delete, etc.

mm2270
Legendary Contributor III

Hey @dstranathan you may want to take a look at the script I posted above last week. You'll see that I do a count of the number of 'console' entries that have the logged in users name in them from the last command. If the count is greater than 1, then it's not the first login. If it's 1, then it is the first login.
You'll never be able to make a login script runner faster than the last command will write in the login entry. There should be no need to do something like look at the login time stamps and compare them.

Edit: Looks like you edited your post since I posted. I'm not sure why its not working for you, since I actually did get around to trying the script on a Mac. I created a new user account, one that was never on it before, and logged in and had the script run. It echoed back it was the first login. I then logged out, logged in under a different account and then back into the new account and ran the script again and it reported it was not the first login. So, not sure what the deal is, but it worked for me. Are you certain the accounts you're testing it under have never been on the Mac before? If its an account that was created, then later deleted and recreated on that same Mac, its not going to work.

iJake
Valued Contributor

The below one-liner might help in all of this as it pulls the date the account was created.

dscl . readpl /Users/"$USERNAME" accountPolicyData creationTime | awk -F: '{ print $2 }' | tr -d " " | cut -d "." -f 1

dstranathan
Valued Contributor II

@mm2270

I appears to be working when ran as a script from a policy, but when running locally as me it yields different results.

Thanks again sir.

dstranathan
Valued Contributor II

@mm2270 I have determined that the following command doesnt work on all my Macs:

last -t console

The "console" switch fails to show me correct information. It works fine wth ttys001 (Terminal or SSH) sessions, but not GUI console sessions.

The last command is a strange beast. Definitely needs to run as admin rights.

iJake
Valued Contributor

@dstranathan Yes, I mentioned earlier last has been deprecated by Apple and is not promised to work. See my post above.

thoule
Valued Contributor II

@iJake Where did you get your information that last was depreciated? I have an Apple support request open to find out why it's not working on some machines and never got that info. I also didn't get the guidance on using syslog. Where did that guidance come from? Apple? What branch? Finally, the syslog commands you gave above generated no output on my machine - you are able to see login history using that command?

iJake
Valued Contributor

@thoule It was given to me by AppleCare Enterprise Support. More accurately, wtmp is what is deprecated and that is what last uses. It was replaced with asl. See this exchange:

The man page for wtmp indicates that this system is deprecated. The commands replying on this file do function, but as you have seen they sometimes will only report partial information.The appropriate replacement would be using syslog to access the asl logs, which do contain this information. An example command would be:
syslog -F raw -k Facility com.apple.system.lastlog
This is admittedly more information to have to dig through, and probably less convenient than the traditional commands. However if this is being automated you should be able to narrow it down to the information you want in your report.
Accessing the asl logs with syslog or asl is the intended method to get this information on a system. As an example of how this output can be reduced to something more readable, this command line prints out the unix timestamps and short usernames.
syslog -F raw -k Facility com.apple.system.lastlog | awk '{ print substr($4,1,length($4)-1) " " substr($28,1,length($28)-1) }'
Another option would be to periodically run the commands and log their output to your own log file over time. It would likely be an even more involved solution to use auditd, however I mention it because it would be one other method to gather login information.