Posted on 10-19-2012 05:40 PM
Miles Leacy and Tom Larkin will be presenting this session on Wednesday, Oct 24 at 1:00 pm. Nelson Classroom (level 8)
This session is intended for administrators that are already familiar with the basics of bash scripting and would like to add some additional techniques to their toolkit. If you are new to scripting and would like to find out what it's all about, you may be interested in the other scripting session: Killer Ninja Script Monkey 101: Introduction to Bash Scripting in Dowling Studio (level 9) on Tuesday, Oct 23 at 3:45 pm.
Topics we'll be discussing include...
Link to session schedule and descriptions:
http://www.jamfsoftware.com/events/user-conferences/jamf-nation-user-conference-2012/sessions
Posted on 10-24-2012 10:49 AM
The most life changing thing I've learned about the command line is that "Ctrl + L" does the same thing as "clear" and doesn't fill up your history with entries you don't need.
Posted on 10-25-2012 06:37 PM
Hi Everyone,
So here are some examples of some of the logic we went over, in no particular order.
Case statement logic:
#!/bin/bash
# get wifi MAC address based on OS version
OSvers=$(/usr/bin/sw_vers -productVersion)
case ${OSvers} in
10.6*) service="Airport" ;;
10.7*) service="Wi-Fi" ;;
10.8*) service="Wi-Fi" ;;
esac
# command to grab mac address
wirelessMAC=$(/usr/sbin/networksetup -getmacaddress ${service} | /usr/bin/awk '{ print $3 }')
/bin/echo "<result>${wirelessMAC}</result>"
if/then logic
JAMFcheck="/usr/sbin/jamf"
# now check if it exists
if [[ -e $JAMFcheck ]]
then /bin/echo "JAMF binary present, continuing as planned..."
else /bin/echo "JAMF binary is not present, we need to halt"
exit 55
fi
For loop logic
#!/bin/bash
# check for local admin accounts
userList=$(dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }')
for u in ${userList} ; do
if [[ `dscl . read /Users/${u} GroupMembership | grep -c "admin"` == 1 ]]
then echo "<result>has admin</result>"
else echo "no admin here"
fi
done
Something we did not cover, *bonus*, is user interaction via invoking apple script.
#!/bin/bash
# user apple script and bash to get input from user to update asset tags in the JSS
# by Tom Larkin
# proof of concept, no warranty given, use at own risk
# get usr input from Apple Script and try to redirect output back into bash and user recon to update the JSS
/usr/bin/osascript <<-AppleScript
tell application "Finder"
activate
display dialog "Enter your asset number" default answer "Enter your asset tag number here"
set theAnswer to (text returned of result)
set cmd to "/usr/sbin/jamf recon -assetTag " & theAnswer
do shell script cmd
end tell
AppleScript
exit 0
exit status with logging
diskCapacity=$(/bin/df -h | /usr/bin/awk '/disk0s2/ { print $5 }' | /usr/bin/sed "s/%//")
if [[ ${diskCapacity} -le 80 ]]
then /bin/echo "boot volume has at least 20% free space"
else /bin/echo "boot volume does not have enough free space" >> /var/log/jamfenrollment.log
exit 1
fi
If there are any other requests on what we went over please post them here. Also, Miles and I would appreciate any feedback, comments, and suggestions on how to improve this session. Thanks again for all the positive feed back and for coming out to share your story with us.
Thanks,
Tom
Posted on 10-29-2012 06:26 AM
Tom,
Great session I really picked up a lot of little tricks to make my scripts better, only thing I would change is to find a bigger room. Could you post some of the bash internals that you presented at the beginning of the session about manipulating the output to use in place of the sed command.
Thanks
Rob
Posted on 10-29-2012 02:10 PM
Hi Rob,
Thanks for your feedback and attendance. We did not expect that big of a turn out and Miles and I have already tossed a few ideas back and forth to make the next time we do this a better experience. To post the string manipulation I will use one of our examples. Note that Miles and myself did this on purpose sort of to show the progression of how you write scripts.
Take the boot volume free space script as an example:
#!/bin/bash
# Returns the free space on the current boot volume in GB, rounded down to the nearest integer.
free=`diskutil info /|grep "Free Space"|awk '{print $4}'`
echo "<result>"${free%.*}"</result>"
In the beginning, grep is one of your best friends, and often enough you will cat | grep something or grep | awk something and a lot of times that is not even needed. Needless to say, you still get the desired results. Then, many times you will see someone further use sed to substitute text, or parse and manipulate strings. Also, a completely valid method of doing so. I can optimize this script by knocking out the grep, like so:
$ diskutil info / | awk '/Free Space/ { print $4 }'
372.7
Now if I want to strip that fraction off and only deal with whole numbers you could use a math binary, or pipe to a sed and do so, or you can also use bash internals. The idea is that bash can do things internally more efficient and use less resources, but of course like I mentioned before, there are always 10 ways at least to do something, if not 100s.
So, now I can assign that command to a variable in my interpreter, like so:
t-lark:~ tlarkin$ free=`diskutil info / | awk '/Free Space/ { print $4 }'`
t-lark:~ tlarkin$
t-lark:~ tlarkin$ echo $free
372.7
Now if I want to exclude the decimal and everything after it, I can do so by echoing out the variable this way:
$ echo ${free%.*}
372
A lot of these internals can be leveraged and in my humble opinion a lot easier (and faster) than learning sed or awk. Not to take away from either binary, since sed and awk are very powerful parsing tools, and I do recommend everyone eventually learn them if they need to. I hope this helps answer your questions and I can post more examples when time allow.
Thanks again for coming out to the JNUC and attending our session, we greatly appreciate it.
-Tom
Posted on 10-31-2012 07:59 AM
Tom,
Thanks those were the examples that I was looking for. Definitely already looking forward to the #JNUC next year.
Thanks for all your help.
Rob
Posted on 10-31-2012 11:33 AM
The other string manipulation we demoed was echoing out a range of characters from a string. So for example:
bash-3.2$ mystring="1234567890"
bash-3.2$
bash-3.2$ echo ${mystring}
1234567890
bash-3.2$
bash-3.2$ echo ${mystring:5:10}
67890
So, this is another way to just use bash internals to print out a range of characters in a string.
Hope this also helps you.
Thanks,
Tom