shell script

Fastest ways to get a Mac’s serial number from the command line

Getting a Mac’s serial number is often a task that is prelude to other work in a shell script. I was toying around with a script and noticed that it was taking longer than I liked on the client machines, but really fast on my machine. Looking around the web I found a great page that listed the times it took another person to query for the Serial Number, on jaharmi.com. It made me stop and do some time test for myself.

I started timing each component to track down the culprit. Turns out the serial number logic was taking over  a second to run to run the first time it was called, but then was dropping dramatically on consecutive calls. I decided to do some time test myself, first to see if Jaharmi’s post was still relevant (it was from 2008) and second to see if I couldn’t tweak it further to gain a few more fractions of a second improvement.

First was what the script had at first, using system_profile. When I tested just using system_profile I found that the first run of the script would take over 1 second on my Mid-2010 MacBook Pro. The next few times I ran it the time dropped from 1.722 seconds down to as low as 0.226 seconds.  The trimmed mean for running it five times was 0.227 seconds.

system_profiler SPHardwareDataType | grep "Serial Number" | awk '{ print $4; }'

Next I took the ioreg approach, first off what Jaharmi had posted…

ioreg -l | awk '/IOPlatformSerialNumber/ { split($0, line, "\""); printf("%s\n", line[4]); }'

But this took even longer!  The trimmed mean time for this was 0.470 seconds.  That would definitely not do.  However, I still felt that ioreg should return a better time than system_profiler, something in my gut told me that.  So I took a closer look at the script and modified it to return a smaller data set before sorting it.

ioreg -c IOPlatformExpertDevice -d 2 | awk '/IOPlatformSerialNumber/ { split($0, line, "\""); printf("%s\n", line[4]); }'

Now we’re cooking.  This returned a trimmed mean time of 0.007 seconds. I tried tweaking it a bit more with a different sorting logic to see if this could be dropped even further. But alas, it didn’t really make much of a difference when dealing with thousandth’s of a second. I ended up using this code…

ioreg -c IOPlatformExpertDevice -d 2 | grep SerialNumber | awk -F "\"" '{print $4}'

… as it required less code to get the same speed result. I’m now adding this to my useful unix file for future reference.

’till next time

Turn off Wi-Fi via shell script

Need to send a Shell Script to disable the wi-fi network?  No problem!  Have multiple types of machines that may have different device ID’s for the wi-fi?  No problem!

#!/bin/bash

# By Chris
## This will send a power-down to the Wi-Fi Device.
## Tested on 10.8.2 with single Wi-Fi device/hardware.

## First we get the Wi-Fi device name.  We are not assuming it is en1.
# We do this by listing all the hardware on the device, then only showing the line of and immediately following "Wi-Fi".
# Then do a quick second grep to only show the line of the Wi-Fi setting with the "Device" tag.
# We then cut out the first part of the entries and keep with is on the right side (of the ":".
# And finaly we strip out the extra space (to be neat).

WiFiDev="`networksetup -listallhardwareports | grep -A 1 "Wi-Fi" | grep -C 0 "Device" | cut -d ":" -f 2 | tr -d " "`"

# echo $WiFiDev

## Now turn it off.

networksetup -setairportpower $WiFiDev off

echo "Turning off the port at $WiFiDev"

exit 0
till next time

Set Proxy on all available network services

When you want to set the proxy on all available network services (say with JAMF’s Casper Suite at imaging time?)

#!/bin/bash

## A few variables we'll need for later

ProxyURL=http\:\/\/foo\/bar\.pac
declare -a NetServs

# Dealing with IFS as we need to alter it to avoid space issues.
OrigIFS=$IFS
IFS=$'\n'

#Define what Network Services are available.
NetServs=( `networksetup -listallnetworkservices | cut -d "." -f 2-` )

# Go through each network service and set the autoproxy.

for NetServ in ${NetServs[*]}; do
networksetup -setautoproxyurl "$NetServ" $ProxyURL
echo "$NetServ" is now set to use the proxy at $ProxyURL
done

exit 0

Enjoy.

till next time

How to Remove Symantec Endpoint Protection 11 (SEP11) with the Casper Suite

Symantec Endpoint Protection 11’s removal is never perfect, few software titles are when you remove or install at the Enterprise level, there’s always a need for further testing and refining.  At the current time I have come up with this method for removing Symantec Endpoint Protection and it seems to work fair enough.  There may be a better way, but this way works for my purpose.

First go to Symantec’s Mac Removal page and download the SymantecRemovalTool from the bottom of the page, not the one that comes up on the top of the page.  Create a folder in the Library/Application Support folder with your business’ name (I use this as a location for storing files and such that can be used in scripts).  Alternatively you could put it in the /tmp folder if you want it to be erased after the reboot.

Now copy the SymantecRemovalTool folder you downloaded (as a zip) into that folder.  Launch Composer and drag the /Library/Application Support/businessname/SymantecRemovalTool folder into Composer.  Let Composer do it’s thing and see the copied files.  Close up Composer and all your windows and move on to the script part.

Launch your favorite shell script editor (XCode, TextEdit, whatever) and put this in the file…

#!/bin/sh
/Library/Application\ Support/businessname/SymantecRemovalTool/SymantecRemovalTool.command / -q

… save the file as SymantecRemovalScript.sh.  Fire up the terminal and make that file executable (chmod +X SymantecRemovaScript.sh).  Launch Casper Administrator and add the script you just made and the package you made from the SymantecRemovalTool folder.

Create a Policy that installs the package, then runs the script after installation.  You can also add the Anti-Virus installer that you are using to replace Symantec with.  I gave a notice that their anti-virus had changed and requested them to reboot.  If nobody was logged in then I had the machine do an automatic restart.

You should be set for the action, but my inventory seemed to not update (though I checked update inventory).  I made three Smart Computer groups to watch this and run an update.  The first group is the Group of computers that still have Symantec Endpoint Protection on them.  The second group had the new Anti-Virus on them, and the third group had both installed.

On the first group you assign the removal/replacement policy.  On the third group (the both group) you assign an update inventory policy.  The second group (new AV) you do nothing as they should all be happy.

Alternate Option:  postinstall script

You should be able to use the postinstall script to launch the SymantecRemovalScript.sh from the installer or even run the script from the postinstall, I tried both and neither worked.  The packages say it installed, but the postinstall script didn’t run.  It should have.  Your mileage may vary.  I found a work around and used that.  Let me know if it works for you as it would remove the need for the script to be uploaded separately.

Till next time.