In multiuser labs on campus we often have people log in once, and never log in again. Sometimes they pick a machine and always use that, sure, but inevitably at some point in the semester we start to run low on disk space. For that reason I have a policy to run once a week on our lab systems that runs a script to check if a user profile has been logged into within a variable number of days. For most systems I’ll use 28 days.
All lab systems are subject to replacement in the event of hardware or software failure, and as such generally a student (or faculty member) should be using network storage or google drive. At the same time we want to provide the convenience to users who may use the same system every class or study period.
This script is based on a script from a coworker (who appears to have pulled it from a GitHub and modified it). Its fairly simple but searches based on the last modified and excludes any user currently logged in. I use a variable (#4
) to assign different ages based on the locations.
error=0
## Checks if the variable has been provided
days=$4
if [[ -z $days ]]; then
read -p "Profile Age:" days
fi
## new shorter bash method to get logged in user
loggedInUser=$( scutil <<< "show State:/Users/ConsoleUser" | awk '/Name ꞉/ && ! /loginwindow/ { print $3 }' )
## Do not delete the current user or the shared folder, add additional users if needed
permanent=("Shared" "$loggedInUser")
## Verify script is being run as root
if [[ $UID -ne 0 ]]; then echo "$0 must be run as root." && exit 1; fi
## users that have not been active in the specified number of days
allusers=`/usr/bin/find /Users -type d -maxdepth 1 -mindepth 1 -not -name "." -mtime +$days`
echo "deleting inactive users"
## iterate through each inactive user, check if they are in the permanent list, then delete
for username in $allusers; do
if ! [[ ${permanent[*]} =~ "$username" ]]; then
echo "Deleting inactive (over $days days) account" $username
# delete user
/usr/bin/dscl . delete $username > /dev/null 2>&1
# find and delete home folder (in case it is not in /Users/)
home=$( dscl . read /Users/${username} NFSHomeDirectory )
/bin/rm -r $home
continue
else
echo "skip" $username
fi
done
echo "complete"
exit $error
Edit: I made some changes to the above script, including using a method to get the current logged in user via bash found here http://erikberglund.github.io/2018/Get-the-currently-logged-in-user,-in-Bash/ and some errors pointed out in a comment in my logic where I conflated username and home folder in a variable.
Edit 2: it seems the codeblock above had a strange WordPress induced bug in line 10 where it was displaying a colon backslash as an emoji. I have worked around this to display correctly, but please make sure you copy from the correct script located on GitHub here.
Nice script!
You don’t need to (& probably shouldn’t) invoke python to get the currently logged in user: https://scriptingosx.com/2020/02/getting-the-current-user-in-macos-update/
In line 21, it looks like you assume that the script is being run from within /Users, but it would be better to include the full path to the user folder. Also, if there is any risk that your users might have moved their user profile elsewhere, it’s not too difficult to check:
home=$( dscl . read /Users/${username} NFSHomeDirectory )
Finally, you are storing directory locations in $permanent, but you’re actually checking for usernames. I’d recommend storing usernames (or, in the example shown, replacing line 14 with a simple check that $username is not $loggedInUser).
LikeLike
Thanks for the note! I actually did update the script on GitHub with that method to get the logged in user after recently stumbling on a blog post, but I didn’t update this post. I will take a look and do some testing with your other suggestions as well.
LikeLike