script to rename computer name (letter of first name and last name)

tomatoes27
New Contributor II

I know there's a number of discussion on it but haven't quite found the correct one. I'm trying to have a policy that will call a script to change computer name based upon users first letter and last name. Here's the workflow:

-User will enroll via DEP. Enter in John Smith
-DEP will look for SplashBuddy (SB) to run.
-SB will do it's thing and will trigger all install packages.
-one of the policies to kick off is to take the information set for the User name and change computer name to jsmith-mbp on the local macbook.

Any help would be appreciated. Thank you

1 ACCEPTED SOLUTION

boberito
Valued Contributor

So you'd have to write a script that does that. You could put that script potentially in a payload-free package or a script that runs with a policy.

#!/bin/sh

#gets current logged in user
getUser=$(ls -l /dev/console | awk '{ print $3 }')

#gets named
firstInitial=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print tolower($2)}' | cut -c 1)
lastName=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print tolower($3)}')
computerName=$firstInitial$lastName"+mbp"

#set all the name in all the places
scutil --set ComputerName "$computerName"
scutil --set LocalHostName "$computerName"
scutil --set HostName "$computerName"

View solution in original post

22 REPLIES 22

boberito
Valued Contributor

So you'd have to write a script that does that. You could put that script potentially in a payload-free package or a script that runs with a policy.

#!/bin/sh

#gets current logged in user
getUser=$(ls -l /dev/console | awk '{ print $3 }')

#gets named
firstInitial=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print tolower($2)}' | cut -c 1)
lastName=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print tolower($3)}')
computerName=$firstInitial$lastName"+mbp"

#set all the name in all the places
scutil --set ComputerName "$computerName"
scutil --set LocalHostName "$computerName"
scutil --set HostName "$computerName"

View solution in original post

I like this! I modified this a bit to add the initials of the client company, an "M" for Mac, and then the user's first and last initials. These are all separated by a dash... PC-M-HI. Company: Pretend Company  Computer type: Mac User first and last name: Howie Isaacks. I set the "PC-M" to be in all caps, but I wanted everything to be in caps so I changed the command from "tolower" to "toupper ".

Asnyder
Contributor III

This is what I use with my DEP setup. Not that you can't use underscores "_" in the host name. This is why I have hostname and hostname2. This will also add the mac address at the end in case of duplicates. Occassionally at my school we have same first initial and last name so that prevents duplicates.

Just place the script in a policy and call it using

jamf policy -event yourtrigger
#!/bin/bash
##########################################################################################
# Computer Naming Script

#Set the hostname

# figure out the user
user=$(python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')

#figure out the user's full name
name=$(finger "$user" | awk -F: '{ print $3 }' | head -n1 | sed 's/^ //' )

# get first initial
finitial="$(echo "$name" | head -c 1)"

# get last name
ln="$(echo "$name" | cut -d   -f 2)"

#Get Mac
mac=`networksetup -getmacaddress Wi-Fi | awk '{ field = substr($3,10,8) }; END{ print field }' | sed s/://g`


# add first and last together
un=($ln"_"$finitial"_"$mac)

un2=($ln"-"$finitial"-"$mac)

# clean up un to have all lower case
hostname=$(echo "$un" | awk '{print tolower($0)}')
hostname2=$(echo "$un2" | awk '{print tolower($0)}')

echo $hostname

sudo scutil --set HostName $hostname2
sudo scutil --set LocalHostName $hostname2
sudo scutil --set ComputerName $hostname
dscacheutil -flushcache

bburdeaux
Contributor II

We do something similar, but use another AD field to fill in the campus the person is at as well(mapped to the Department field in JamfPro), so we pull the info from the User and Location section using the API.

#!/bin/sh

jssUser=$4
jssPass=$5
jssHost=$6

serial=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformSerialNumber/{print $4}')

username=$(/usr/bin/curl -H "Accept: text/xml" -sfku "${jssUser}:${jssPass}" "${jssHost}/JSSResource/computers/serialnumber/${serial}/subset/location" | xmllint --format - 2>/dev/null | awk -F'>|<' '/<username>/{print $3}')
dept=$(/usr/bin/curl -H "Accept: text/xml" -sfku "${jssUser}:${jssPass}" "${jssHost}/JSSResource/computers/serialnumber/${serial}/subset/location" | xmllint --format - 2>/dev/null | awk -F'>|<' '/<department>/{print $3}')

if [ "$username" == "" ]; then
    echo "Error: Username field is blank."
    exit 1
elif [ "$dept" == "" ]; then
    echo "Error: Department field is blank."
    exit 1
else

compname=$dept"-"$username"-mac"

/usr/sbin/scutil --set HostName "$compname"
/usr/sbin/scutil --set LocalHostName "$compname"
/usr/sbin/scutil --set ComputerName "$compname"

fi

tomatoes27
New Contributor II

@boberito Thank you for the script. It looks good.

RLim945
New Contributor III

@boberito Great script! Would anyone know how to add to this script so that it can check the type of Mac it is and append the appropriate name?

For John Smith, we use:

JSMITH.PORTABLE for Laptops
JSMITH.DESKTOP for Desktops

Edit: Actually, I'm running into the following error

SCPreferencesSetLocalHostName() failed: Invalid argument

I believe it's because the + symbol is not an accepted character for the Local Host Name?

boberito
Valued Contributor

No idea about that error. It's entirely possible the + isn't allowed, or maybe there's a hidden character like a return character or something. I dunno.

sysctl -n hw.model | cut -d "," -f 1 | tr -d '[0-9]_'

That'll give you the model of the computer

Then you'd need some if or case statements to determine if you want it named portable or desktop.

boberito
Valued Contributor

And looking at the system preferences, sharing. You'll see the Computer Name has a + but the local network name right under it is the name without the plus.

PeterClarke
Contributor II

I just use a "Smart List" with criteria: Model is like Macbook

( = Macbook, Macbook AIR, Macbook Pro ) = Laptop
Anything else is a Desktop…

So Smart Group: Desktop criteria: Model is not like Macbook

This seems like the simplest way to distinguish between Desktops and Laptops…

( unless you need the criteria in a script as part of some other processing… )

tcarlson
New Contributor III

I was able to use boberito's script, at the top, I edited to display/change computer name as firstname lastname. Not a huge issue but the names are lower case, is there a tweak so that I can get the names displayed first letter is capitalized. Thanks in advance.

OOBIDUB
New Contributor

Something like this should work.

firstInitial=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print toupper($2)}' | cut -c 1)

