Assistance needed: Deleting Mobile Accounts older than 30 days.

Poseiden
New Contributor III

Beginner scriptor in need of some assistance. I basically pieced this script together from two other scripts, it fails when I run this and works when separated.

This is the error I receive when running the script, which I'm guessing is a syntax error. Any help would be greatly appreciated!

Script exit code: 2
Script result: /Library/Application Support/JAMF/tmp/Delete User Profiles Older than 1 day: line 19: unexpected end of file

Script

#!/bin/bash

# Delete User Profiles in /Users. Exclude the 'Shared' account.
oldUsers=`find /Users -type d  -mtime +1 -maxdepth 30 | cut -d"/" -f3`

for oldUsers in `ls /Users | grep -v Shared`
do
    if [[ $oldUsers == `ls -l /dev/console | awk '{print $3}'` ]]; then
        echo "Skipping user: $username (current user)"
    else
        echo "Removing user: $username"

        # Optional, removes the account
        dscl . delete /Users/$username

        # Removes the user directory
        rm -rf /Users/$username
    fi
1 ACCEPTED SOLUTION

mscottblake
Valued Contributor

@Poseiden That script I had deletes all users on the machine. I was running that in a lab environment. This is what I run when I need to delete accounts older than X days:

#!/bin/bash

#  Modified 2015-03-11
#  delete_inactive_users.sh
#  Maintained at https://github.com/dankeller/macscripts
#  by Dan Keller
#
#  MIT License
#
#======================================
#
#  Script to delete local user data that has not been accessed in a given time
#  period.
#
#  This script scans the /Users folder for the date last updated (logged in)
#  and deletes the folder as well as the corresponding user account if it has
#  been longer than the time specified. You can specify user folders to keep as
#  well.
#
#  User data not stored in /Users is not effected.
#
#  Helpful for maintaing shared/lab Macs connected to an AD/OD/LDAP server.
#
#======================================

#----Variables----
# DEFAULT VALUE FOR "AGE" IS SET HERE
AGE=122 # Delete /Users/ folders inactive longer than this many days

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 4 AND, IF SO, ASSIGN TO "AGE"
if [ "$4" != "" ]; then
  AGE=$4
fi

KEEP=("/Users/Shared") # User folders you would like to bypass. Typically local users or admin accounts.
#--End variables--


### Delete Inactive Users ###
if [[ ${UID} -ne 0 ]]; then
  echo "$0 must be run as root."
  exit 1
fi

USERLIST=$(/usr/bin/find /Users -type d -maxdepth 1 -mindepth 1 -not -name "." -mtime +"${AGE}")

echo "Performing inactive user cleanup"

for a in ${USERLIST}; do
  if ! [[ ${KEEP[*]} =~ "$a" ]]; then
    echo "Deleting inactive (over ${AGE} days) account and home directory: $a"

    # delete user
    /usr/bin/dscl . delete "$a" > /dev/null 2>&1

    # delete home folder
    /bin/rm -r "$a"
    continue
  else
    echo "SKIPPING $a"
  fi
done

echo "Cleanup complete"
exit 0

View solution in original post

18 REPLIES 18

CasperSally
Valued Contributor II

I'm using @cbrewer script posted here. Didn't compare the 2 but hopefully will get you going.

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

Chris
Valued Contributor

You're missing a "done" in your for-loop

Poseiden
New Contributor III

@CasperSally I took a look at @mscottblake from this post, basically the same.

https://jamfnation.jamfsoftware.com/discussion.html?id=5042

@Chris

Adding a done at the end just deletes everything in /Users/

Chris
Valued Contributor
Adding a done at the end just deletes everything in /Users/

Not adding it will make your script not run ;)
The problem is this line:

oldUsers=`find /Users -type d  -mtime +1 -maxdepth 30 | cut -d"/" -f3`

is not doing what you want it to

mscottblake
Valued Contributor

