Skip to main content

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

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


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


@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/


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


@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

  • @Chris



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



    Thanks @mscottblake! This worked flawlessly!


    @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.


    @mscottblake



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


    @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


    @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.


    @mscottblake thanks for the clarification.


    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.


    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


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


    Screenshot from script.
    Age=5





    Thanks,
    Rich


    @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

    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?


  • 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> g-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.


    Reply