Yes, this is going to be a tiresome shell script post, but the thing about tiresome shell script posts tend to be actually useful things if you’re looking for a quick way of reminding yourself about the quickest, easiest and most efficient way of performing some simple but crucial task without a lot of pointing and clicking (and, better yet, without having to actually do any of that at all). After all, this blog is squarely pitched at people like me who enjoy shell scripting but got their degrees in Anthropology and had to pick this stuff as they went along so there’s probably some value in it.
I greatly enjoy Jamf Pro, and if you’re looking for a solution to implement or administer a whole raft of computer and devices then you could a) do far worse than use what is essentially the premier product for doing that, and b) give me a call. Rates are reasonable, operators standing by etc etc.
One of the fun things about Jamf Pro is that there are a couple of different ways of sending a script to a client machine without much (if any) input from the user, who probably has better things to do with his/her/their time. The best way is by setting an Extension Attribute – you write a script (or use/customize one of the hundreds of scripts or templates built into Jamf Pro or posted on Jamf Nation) to run a script against a macOS computer on check-in. In plain English, the Jamf Binary that gets installed on your client computer when you setup Jamf sits quietly in the background and occasionally phones home to the Jamf Server to let the server know that all is well, and to ask if there are any messages for it to look at. When it checks in then the Jamf Server can send down policies and profiles to restrict or allow the client computer to do all kinds of things, and in addition can run a shell script on the computer as root
.
Which is very, very handy, because when you’re trying to administer computers and you need to do something substantive to those computers via the command line then you need to be able to do so as root
, and chances are that a good number of your end users are either going to look askance at plugging in their passwords into odd screens or are running non-admin accounts and just plain don’t have useful passwords to plug in there. And also very handy because you can take the output of those scripts and put them into Jamf Pro by setting an Extension Attribute and throwing the result into a Smart Computer Group and in turn putting that onto your Dashboard.
In plain English – this is a thing that Jamf Pro puts on your computer that can report back all kinds of custom, non-standard but highly useful information, such as whether your laptop battery health has dipped below acceptable levels, whether your hard drive has been throwing up errors, or if your computer hasn’t backed up in a week; all useful things that someone should know about, and all indicative of a need for urgent attention and service. Further, all things that you – as the end user – might just plain not notice until it’s far, far too late.
Extension Attributes can handle full-size, complex, heavy duty scripts. You can see some examples here. The other place you can use shell scripts in Jamf Pro is in the Files and Processes field in Policies, and that’s where the operators come into play.
See, the idea is that you throw simple, single-command one-shot scripts into that field so that you can accomplish quick, basic tasks – with root permissions – on the destination Mac. Which is great if you want to, say, set the NTP time server or point the computer at an alternate Software Update Server.
But what if you want to put something a little more complex in there and string a couple of commands together? Well, it’s not widely and loudly talked about but you are able to do that by stringing your commands together using an operator like &&
, ||
or ;
.
A very quick word or two about && and || follows:
&&
works as a logical AND statement – requiring all conditions to be true. An example of this would be something like:
echo 'Hello World' && echo 'Goodbye Cruel World'
Which would give you an output of
Hello World
Goodbye Cruel World
||
works as a logical OR statement – requiring only one condition to be true, thus:
echo 'Hello World' || echo 'Goodbye Cruel World'
Which would give you an output of
Hello World
Back to the good stuff! Let’s say that I wanted to be able to construct a policy that would change the hostname of a client computer to match it’s hardware serial number. There are reasons not to do that (chiefly that it looks messy and that end users might find it confusing and impersonal), but equally if you’re working in a lab with a lot of identical workstations then using that as a demarcator might be practical. There are two steps to making this happen.
First, you have to find the serial number of the computer. This part is relatively straightforward because all you really need to do is to go talk to the I/O Kit Registry (ioreg
) command and tell it to go search through the million billion things it can look at and pull out the entry for the computer’s serial number, thus:
ioreg -c "IOPlatformExpertDevice" | awk -F '"' '/IOPlatformSerialNumber/ {print $4}'
Go ahead and drop that into your Terminal and hit return, and it’ll throw your serial number back at you. Great. Next you’ll need a command to go and set the hostname of the computer. We’ll hit up the System Configuration Utility command (scutil
), thus:
sudo scutil --set HostName insertSnappyNewHostnameHere
Finally, we’ll need to stick these two crazy kids together by getting ioreg
to return the serial number, setting that as a variable, and then passing that variable over to scutil
, like so:
myVar=$(ioreg -c "IOPlatformExpertDevice" | awk -F '"' '/IOPlatformSerialNumber/ {print $4}'); sudo scutil --set HostName $myVar
What we’ve done here is glue those two commands together with a ;
– but if the first command errored out or failed or some new update renamed or borked something in ioreg then the latter command would simply fail without giving you much indication that anything had gone wrong. The good news is that with this particular command the worst that could happen would be inaction; without relevant input from the first command to the second then the computer would just sit there with it’s original hostname until told otherwise, and thanks to the magical healing powers of Jamf Pro you’d be able to make a nice, neat, very visible smart computer group on its dashboard so that you’d know which computers had the command failed and required additional work or laying on of hands…