Posted on 05-17-2012 11:04 AM
I am needing a script that can be added to our summer update configuration that will delete every user with the exception of admins. Anyone had any luck doing this? I have tried using Tom Larkin's script and it seems to remove the home directories from /Users how ever the accounts are still populated in SystemPreferences>Accounts. Any ideas?
https://discussions.apple.com/message/12165862#12165862
dscl . -delete /Users/
dscl . list /Users | grep -v "_"
#!/bin/bash
UserList=`/bin/ls /Users | /usr/bin/grep -v "Shared"`
for u in $UserList ; do
if [[ `/usr/bin/dscl . read /Groups/admin GroupMembership | /usr/bin/grep $u -c` == 1 ]]
then /bin/echo "Admin account detected skipping..."
else /usr/bin/dscl . delete /Users/$u && /bin/rm -rf /Users/$u
fi
done
Solved! Go to Solution.
Posted on 05-17-2012 01:17 PM
The "dscl . delete /Users/username" command should remove it from the Accounts prefpane.
My script builds a list of users with UniqueID's higher than 1000 (this way it's only looking at cached AD users). It then checks for home directories older than 21 days and then removes the account and home directory for that user. It also only deletes users who are members of our students group in AD.
#!/bin/sh
userList=`dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'`
echo "Deleting account and home directory for the following users..."
for a in $userList ; do
if [[ "$(id $a | tr '[:upper:]' '[:lower:]')" =~ "your student AD group" ]]; then
find /Users -type d -maxdepth 1 -mindepth 1 -not -name "*.*" -mtime +21 | grep "$a"
if [[ $? == 0 ]]; then
dscl . delete /Users/"$a" #delete the account
rm -r /Users/"$a" #delete the home directory
fi
fi
done
Posted on 01-06-2017 11:45 AM
Can anyone help me? I work for a school district that allows teachers to checkout laptops from the library when needed. As a result I have several accounts on computers that do not need to be there. So I am trying to find a script that will delete mobile accounts even if they are an admin accounts except for a specified list. Example I want to keep the local admin and esteacher ( mobile admin) and esstudent ( mobile managed account) . Thanks for any help you can give I am VERY NEW to scripting.
Posted on 02-15-2017 06:33 PM
@TJ78620 The solution in this thread might work for you.
You'd modify the "KEEP" section with something like this:
KEEP=("/Users/Shared" "/Users/esteacher" "/Users/esstudent" "/Users/[LOCALADMIN]")
As well as the age of the accounts in this section:
AGE=122 # Delete /Users/ folders inactive longer than this many days
Posted on 02-17-2017 06:32 AM
Thanks Ryan I will give it a try
Posted on 02-17-2017 08:47 AM
5 year old thread, but since it's still active I will add the latest version of what I'm using. I think it's a little more robust than what I first posted. I've also considered moving the home directories to an archive directory instead of nuking them.
#!/bin/bash
userList=`dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'`
echo "Deleting account and home directory for the following users..."
for user in $userList ; do
if [[ "$(id $user | tr '[:upper:]' '[:lower:]')" =~ "my student group" ]]; then
if [[ "$(find /Users -type d -maxdepth 1 -mindepth 1 -not -name "*.*" -mtime +21 | grep "$user")" =~ "$user" ]]; then
dscl . delete /Users/"$user" #delete the account
rm -r /Users/"$user" #delete the home directory
echo "$user"
fi
fi
done
OR if you don't want the AD group lookup part...
#!/bin/bash
userList=`dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'`
echo "Deleting account and home directory for the following users..."
for user in $userList ; do
if [[ "$(find /Users -type d -maxdepth 1 -mindepth 1 -not -name "*.*" -mtime +21 | grep "$user")" =~ "$user" ]]; then
dscl . delete /Users/"$user" #delete the account
rm -r /Users/"$user" #delete the home directory
echo "$user"
fi
done
Posted on 02-28-2017 08:06 AM
This could be useful for a situation where we need keep our loaner computers cleaned up. If i simply didnt want to search for a student group or a specific name would i simply remove "=~ "my student group" and =~ "my student group"
all id be looking to do is delete any account older than x amount of days old.
Posted on 03-02-2017 04:30 AM
Running this...
find /Users -type d -maxdepth 1 -mindepth 1 -mtime +1
... does not return the proper list of users whose accounts are older than 24 hours. Running "ls -l /Users" returns a confirmation that the folders have not been modified for several days. After bashing my head against my desk as well as some research, it looks like -mmin is better at this. So this works for our scenario...
#!/bin/sh
# Remove Mobile Accounts.sh
# Removes all mobile accounts from the system
userList=`dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'`
echo "Deleting account and home directory for the following users..."
for a in $userList ; do
find /Users -type d -maxdepth 1 -mindepth 1 -mmin +$((60*24)) | grep "$a"
if [[ $? == 0 ]]; then
dscl . delete /Users/"$a" #delete the account
rm -r /Users/"$a" #delete the home directory
fi
done
Posted on 03-02-2017 06:07 AM
Here's the script I use to clean AD accounts. It started life as something to just delete all AD accounts. When we switched from classroom sets of MacBook Airs to a truer 1-to-1 model of students being assigned a laptop they could take home I modified the script so a student could run it from Self Service and delete any AD account but theirs (we had some teachers that didn't bother to have regular laptop assignments with their class sets resulting in some machines having over 70 users created).
Note that my environment is all >= macOS 10.10, so I use sysadminctl
rather than dscl
and rm
to delete the user accounts.
#!/bin/bash
################################################################################
# DeleteADUsers.sh
#
# Requires Mac OS X 10.10 or newer
# If run as root, deletes all AD accounts
# If user is logged in, asks to verify login ID and will not delete that account
################################################################################
adusers=$(dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}')
currentuser=$(stat -f "%Su" /dev/console)
response="2" # Presume confirmation failure
if [[ "$currentuser" != "root" ]]; then
# If we're not root, ask user to verify their login ID
response=$(/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper -windowType utility -title "Verify login ID" -heading "Verify login ID" -description "Please verify that $currentuser is your login ID" -button1 "That's Me" -button2 "Not Me")
if [ "$response" != "0" ]; then
echo "Did not get confirmation from user, no accounts will be deleted"
fi
else
echo "Running as root, so all AD accounts will be deleted"
response="0" # Always set confirmation response when root
fi
if [ "$response" == "0" ]; then
echo "Deleting AD user accounts..."
for user in $adusers ; do
if [ "$user" != "$currentuser" ]; then
/usr/sbin/sysadminctl -deleteUser "$user"
echo "$user deleted"
fi
done
fi
Posted on 04-28-2017 08:40 AM
I want to use the above script to delete AD users older than "X" days. I've tried modifying it, but my scripting skills could use a bit more work. The script works pretty well, but I noticed a couple strange behaviors that maybe someone with more knowledge could explain? I ran this script on one of our student lab computers with about 75 accounts. We use AD accounts that create a mobile account on login. Most of these accounts do NOT end up in the Users & Groups pref pane, however about 8 or 9 DID. In summary, if you look at /Users/ there are 75 folders, but only 8 or 9 of them are in U&G list.
All accounts that were in /Users/ but NOT in the U&G pref pane were deleted (except one.... weird part). I could not see anything about that one account that would explain it being left alone (not logged in, etc.)
I ran the script again and this time ALL accounts (except admin, shared) were deleted, the only accounts left were the ones in the U&G, and the straggler that didn't go away the first time... Not sure why this didn't happen on the first run, but did the second.
tl;dr
I want to modify the above script to ONLY delete AD accounts OLDER than "X" days
Thanks in advance!!!
Posted on 08-21-2017 02:11 PM
I feel like an absolute newb here, but I'm trying to make your script delete any mobile accounts; regardless of age. I've changed -mtime +21 to -mtime 0; but still not getting the desired results. We're looking to scope this to loaners for once they are checked in; it will completely wipe the mobile accounts.
Any help would be much appreciated!
Edit: Scratch that. Took out the "-not" flag, and things are nice and dandy. Thanks!
Posted on 11-03-2017 11:27 AM
We are running a script similar to the ones above, and it is working as intended. It logs when it ignores a user due to it not being a student account, ignores the current user, ignores a user due to recent activity, and removes a user due to no recent activity. However, I am running into a bizarre problem where sometimes some of my users' home folders are not updating with a modification date/time upon login. During some troubleshooting we have determined that some users' home folders have a modification date/time that is older than their last login when viewed from the last command. Has anyone else seen anything like this before?
Posted on 11-03-2017 12:01 PM
I've seen what you're seeing, but haven't looked into it too much. For now, we aren't removing user accounts and home directories with this method.
Posted on 11-03-2017 12:32 PM
Did you find a more reliable method, or are you just avoiding it altogether for now?
Posted on 11-03-2017 12:54 PM
Just avoiding at the moment. I think the answer is going to be to look recursively through all files in the home directory, find the newest one and use that date.
This may be a start:
https://stackoverflow.com/questions/4561895/how-to-recursively-find-the-latest-modified-file-in-a-di...
Posted on 11-03-2017 02:35 PM
Anyone reason you can think of not to just ignore those home folders that contain a file less than 30 days since last modification? Check out the third if statement with the find command.
#!/bin/bash
for home in /Users/*; do
username=`basename $home`
if [[ `echo $username | cut -c -1` =~ ^[0-9]+$ ]]; then
if [[ `stat -f "%Su" /dev/console` == $username ]]; then
echo "Skipping due to being currently logged in: $username"
else
if [[ `find $home -type f -mtime -30` ]]; then
echo "Skipping due to recent activity: $username"
else
dscl . -delete /Users/$username && echo "Removed user account: $username"
rm -rf $home && echo "Removed home folder: $home"
fi
fi
else
echo "Skipping non-student: $username"
fi
done
Edit: By the way, in our environment we are only trying to delete student users that have not been used in the last 30 days. All student usernames and only student usernames start with a number.
Posted on 12-14-2017 10:01 AM
@cbrewer
Trying to work with your script below and changing the mtime to 15 or 10 but it seems it doesn't delete any user accounts either way.
Wondering if 10.12.6 is not working the same way.
#!/bin/bash
userList=`dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'`
echo "Deleting account and home directory for the following users..."
for user in $userList ; do
if [[ "$(find /Users -type d -maxdepth 1 -mindepth 1 -not -name "*.*" -mtime +21 | grep "$user")" =~ "$user" ]]; then
dscl . delete /Users/"$user" #delete the account
rm -r /Users/"$user" #delete the home directory
echo "$user"
fi
done
Gabe Shackney
Princeton Public Schools
Posted on 12-14-2017 10:40 AM
@gshackney Read a few posts up. I've found that running find on just the home directory with mtime is not reliable. I personally wouldn't delete any home directories based on that logic alone.
Posted on 12-14-2017 10:46 AM
Ah, missed that. Guess I'm back to just deleting all users (minus my needed ones) once its 80% full
Gabe Shackney
Princeton Public Schools
Posted on 12-14-2017 10:51 AM
@gshackney I have a Self Service policy that will show for our Media Lab teachers when there is "more than X accounts" and they can remove all accounts except for our local admin and jamf account. Usually if they start seeing space issues (we have 120 SSDs) they go right to this now.
Posted on 12-14-2017 11:21 AM
Well since I stopped creating system user accounts with the bind, I just have to delete the home folders.
So Now I just run this when the drive hits 80% full or more(just edit the grep's with the accounts you want to save):
#!/bin/sh
for home in $(ls /Users | grep -v localadmin | grep -v Shared | grep -v admin | grep -v username | grep -v username | grep -v username | grep -v username | grep -v username | grep -v $3)
do
sudo rm -rf /Users/$home
done
Gabe Shackney
Princeton Public Schools
Posted on 01-19-2018 07:48 AM
@gshackney Where do you run this? In self service or as a policy based on a smart group?
Posted on 01-19-2018 07:55 AM
@tdilossi
Policy that runs automagically base on a Smart Group targeting specific heavy use machines and also machines over 80% full:
Gabe Shackney
Princeton Public Schools
Posted on 01-19-2018 07:59 AM
@gshackney excellent! thanks for the prompt response!!
Posted on 05-06-2019 08:03 AM
We were looking at implementing this recently, but one caveat we ran into was if you push packages in Jamf with the Fill Existing Users option checked, it will modify files in the users home folders, effectively making the find command with mtime inaccurate.
We are still looking for a trusted source for last login time/activity that can be used.
On a side note, there is a configuration profile payload for Mobility that lets you set deleting user accounts after x days of login, but it was unreliable for us. Deleting users too early.
Posted on 05-06-2019 08:57 AM
I've found it more reliable to get mtime on the user's Preferences folder versus their entire home directory.
if [[ $(find /Users/$user/Library/Preferences -type d -maxdepth 1 -mindepth 1 -mtime +30) ]]; then
echo "Deleting $user"
sysadminctl -deleteUser $user
fi