Script help

grecopj
Contributor

Hi All,

I have a policy that runs on logout that runs a script to delete all users except the local admin user. I thought this was working fine but I was told by some students that there work was still there when they logged back into the machine. I went back and checked the logs and it indeed shows the policy as failing.

Here is the script that runs:

for dir in /Users/* do if [ ! "$dir" = "/Users/admin" ] && [ ! "$dir" = "/Users/viscom" ] && [ ! "$dir" = "/Users/Shared" ] ; then echo ${dir} rm -R $dir dscl . -delete $dir fi done

exit 0

The error that is showing in the log:

Executing Policy Delete User Script...
Running script Delete User on Logout...
Script exit code: 0
Script result: /Users/pereve DS Error: -14009 (eDSUnknownNodeName) delete: Invalid Path

Any help would be greatly appreciated as I am not very well versed in this.

Thanks,
Pete

1 ACCEPTED SOLUTION

jturnage
New Contributor III

We use this script. HINT!!!! macadamia is the name of our local admin account. so replace macadamia with the short name of your local admin account in the exempt variable and it should work.

#!/bin/bash

# Clear all non local admin accounts script
# Script is based off work at the following webpage:
# http://www.macos.utah.edu/documentation/authentication/dscl.html

# Author: r.purves@arts.ac.uk

# Set up needed variables here

macname=$( scutil --get ComputerName | awk '{print substr($0,length($0)-3,4)}' )
OIFS=$IFS
IFS=$' '

# Special section to set up globally exempted user accounts
# You can add more accounts here separated by a space

exempt=( macadmin )

exempt[$[${#exempt[@]}]]=echo $username

# Find exempt array length

tLen=${#exempt[@]}

# Delete accounts apart from those in the exclusion array

# Read the user account from /users in order.

for Account in `ls /Users`
do

# Does the flag file exist? If so, delete it.

if [ -f /var/tmp/adminexempt ]; then rm /var/tmp/adminexempt fi

# Loop around the exemption array to check current user.

for (( i=0; i<${tLen}; i++ )); do

# Create the exemption flag file if account matches. We do this because of BASH's local variable limitation.

if [ "${exempt*}" == $Account ]; then touch /var/tmp/adminexempt fi

done

# If exempt file doesn't exist, delete the account.

if [ ! -f /var/tmp/adminexempt ]; then dscl . delete /Users/$Account > /dev/null 2>&1 rm -rf /Users/$Account fi

# Read the next username.

done

# Let's set IFS back to the way it was.

export IFS=$OIFS

# Clean up any left over flag files

if [ -f /var/tmp/adminexempt ];
then rm /var/tmp/adminexempt
fi

# All done!

exit 0

View solution in original post

20 REPLIES 20

stevewood
Honored Contributor II
Honored Contributor II

The problem you're running into is that your dscl command is trying to delete the full home folder path. If you echo out $dir you'll see that the variable is /Users/<username>, so dscl is trying to do the following:

dscl . -delete /Users/<username>

You need to get just the <username> portion of the dir variable. There are a few ways to do this, but I'll show you using cut:

myUser=`echo ${dir} | cut -c8-`

You'd then use this to delete the user from dscl:

dscl . -delete $myUser

Your entire script would look like this:

for dir in /Users/*
    do
        if [ ! "$dir" = "/Users/admin" ] && [ ! "$dir" = "/Users/viscom" ] && [ ! "$dir" = "/Users/Shared" ] ; then 
            echo ${dir}
            rm -R $dir 
            myUser=`echo ${dir} | cut -c8-`
            dscl . -delete $myUser 
        fi 
    done

exit 0

I'm cheating using cut because you know the /Users/ portion is a fixed 7 characters long.

Test that out and if it doesn't work, post back and let us know.

grecopj
Contributor

Steve,

Thank you posting back. I created a new policy and added the new script as you provided but I am still getting this error. Tried with two different users.

Script result: /Users/grecopj DS Error: -14009 (eDSUnknownNodeName) delete: Invalid Path

Script result: /Users/aaviscoma DS Error: -14009 (eDSUnknownNodeName) delete: Invalid Path

When logged in as the admin, viscom, the script completes.

mm2270
Legendary Contributor III

To my knowledge, dscl requires the path to the item you're looking to delete, at least in the sense that you need /Users/ or /Groups/, /Computers/ etc. So dscl . -delete /Users/username should actually be correct. I just did a quick test and see that dscl . -delete username fails.

$ sudo dscl . create /Users/mytestuser
$ dscl . list /Users | grep "mytestuser"
$ mytestuser
$ sudo dscl . delete mytestuser
$ delete: Invalid Path
$ <dscl_cmd> DS Error: -14009 (eDSUnknownNodeName)

$ sudo dscl . -delete /Users/mytestuser
$

Edit: Its possible dscl is not liking how the full string is set up. You may need to either:
a) quote the ${dir} string, like dscl . -delete "${dir}"
or
b) chop it down to the username only as @stevewood mentioned, and then recombine it with /Users/, like

myuser=$(echo ${dir} | cut -c8-)
dscl . -delete /Users/${myuser}

Which seems really silly, but its possible its seeing something it doesn't like in that full path that gets passed to dscl.

stevewood
Honored Contributor II
Honored Contributor II

Ah, Mike is correct. Sorry about that wild goose chase, I guess I thought I had used just the user name in the past.

GabeShack
Valued Contributor III
#!/bin/sh

for home in $(ls /Users | grep -v xxxxxx | grep -v Shared | grep -v xxxxxx | grep -v xxxxxx | grep -v xxxxx | grep -v xxxxx | grep -v xxxxx | grep -v xxxxx | grep -v xxxxx | grep -v xxxxx | grep -v xxxxx | grep -v xxxxx)
do
sudo rm -rf /Users/$home
done

So this is my script with all the specific users that I exclude x'ed out. Not sure if this helps..
I use this to remove the student AD accounts on the computers when they start to fillup a drive.
Gabe Shackney
Princeton Public Schools

Gabe Shackney
Princeton Public Schools

grecopj
Contributor

Mike & Steve,

I changed the lines that Mike made mentioned to.

myUser=echo ${dir} | cut -c8- dscl . -delete $myUser

to

myuser=$(echo ${dir} | cut -c8-)
dscl . -delete /Users/${myuser}

Still getting this error

Script result: /Users/aaviscoma DS Error: -14009 (eDSUnknownNodeName) delete: Invalid Path

Now, sorry for not mentioning this earlier if this makes a difference. All these users are authenticating via AD. If I go back into the User's folder, I don't see those accounts.

mm2270
Legendary Contributor III

That makes sense (that you don't see the home folders) Your script first deletes the home folder and then tries to delete the actual local directory services account, which is what its failing on.
I have to say, I'm not sure why you're seeing this error. The dscl delete syntax seems correct from what I can tell, but obviously something's amiss that none of us are seeing.

Silly question, but can you run a test where you reverse the order? Try deleting the ds account with dscl . -delete first, then delete the Home folder? It should not make a difference at all, but stranger things have happened.

Edit: on one of the Macs this is erroring on, can you run the following to see what it reports?

dscl . list /Users

grecopj
Contributor

Mike,

Here is the what i get when I run that

HA14225:~ viscom$ dscl . list /Users
_amavisd
_appleevents
_appowner
_appserver
_ard
_assetcache
_atsserver
_avbdeviced
_calendar
_ces
_clamav
_coreaudiod
_coremediaiod
_cvmsroot
_cvs
_cyrus
_devdocs
_devicemgr
_dovecot
_dovenull
_dpaudio
_eppc
_ftp
_geod
_installassistant
_installer
_jabber
_kadmin_admin
_kadmin_changepw
_krb_anonymous
_krb_changepw
_krb_kadmin
_krb_kerberos
_krb_krbtgt
_krbtgt
_launchservicesd
_lda
_locationd
_lp
_mailman
_mcxalr
_mdnsresponder
_mysql
_netbios
_netstatistics
_networkd
_postfix
_postgres
_qtss
_sandbox
_screensaver
_scsd
_securityagent
_serialnumberd
_softwareupdate
_spotlight
_sshd
_svn
_taskgated
_teamsserver
_timezone
_tokend
_trustevaluationagent
_unknown
_update_sharing
_usbmuxd
_uucp
_warmd
_webauthserver
_windowserver
_www
_xcsbuildagent
_xcscredserver
daemon
nobody
root
viscom
HA14225:~ viscom$

mm2270
Legendary Contributor III

Ok, looks pretty standard. Is the user account the script was supposed to delete listed there? Is it "viscom" in this example?
I only had you do that to make sure the account records were actually appearing in the /Users/ section and not somehow appearing somewhere else.

grecopj
Contributor

viscom is the admin account which I ran this. Past accounts like grecopj and aaviscoma are not in there.

mm2270
Legendary Contributor III

Oh? So, I'm confused then. The script is erroring, but it removed the accounts? Both the home folder and the accounts in directory services? Is that what you're saying?

dbrodjieski
New Contributor III

Hi grecopj-
Do you have it set to create mobile account at login? Unless you do, I don't believe that a local dscl record will be generated for AD authenticated accounts. By chance are the users seeing contents of what is on their network home folder?

grecopj
Contributor

Dan,

No, Create mobile account is not checked in my binding settings. Force local home directory is checked.

I am not sure if they are seeing what is on their network home folder.

Again, I thought this was all working. Had an instructor come to me today that students wanted to know why there items were still on the desktop when we told them they would be deleted on log out.

Mike,

Just to make sure I was not crazy. I removed the one machine from the scope of the policy. Logged in with a couple of AD accounts. Went back into the user folder and they were still there. So yes, seems to delete the accounts but still get the error in the log.

nessts
Valued Contributor II

looks to me that the home directory exists, but the local account does not and that is the error that is getting reported.
So maybe you should run ID or a list/read of that account prior to trying to delete it.
Of course I spent all of 30 seconds looking at all of this so i could be all wet.

dbrodjieski
New Contributor III

So in your case, I think that while the local home folder is being created in /Users/, the dscl record is not, and therefore you are getting the error when trying to remove the dcsl record. Just because a folder exists in /Users/ does not mean that the system has a user record. If you log in as one of the users, and then while still logged in, run

dscl . list /Users

do you see that user in the list?

grecopj
Contributor

When logged in as one of the AD users and the above command is run I do not see it listed.

grecopj
Contributor

So, I also tried the script that Gabe posted.

#!/bin/sh

for home in $(ls /Users | grep -v viscom | grep -v Shared)
do
sudo rm -rf /Users/$home
done

It too removes the folder from the users folder but still returns the error under my policy.

Script result: /Users/aaviscoma DS Error: -14009 (eDSUnknownNodeName) delete: Invalid Path

dbrodjieski
New Contributor III

You don't see the user listed because it's not creating a dscl record, therefore, you do not need to run the command to remove the dscl record, only the user's home folder. You are receiving the error because it's trying to delete something that doesn't exist.

jturnage
New Contributor III

We use this script. HINT!!!! macadamia is the name of our local admin account. so replace macadamia with the short name of your local admin account in the exempt variable and it should work.

#!/bin/bash

# Clear all non local admin accounts script
# Script is based off work at the following webpage:
# http://www.macos.utah.edu/documentation/authentication/dscl.html

# Author: r.purves@arts.ac.uk

# Set up needed variables here

macname=$( scutil --get ComputerName | awk '{print substr($0,length($0)-3,4)}' )
OIFS=$IFS
IFS=$' '

# Special section to set up globally exempted user accounts
# You can add more accounts here separated by a space

exempt=( macadmin )

exempt[$[${#exempt[@]}]]=echo $username

# Find exempt array length

tLen=${#exempt[@]}

# Delete accounts apart from those in the exclusion array

# Read the user account from /users in order.

for Account in `ls /Users`
do

# Does the flag file exist? If so, delete it.

if [ -f /var/tmp/adminexempt ]; then rm /var/tmp/adminexempt fi

# Loop around the exemption array to check current user.

for (( i=0; i<${tLen}; i++ )); do

# Create the exemption flag file if account matches. We do this because of BASH's local variable limitation.

if [ "${exempt*}" == $Account ]; then touch /var/tmp/adminexempt fi

done

# If exempt file doesn't exist, delete the account.

if [ ! -f /var/tmp/adminexempt ]; then dscl . delete /Users/$Account > /dev/null 2>&1 rm -rf /Users/$Account fi

# Read the next username.

done

# Let's set IFS back to the way it was.

export IFS=$OIFS

# Clean up any left over flag files

if [ -f /var/tmp/adminexempt ];
then rm /var/tmp/adminexempt
fi

# All done!

exit 0

grecopj
Contributor

Joshua, thank you very much for the script! Exactly does the job. This seems to be working well with my test machines. Will switch it over to my lab machines this week. Nice to have it so I can add certain users to the exempt list. Helps with faculty machines where I want to keep their home folders to a particular machine. Mostly for my adjunct work stations. While I know there are other options, this fits the bill for me.

Also want to thank all that responded. Being a one man shop where I am forced to where several hats, it's great to know that I have such a valuable resource that I can turn to.

Thanks again to all!!