@Poseiden That script I had deletes all users on the machine. I was running that in a lab environment. This is what I run when I need to delete accounts older than X days:

#!/bin/bash

#  Modified 2015-03-11
#  delete_inactive_users.sh
#  Maintained at https://github.com/dankeller/macscripts
#  by Dan Keller
#
#  MIT License
#
#======================================
#
#  Script to delete local user data that has not been accessed in a given time
#  period.
#
#  This script scans the /Users folder for the date last updated (logged in)
#  and deletes the folder as well as the corresponding user account if it has
#  been longer than the time specified. You can specify user folders to keep as
#  well.
#
#  User data not stored in /Users is not effected.
#
#  Helpful for maintaing shared/lab Macs connected to an AD/OD/LDAP server.
#
#======================================

#----Variables----
# DEFAULT VALUE FOR "AGE" IS SET HERE
AGE=122 # Delete /Users/ folders inactive longer than this many days

# CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 4 AND, IF SO, ASSIGN TO "AGE"
if [ "$4" != "" ]; then
  AGE=$4
fi

KEEP=("/Users/Shared") # User folders you would like to bypass. Typically local users or admin accounts.
#--End variables--


### Delete Inactive Users ###
if [[ ${UID} -ne 0 ]]; then
  echo "$0 must be run as root."
  exit 1
fi

USERLIST=$(/usr/bin/find /Users -type d -maxdepth 1 -mindepth 1 -not -name "." -mtime +"${AGE}")

echo "Performing inactive user cleanup"

for a in ${USERLIST}; do
  if ! [[ ${KEEP[*]} =~ "$a" ]]; then
    echo "Deleting inactive (over ${AGE} days) account and home directory: $a"

    # delete user
    /usr/bin/dscl . delete "$a" > /dev/null 2>&1

    # delete home folder
    /bin/rm -r "$a"
    continue
  else
    echo "SKIPPING $a"
  fi
done

echo "Cleanup complete"
exit 0

Poseiden
New Contributor III

@Chris

Thanks for the help, I'll probably have to get a book about this stuff!

Thanks @mscottblake! This worked flawlessly!

mscottblake
Valued Contributor

@Poseiden I'm glad that works for you. I think the best thing about it is that to change the duration, you just need to change parameter 4 in your policy. Therefore the same script can be used in different policies where requirements are different.

Poseiden
New Contributor III

@mscottblake

I changed the duration to 30 days, matching our Windows group policy. I'll be using this in lab environments as well!

gmillercmsd12
New Contributor

@Poseiden I am new to Casper and the need use of scripts. Can you send me your "delete accounts older than X days" script with some normal data entered. I am having trouble following/figuring out how to enter the users in the "keep" area and if I need to adjust anything in the $4 area. Thanks

mscottblake
Valued Contributor

@gmillercmsd12 The script he's referencing can be found above. Copy that script into your JSS. Then you can change the KEEP variable to KEEP=("/Users/Shared" "/Users/AnotherUser"). You can change the default age with the AGE variable. That's in days. Alternatively, you can pass a number into parameter 4 in your policy to customize the delay before they are deleted.

gmillercmsd12
New Contributor

@mscottblake thanks for the clarification.

jameslnorris
New Contributor

Thanks for this, @mscottblake! Exactly what I was looking for to clean up these 128gb Airs with 100 student user folders on them without deleting frequent users.

richeames
New Contributor III

I was just testing the script posted by@mscottblake and I'm not sure if I did something wrong. I have the script, changed it to 5 days to test deleting some older Users on a machine. The policy is set in Self Service and available with JSS login credentials matching jamf_admins or help_desk. I logged into the computer as a student standard account then launched Self Service. Logged into Self Service as a user in jamf_admin so I could see and run the policy. Once the policy ran it kept the users I wanted, Shared and local admin but it deleted all the local user accounts including the student one I was logged in as, I watched the Desktop items disappeared. I logged out of the user, logged in as local admin and checked System Preferences, the only accounts left were the ones in the script I excluded.
What I was hoping is that it would leave the current logged in user alone. Maybe I misinterpreted the script but I would think the current logged in user would have a modified date of today so it would ignore current logged in user.