steagle
New Contributor II

@tcarlson - what does your script look like now, either with or without proper capitalization (ideally with)? I'm trying to accomplish the same thing.

hmartinez
New Contributor

I have taken ideas from everyone, but I cannot remove the following error:

Executing Policy Test Computer Name
Running script Computer Name By Hebert...
Script exit code: 0
Script result: SCPreferencesSetLocalHostName() failed: Invalid argument
Rename Successful

My script is:

#!/bin/sh

#gets current logged in user
getUser=$(ls -l /dev/console | awk '{ print $3 }')

#gets named
firstName=$(finger -s $getUser | head -2 | tail -n1 | awk '{print ($2)}')
lastName=$(finger -s $getUser | head -2 | tail -n1 | awk '{print ($3)}')
model=$(sysctl -n hw.model | cut -d "," -f 1 | tr -d '[0-9]_')
computerName=$firstName" "$lastName" "$model
localHostName=$firstName"-"$lastName"-"$model

#set all the name in all the places
echo $ComputerName
/usr/sbin/scutil --set ComputerName "$computerName"
/usr/sbin/scutil --set HostName "$computerName"
/usr/sbin/scutil --set LocalHostName "$localHostName"

dscacheutil -flushcache

echo "Rename Successful"

exit 0

OOBIDUB
New Contributor

I made a couple changes, see if this works for you.

#!/bin/sh

#gets current logged in user
getUser=$(ls -l /dev/console | awk '{ print $3 }')

#gets named
firstName=$(finger -s $getUser | head -2 | tail -n1 | awk '{print ($2)}')
lastName=$(finger -s $getUser | head -2 | tail -n1 | awk '{print ($3)}')
model=$(sysctl -n hw.model | cut -d "," -f 1 | tr -d '[0-9]_')
computerName=$firstName" "$lastName" "$model
localHostName=$firstName"-"$lastName"-"$model

#set all the name in all the places
echo $computerName
/usr/sbin/scutil --set ComputerName "$computerName"
/usr/sbin/scutil --set HostName "$computerName"
/usr/sbin/scutil --set LocalHostName "${localHostName}"

dscacheutil -flushcache

echo "Rename Successful"

exit 0

sdagley
Honored Contributor II

