Apple Admin Scripting For Beginners
Apple Admin Scripting For Beginners
If you’ve tried your hand at scripting before and found yourself floundering, there’s probably a reason for that:
most tutorials jump directly into providing you with scripts to memorize that may or may not make sense to
you, before they even explain what scripting is and why it’s a good idea to learn some.
And getting started is easy, as long as you can understand how and why scripting works before trying to
memorize strings of commands.
Why do we script?
You can accomplish what looks like a complex feat with only four commands.
Using an MDM such as Jamf Pro, we can automate this command to all computers with a simple one-line
command: open, along with the location of the file.
Interpreters
Don't know what those are? Actually, you do!
You've already been using interpreters for years. The most common
interpreters are Windows Explorer and Mac Finder. Their job is to interpret your
mouse clicks and keyboard commands into computer actions. If you click a file,
Terminal is where Apple
both Windows Explorer and Mac Finder interpret that click as you wanting to
users run their scripts.
select a file. Double-click; they interpret that you want to open a file.
Understanding how
Terminal works helps you
However, not all interpreters will interpret your actions the same way. For demystify scripting.
example: if you select a file in Explorer and hit ENTER, it opens the file. If you do
the same on a Mac, it allows you to edit the file name.
Terminal itself isn't itself an interpreter. It's just a window to an interpreter called bash. Your Mac contains multiple
interpreters, but this e-book focuses on bash.
When you open Terminal from the application's utilities folder, it logs you in to an interpreter: bash. Bash is short for
Bourne-AgainSHell. It's a revised version of the interpreter shell (sh) created by Steven Bourne 40 years ago.
How do commands work?
In the simplest sense, commands tell a computer what to do. You can do anything you'd do using the Finder.
For instance, you can open a file by double-clicking on it. Or, you can open the Terminal and use the following
command, replacing the name of the document with anything you currently have on your desktop:
open /Users/jamfwebinar/Desktop/scripting101.docx
How about a web page instead of a file? The open command does that, too. Just tell it the URL and which browser
you want it to open with:
Here's the interactive part: you'll get the most out of this e-book if you open up Terminal and follow along as we go.
Applications > Utilities > Terminal
This seems like a simple exercise, but you will be using the echo command in many different ways as you move
forward with your scripting, so give it a try!
As you can see, the echo command means: repeat what I say.
To really give a command some teeth, you add in an argument: the text inside of the single quotes. The argument
tells the command what to do.
To learn more simple scripts that have more relevance in your day-to-day workflows, you can start with doing basic
things you would do on your desktop. A good practice is to start doing this as a matter of course throughout your
day as you do routine tasks with the Finder, to help you feel more comfortable with scripting.
For example, you already know how to, through Mac Finder:
To create a folder on your desktop named ‘MyStuff,’ in Terminal at the command line, key:
mkdir Desktop/MyStuff
To create a file with content in it, start backwards with the content, and then point (>) the content to where and in
what format you would like that content to be saved, using the usual format for a file location address:
echo "The quick brown fox jumped over the lazy dogs." > Desktop/Quick-Brown-Fox.txt
Put the file in the folder. From the command line, key:
mv Desktop/Quick-Brown-Fox.txt Desktop/MyStuff
One thing about the command line in Terminal is that if you told it to do something, it does it. It doesn’t give you a
confirmation message (unless you told it to).
So, for your peace of mind, check via the Finder to ensure you have a new folder called “MyStuff” and that it
contains the document Quick-Brown-Fox.txt.
You can open the document through Terminal, as well!
Input:
open Desktop/MyStuff/Quick-Brown-Fox.txt
You can delete documents and folders through Terminal, as well, with the rm command.
rm = remove
rm -r = remove recursively
To remove a document, you simply need rm. Try the following in the command line:
rm Desktop/MyStuff/Quick-Brown-Fox.txt
Via the Finder, check the folder, and the Quick-Brown-Fox.txt document should be gone.
rm Desktop/MyStuff
When Terminal cannot or will not do what you ask, you will receive an error message, as you did:
To tell Terminal that you REALLY mean to remove the folder/directory and all contents in it, you need to include
the remove recursively command, or rm -r.
Try it in Terminal, and then check to ensure that the MyStuff folder is gone.
rm -r Desktop/MyStuff
Note: If you want a folder or document to have spaces in it, simply surround the name with quotation marks. For
example, “My Stuff” or “Quick Brown Fox.txt”.
Writing scripts from Terminal Commands
Now, we're going to make a script out of what you have just done in Terminal!
First, download and open a script editor. We like BBEdit, but there are others listed as resources at the end of
this e-book. You can use a text editor, but a free script editor generally offers syntax highlighting: changing colors
of specific parts of script so that you can see at a glance which is which, as well as find and fix any errors. This is
especially helpful in understanding what is going on for those new to scripting syntax, and for troubleshooting. In
this case, commands are blue and arguments are pink.
Always type at the top of each script something called a shebang: called hash + bang #! Followed by /bin/bash, so
that when you use your scripts, Terminal will know to use bash as an interpreter.
#!/bin/bash
Copy and paste each line of commands you have used already into the script editor. Adding blank lines helps to
make it more readable.
Did you blink? You might have missed it! Another good reason to use scripts: they’re fast!
Here’s a fun one to try, this time starting from a script editor to begin with.
#!/bin/bash
echo 'Hello, World!'
sleep 5
echo
echo "Here’s to the crazy ones."
say "Here’s to the crazy ones."
echo "The misfits. The rebels."
say "The misfits. The rebels."
echo "The troublemakers."
say "The troublemakers."
echo "The round pegs in the square holes."
say "The round pegs in the square holes."
echo
exit
As you can see, line three is an echo command with ‘Hello, World!’ echo is blue, and the variables are pink.
The fifth line is sleep 5.
Sleep means pause, and 5 means to pause for 5 seconds.
See what we did there? Now you know what say means.
sleep = pause (should be used in conjunction with an argument for how many seconds)
rm = remove a file
First: we tell computer what the data will be. In this case, type into terminal:
myName=Martin
And then hit ‘enter.’ Always use a variable name that is clear, straightforward and easy to remember for later use.
Then, we tell the computer what to do with the data. Whenever we are going to use a variable, indicate that it is a
variable with the $ symbol. So, you’ll type into terminal:
This practice of defining a variable and then using the variable in a script has many practical uses for your workflow.
One-liners
Here’s another useful command, modified by a variable. Let’s say that you wanted to figure out if a Mac needs an OS
upgrade.
Again: we’re going to work backwards.
First, we need to decide which variable we are going to use — and we’re going to let a command result find it for us.
This will require two new commands (really, one: simple, and then refined):
The sw_vers command tells us information about the macOS: the name of the OS, the version of the OS we're
running, and the build number. If you want only the version, you can write the script with a -productVersion after the
command, and it gives you only what you want.
ProductName: Mac OS X
ProductVersion: 10.14.4
BuildVersion: 18E226
10.14.4
Working from already-existing commands means we don't have to set the variable ahead of time, but we do have
to indicate that it is a variable we are using. You would set up the variable like this:
$( sw_vers -productVersion )
We still have the $ but instead we're using the software version command as our variable, and we're putting that
command in parenthesis. Like in algebra, what is inside the parenthesis is calculated first, and then anything
outside of the parenthesis comes next.
To make this even more useful, we'll need to use something called conditionals.
It’s only logical: conditionals build intelligence into scripts with if and then commands
Conditionals are if/then questions. If/then statements are decisionmakers: we give them the conditions that need to
be met, and then tell them to evaluate whether conditions are being met.
For example:
You can combine variables with conditionals for very useful results.
#!/bin/bash
osVersion=$( sw_vers -productVersion )
if [ $osVersion = "10.14.5" ]; then
echo No upgrade needed.
fi
Starting with a variable, an administrator can call up which OS version is on the Mac.
Adding in a conditional, starting with if, and then adding an echo, will cause Terminal to check which OS version a
Mac is running, and if it is the version that an administrator wants, Terminal will report back “No upgrade needed.”
Try this in Terminal by saving this script and dragging it into the Terminal.
How about if the if condition is false? Simply add an else statement and then specify what we want to happen.
Else is, of course, short for ‘or else.’
#!/bin/bash
osVersion=$( sw_vers -productVersion )
if [ $osVersion = "10.14.5" ]; then
echo No upgrade needed.
else
echo Update required.
fi
Can you run a script not only detecting which OS version a Mac has, but also automatically installing the newest
version if it’s needed?
On every enrolled Mac, Jamf Pro installs its own jamf command line, or binary tool. The jamf command does
things specific to Jamf management like running policies. We can give any policy a unique name, called a Custom
Trigger, and then use the jamf command line tool to call that policy by its customer trigger name — and run it.
In this case, the script we will be using is going to call the runUpgrade policy, which is exactly what it sounds like:
running a software upgrade.
To do this on multiple computers at the same time, you’ll need to use an MDM service like Jamf pro.
To add this script to Jamf Pro, go to Settings > Computer Management > Scripts and then select the ‘New’ button.
Here, you can name It something like CheckOSVersionandRunUpgrade, leave notes about it, put the script into the
‘Script’ tab, provide options and limitations, and save.
#!/bin/bash
osVersion=$( sw_vers -productVersion )
if [ $osVersion = "10.14.5" ]; then
echo No upgrade needed.
else
jamf policy -event runUpgrade
fi
Jamf Pro offers a view of scripts that highlights types of scripting, much like a script editor. Select ‘shell’ one time
from the dropdown, and then it will default to this easier-to-read editor.
You can add in echo commands that will then be reflected back into your policy logs. They can help with
troubleshooting and locating devices that have not been updated.
To create the policy, create a new policy and scope it to a Smart Group. Make it a recurring event and link it to the
code you have created and named above. (For more on creating policies, please see https://docs.jamf.com/10.1.0/
jamf-pro/quickstart-computers/Create_a_Policy_to_Run_Software_Update.html).
#!/bin/bash
while [ $( pgrep TextEdit )]
do
echo Waiting for TextEdit to quit.
sleep 2
done
echo TextEdit has quit.
The pgrep command determines whether or not a process is running: in this case, the TextEdit application. The
next two statements tell us what SHOULD happen while TextEdit is running:
Opening TextEdit, running this script in Terminal, and then quitting TextEdit will show you how this script works.
cd = change directory
~ is a shortcut for the home folder and called the tilde.
ls = list (creates a list of items in whichever directory is selected)
aFile = a variable name for 'any file,' which could be any phrase you prefer.
'for' in this case is both setting a variable and reading a variable at the same time. It is effectively saying:
For each file in the file list, do the following. Echo that we're renaming the current file, and then use the
move command to actually do it.
Here, we're going to pre-pend the name of every file in the MyStuff Folder with "webinar."
#!/bin/bash
cd ~/Desktop/MyStuff
filelist=$( ls )
All of the files in your MyStuff folder should now begin with webinar-.
Take a look ahead
Don't worry. We are not expecting you to know all of the commands below! But you might be surprised by how
thoroughly you now get the gist of it.
Here is what the script might look like after the warning period has ended.
#!/bin/bash
"/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper" \
-windowType utility \
-lockHUD \
-title "macOS Mojave Upgrade" \
-heading "ALERT: Your OS upgrade is about to start!" \
-description "Your Mac will automatically upgrade its operating system in five
minutes and can no longer be deferred. Close and save your work now. The process
will take about an hour and your computer may restart multiple times. Leave your
computer connected to power and do not move or close your laptop. To begin the
upgrade immediately, select the 'Upgrade Now' button." \
-icon "/Applications/Install macOS Mojave.app/Contents/Resources/InstallAssistant.
icns" \
-iconSize 256
-button1 "Upgrade Now" \
-defaultButton 1 \
-countdown \
-timeout 300 \
-alignCountdown right
exit 0
This is what it looks like when it runs:
As you can see, it doesn’t cover the entire screen (-iconSize 256). This allows the user the ability to click away and
save their work. The countdown displays on the right side, and the default button says “Upgrade Now”.
This script is built into most installers. This one-liner assumes Mojave is already in the folder, and the ampersand
restarts the computer.
This peek into more complex code isn’t meant to scare you – it’s meant to show you how, with just a little bit
of knowledge, you can get pretty far with scripts: automating and improving your workflows and your user’s
experience.
It’s also to show you something else: even if you haven’t built a code from scratch, you can still use it. You want to
do something in a script? Google it. Someone else might have done it for you!
Your Mac
If you'd like to discover new commands, your biggest resource is already staring you in the face: your computer is
actually already a tremendous resource.
Try this:
From a Finder window, select shift , command , period . to show hidden files and folders. Commands in
Terminal are, after all, backed up by something. And your computer is holding all of the instructions that come with
each command in a separate file.
The first folder you should investigate is bin. Bin is short for binary. Open to see what's inside. This folder contains
about 35 items: echo, bash, mkdir – some familiar, but some new.
You don't have to learn what each command does. Instead, when writing your scripts, think about what you would
be doing in the finder and then seek commands that do what you need. Google is your friend! If you can do it in
the Finder, there's a command line for it.
Other folders to investigate include sbin and uxr (which stands for Unix system resources). Take a look around!
Instructional videos
This guide is a simplified version of a Scripting for Beginners webinar. If you’re more of an auditory learner, you
would do well to watch it, and there are more examples to learn there: Scripting 101 for Apple Admins
Once you’ve watched the video, head on over to the blog post that follows up on it, which offers ideas for next
steps and how to continue learning, with a more in-depth list of resources than in this guide: Just 10 Commands,
Then Keep Learning
Trainingcatalog.jamf.com
We have 15 hours of short how-to videos on scripting with basic and advanced courses. Check out our scripting
series, available to subscription customers.
Request Trial