Is there a way to add "Users/~CurrentUser" as a user folder not to delete.

Thanks,
Rich

Johnny_Kim
Contributor II

@richeames Sounds like you age date is not set properly. What do you have set in Parameter 4 in the script options?

richeames
New Contributor III

Screenshot from script. Age=5

3fc7dd9849d247dcaabe143e788f653b

Thanks,
Rich

Johnny_Kim
Contributor II

@richeames

This is the script I'm using. The 14 in 'mtime +14' are the days. change that accordingly and accounts with a user ID less than of 1000 are local accounts are not deleted. Give this a shot.

#!/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
find /Users -type d -maxdepth 1 -mindepth 1 -not -name "*.*" -mtime +14 | grep "$a";
if [[ $? == 0 ]]; then
dscl . delete /Users/"$a"; #delete the account
rm -r /Users/"$a"; #delete the home directory
fi
done

TechSpecialist
Contributor

Hi all,

Five years later... on Catalina.

I'm trying to get this script running. I'm currently having it set up like this:

"#----Variables----

DEFAULT VALUE FOR "AGE" IS SET HERE

AGE=1 # Delete /Users/ folders inactive longer than this many days

CHECK TO SEE IF A VALUE WAS PASSED IN PARAMETER 4 AND, IF SO, ASSIGN TO "AGE"

if [ "$4" != "" ]; then AGE=$4
fi

KEEP=("/Users/Shared" "/Users/user1" "/Users/user2") # User folders you would like to bypass. Typically local users or admin accounts.

--End variables--

Delete Inactive Users

if [[ ${UID} -ne 0 ]]; then echo "$0 must be run as root." exit 1
fi

USERLIST=$(/usr/bin/find /Users -type d -maxdepth 1 -mindepth 1 -not -name "." -mtime +"${AGE}")

echo "Performing inactive user cleanup"

for a in ${USERLIST}; do if ! [[ ${KEEP[*]} =~ "$a" ]]; then echo "Deleting inactive (over ${AGE} days) account and home directory: $a"

# delete user /usr/bin/dscl . delete "$a" > /dev/null 2>&1

# delete home folder /bin/rm -r "$a" continue else echo "SKIPPING $a" fi
done

echo "Cleanup complete"
exit 0"

then in the logs it reports like this:

Script exit code: 0
Script result: Performing inactive user cleanup
SKIPPING /Users/Shared
Cleanup complete

So I don’t understand why it is not saying “SKIPPING’ /Users/Shared /Users/user1 /Users/user2

And I don’t understand why it doesn’t delete any of the other users that should have been deleted.

I have the time currently set to 1 as I want to test it with an account I created yesterday.

Does this script need revisiting because of Catalina? Any suggestions?

Mauricio
Contributor III

And I don’t understand why it doesn’t delete any of the other users that should have been deleted.

One possible cause is SIP.
If you run your script in a "verbose" mode you will see some entries like this:

rm: /Users/targetuser/Pictures: Operation not permitted
rm: /Users/targetuser/Library/Application Support: Operation not permitted
rm: /Users/targetuser/Library/Preferences: Operation not permitted
rm: /Users/targetuser/Library/Caches: Operation not permitted
rm: /Users/targetuser/Library: Operation not permitted
rm: /Users/targetuser: Operation not permitted

We are working on a local/otherAD accounts migration to our AD system and we had to add several PPPC in our MDM to support/bypass those restrictions.

Another possible solution is to use sysadminct.

sysadminctl -deleteUser <user name> [-secure || -keepHome] (interactive || -adminUser <administrator user name> -adminPassword <administrator password>)

Does this script need revisiting because of Catalina?

Answer: YES, anything from 10.13.2 to cover your base.