@OOBIDUB Use the code block tag (triple back-tick ```) before and after your script to prevent the forum sofwtare from mangling the display.

SpriteRemix
New Contributor

Hello,

I made some changes, I included the first letter to be capital and the following letters to be lower case.

#!/bin/sh

#gets current logged in user
getUser=$(ls -l /dev/console | awk '{ print $3 }')

#gets named
firstName=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print toupper(substr($2,1,1)) tolower(substr($2,2)) }')
lastName=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print toupper(substr($3,1,1)) tolower(substr($3,2)) }')
model=$(sysctl -n hw.model | cut -d "," -f 1 | tr -d '[0-9]_')
computerName=$firstName" "$lastName"'s "$model"

#set all the name in all the places
echo $computerName
scutil --set ComputerName "$computerName"
scutil --set LocalHostName "$computerName"
scutil --set HostName "$computerName"

echo "Rename Successful"

exit 0

szultzie
Contributor II

hi everyone, hoping someone can help. Im looking to do the exact thing as here, name a computer with a user. my issue is that i get _mbsetuser becuase if i run this policy at enrollment thats the user that is logged in. Is there an easy way to wait till a real user logs in before it runs?

My end result is username-serial number as the computer name. My PreStage is authenticating to my AD (other issue with this part right now) but when it works it passes the AD usernaem and creates a local user with the same name. Id like to name the computer the username-serialnumber, so far in testing i am able to run it after a user is set up and logged in and it does what I want, if i let it sit it gives me _mbsetupuser.

This is a script i put together from various Jamf Nation sources 😃
I am not great at scripting, but i think maybe a check to see if the user is _mbsetupuser and then wait xx seconds and try again until its not?

#!/bin/bash

##get serial number
computerName=$(ioreg -c IOPlatformExpertDevice -d 2 | awk -F" '/IOPlatformSerialNumber/{print $(NF-1)}')


# figure out the user
user=$(python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");')


#set the host name on several places

/usr/local/bin/jamf setComputerName -name "$user-$computerName"
/usr/sbin/scutil --set LocalHostName "$user-$computerName"
/usr/sbin/scutil --set HostName "$user-$computerName"
/usr/sbin/scutil --set ComputerName "$user-$computerName"
/usr/bin/defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName "$user-$computerName"

/usr/local/bin/jamf recon
exit 0

fernandez_payen
New Contributor III

Is there a way to reverse the script for first name last initial?

shaquir
Contributor III

Hi @fernandez.payen ,
Building off of @boberito 's script, you can edit the "cut" filter for your desired name requirement.

| cut -c 1

I put an example to show the what the difference would be:

#!/bin/sh
#gets current logged in user
getUser=$(ls -l /dev/console | awk '{ print $3 }')

#gets named
firstName=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print tolower($2)}')
lastInitial=$(finger -s $getUser | head -2 | tail -n 1 | awk '{print tolower($3)}' | cut -c 1)
#final computer name using First Name and Last initial
computerName=$firstName$lastInitial"+mbp"

#set all the name in all the places
scutil --set ComputerName "$computerName"
scutil --set LocalHostName "$computerName"
scutil --set HostName "$computerName"

tlarkin
Honored Contributor

Python 3 method using dscl with plist output and using plistlib to parse the data. You can do pretty much all the string manipulation you would need with native builtins

>>> import subprocess
>>> from SystemConfiguration import SCDynamicStoreCopyConsoleUser
>>> 
>>> USER, UID, GID = SCDynamicStoreCopyConsoleUser(None, None, None)
>>> 
>>> user_path = "/Users/" + USER
>>> 
>>> cmd = ['dscl', '-plist', '.', '-read', user_path]
>>> proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out, err = proc.communicate()
>>> import plistlib
>>> plist = plistlib.loads(out)
>>> realname = plist['dsAttrTypeStandard:RealName']
>>> print(realname[0])
Tom Larkin
>>> name_list = realname[0].split()
>>> print(name_list)
['Tom', 'Larkin']
>>> fname = name_list[0]
>>> print(fname)
Tom
>>> print([c for c in fname])
['T', 'o', 'm']
>>> print([c for c in fname][0])
T

Shell is probably a bit more of a simple approach, but using the dscl output you would deal with more structured data

emily
Valued Contributor III

I realize I'm digging up an old thread but I thought this might help someone who is getting SCPreferencesSetLocalHostName() failed: Invalid argument when trying to set the LocalHostName when changing the computer name. This is due to the local hostname not allowing any special characters. You can do something like the following to strip special characters:
localHostName=$( echo $computerName | tr -dc '[:alnum:] ' )

Then for the line that sets the local hostname use that modified variable instead. So for a computerName of first.last+mbp you'd get a local hostname of firstlastmbp.

howie_isaacks
Valued Contributor

Here's what I came up with. I tested it on my iMac, and it worked exactly as intended.

#!/bin/sh

#Rename the Mac using the first and last initial of the user's name. Before using this script, replace "XX" in line 12 with the client company's initials

#Who is the current logged in user?
currentUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`
echo $currentUser

#Generate computer name - Replace "XX" with the client company's initials
firstInitial=$(finger -s $currentUser | head -2 | tail -n 1 | awk '{print toupper ($2)}' | cut -c 1)
lastInitial=$(finger -s $currentUser | head -2 | tail -n 1 | awk '{print toupper ($3)}' | cut -c 1)
computerName=$"XX-M-$firstInitial$lastInitial"

echo $computerName

#Send the computer name to inventory record
scutil --set ComputerName $computerName
scutil --set LocalHostName $computerName
scutil --set HostName $computerName

#Clear the directory service cache then run a current inventory to send the new Mac name to Jamf Pro
dscacheutil -flushcache
/usr/local/jamf/bin/jamf recon