It has now been one year since I started my new position with Tamman Technologies and moved my family to the Greater Philadelphia area. It feels like everything has changed, but everything has stayed the same. Plus ça change, plus c’est la même chose, as the saying goes.
It has been a good change, a happy change. While it was a big move, it felt more dramatic to me a year ago than it does now, when it is just reality. I don’t have all of my thoughts about it collected and organized right now, but I felt that I should at least mark this point in time.
I’d also like to thank all of our family and friends that made the move possible, bearable, and successful.
I am a little late to this, but my AutoPkg recipe repository is now available alongside many others. So, I made the switch:
So, if you’ve been following my whimsical AutoPkg repository (Acorn! Fantastical! LaunchBar! XRG!), I suggest you switch, too.
In case you were still interested, I’ve updated the source code link for my Penn State MacAdmins Conference 2013 Luggage talk. My examples from the talk are ﬁnally on-line, so you can follow along in a little more detail if the information already presented in the slides wasn’t enough.
The main repository for the talk contains links to several Mercurial subrepositories, since I tracked each example separately as its own project.
Munki writes out data into the ManagedInstallReport.plist ﬁle when it runs. The InstallResults key in the report shows if anything at all was installed. If something was installed during the last Munki cycle, can we can programmatically ﬁlter out just the OS X Update?
The answer is yes! If it weren’t, of course, this would be an even shorter article. No short articles!
Let’s take a look at the Python code to do this. You can enter the following lines of code in the interactive Python interpreter. To get there, type “python” at the command prompt in Terminal on an OS X system.
We’ll start with the assumption that the OS X 10.8.4 update has just been installed. In that case, it would be listed in the current ManagedInstallReport.plist. (This won’t be the case on your own computer, of course, unless the same OS X update was just installed by Munki. For more on other conditions, stay tuned.) Create a variable for the plist ﬁle path as follows.
Import the Python “sys” module and add “/usr/local/munki” to the sys.path. This tells Python to look for importable modules there. This is roughly akin to adding to the PATH environment variable in a UNIX shell.
Since the Munki tools are installed — otherwise, we wouldn’t be worried about interpreting Munki install results — we can depend upon the availability of the “munkilib” Python module. That happens to include FoundationPlist, which is a handy way to read property lists. (In the following example, I import FoundationPlist as “plistlib” to hearken back to the name of an older Python module that did the same.)
Read the Managed Installs Report plist ﬁle from the path given earlier. Pull out only the contents of the “InstallResults” array from the property list data.
Iterate through the “InstallResults” array to ﬁnd each dictionary whose name is “OS X Update” and whose “applesus” value is “true.” There should only ever be one result, because only one OS X update should be installed during any given Munki run.
Printing the result displays information from the matching dictionary.
I was involved in a discussion today about the utility of adding scripts that can be run via “periodic.” It’s extremely handy to be able to drop or deploy scripts into the locations examined by periodic when it is scheduled. It’s so handy, I can’t believe I haven’t written about this before.
I’ve long been a fan of /usr/sbin/periodic and its ability to run other scripts. It has been tied together with ﬁrst cron and then launchd on the OS X platform for years, where maintenance scripts are run on a daily, weekly, and monthly basis.
Periodic itself is a shell script from FreeBSD that runs other executables in a speciﬁed directory. It will run any executables at the path speciﬁed by the argument following the command. By default, it will treat the argument as a directory within /private/etc/periodic, but you could also speciﬁed a arbitrary path.
Apple’s OS X maintenance jobs consist of scripts found within periodic subfolders:
Running “periodic daily” to execute the contents of the “daily” folder above is triggered by /System/Library/LaunchDaemons/com.apple.periodic-daily.plist.
The weekly and monthly launchd jobs are similar, diﬀering in their StartCalendarInterval values. I’m pretty sure that the timing of the weekly job has shifted from previous OS X releases to what I see on my system today.
|Job||Day||Time (system local)|
|Daily||Every day||3:15 AM|
|Weekly||Every week, day 6 (Saturday)||3:15 AM|
|Monthly||Every month, day 1||5:30 AM|
Once you place a new script into any of the existing folders, it will be called on the schedule speciﬁed by these three launchd tasks. The next time it runs, the periodic utility automatically picks up on any new executables in whatever subfolder it examines.
But, you don’t have to stop there. You can add your own periodic subfolders and wire them up with launchd. Add your own subfolders in /private/etc/periodic. Then, these subfolders can be activated via new launchd jobs that you create (and place in /Library/LaunchDaemons).
For example, to run all of the scripts in the new folder /private/etc/periodic/morning before the start of each business day, you could specify:
In researching the InstallResults key from the ManagedInstallReport.plist, I found that Munki automatically archives previous ManagedInstallReport.plist ﬁles. The archive is stored at the path /Library/Managed Installs/Archives.
I had 100 timestamped, archived reports there. That was such a speciﬁc number that it didn’t seem to be a coincidence. Sure enough, in the source code of munkicommon.py, there is a segment devoted to trimming the archived reports down to the last 100. Excess reports over 100 are deleted.
These archived reports are helpful if you are seeking to ﬁnd am example of something speciﬁc in the ManagedInstallReport output. In my case, I was looking to see how the InstallReport presented a system software installation, like the OS X 10.8.4 Update. On my home systems, I install those packages through the standard public Apple Software Update mechanism, but the update itself could have been obtained through a Software Update Server (SUS).
Luckily, the installation of the OS X 10.8.4 Update was recent enough that it did appear in the AppleUpdates and InstallResults of some of my archived ManagedInstallReport ﬁles. To ﬁnd where, I opened up the “Archives” folder as a Project in BBEdit and performed a Project-wide search for “OS X Update.” When I found a single ﬁle with two “hits,” I was reasonably sure that was the one where the install happened. For reference, its AppleUpdates key:
… and the InstallResults key:
Munki keeps track of various aspects of its managed software update process in the “/Library/Managed Installs/ManagedInstallReport.plist” ﬁle. I can’t take any credit for any clever uses of “ManagedInstallReport.plist,” but I did want to jot down a few things I learned about it.
Before and during a Managed Software Update run, the “InstallResults” key maps to an empty array.
Immediately afterwards, the array will expand to contain dictionaries representing each item that was installed. The array contents remain until the next Munki run.
In the following example, BBEdit v10.5.4 was installed by Managed Software Update.
Parsing the “InstallResults” array after a Munki run can be useful. Here are some points to consider:
As mentioned in the previous installments in this small series, Demo mirrored Terminal sessions with screen and Demo mirrored Finder windows, I included a live demonstration element in my Luggage talk at the Penn State MacAdmins Conference 2013.
The live demonstration involved applications that allowed me to focus my attention on the presenter’s screen in front of me while simultaneously projecting the same information to the audience — all while using video spanning instead of video mirroring.
I used this third speciﬁc technique to demo real-time editing of a text ﬁle on my secondary display in BBEdit 10.5 from Bare Bones Software. Of the three techniques, this is the one that ﬂopped in actual execution. However, I believe that it would have worked with more practice.
First, I opened the text document in a BBEdit window. This ﬁrst window was the one I watched on my laptop’s primary display.
I left the font and other display settings on this ﬁrst window set at their defaults, as speciﬁed in the BBEdit preferences. Since I was going to be viewing this on my screen, my normal settings worked just ﬁne.
Second, I made sure that the ﬁrst BBEdit window was showing the Files sidebar with View > Show Files command. (While this is not technically necessary, I like it this way.)
Third, I right-clicked on the name of the text ﬁle in the Files sidebar of the ﬁrst BBEdit window. From the contextual menu, I chose the ﬁrst command, “Open in Additional Window.” This opened a second window with the same content. All of the windows displaying that text ﬁle’s content are updated as changes are made to the ﬁle. You could also use View > Open in Additional Window with or without the Files sidebar open.
Fourth, while in the second BBEdit window, I selected Window > Synchro Scrolling command. This changes BBEdit’s default scrolling behavior. With synchro scrolling, vertical scrolling actions in any of the related windows then trigger scrolling in the others. This is not strictly necessary — if you have enough textual content to demand scrolling, it may simply be too much for a live demonstration — but I enabled it for good measure.
Fifth, I greatly increased the font size to scale the text up for the audience viewing the secondary display. This took me a while — along with a support request to the ever-patient Bare Bones Software — to ﬁgure out, because I wanted diﬀerent display settings for each window. For a day or so, I despaired that I’d ever be able to do it.
The answer was simple, and I found it as I was waiting for the quick answer from Bare Bones support. While the second window was active, I pressed Command-T to bring up the standard system Type panel (which is labelled “Fonts”). You can also access it from View > Text Display > Show Fonts. From the Fonts panel, I changed the type size to 36 points for the whole window and only that window.
Once all of this is set up, BBEdit handles all the work to make the second window act as a real-time duplicate of the ﬁrst window.
At the conference, I arranged everything before the presentation began. Somewhere in that preparation, I believe I messed up, which led to my problems making this work as intended. However, in my defense, the BBEdit window arrangement feel more complicated. (For that reason, I’d either like to ﬁnd a script to do this for me, or cobble one together.) At the appropriate moment when I dropped out of Keynote, I was ready for the two-window demonstration. When the demo was done, I switched to Keynote to continue with slides.
My earlier advice about using this technique sparingly applies here, as well. Perhaps doubly so, since the setup in BBEdit has a few more steps.
As mentioned in Demo mirrored Terminal sessions with screen, I wanted to include a live demonstration element in my Luggage talk at the Penn State MacAdmins Conference 2013. I used a second speciﬁc technique to demo Finder windows screens in real-time on my secondary display. As with the Terminal portion of the demonstration, this mirroring enabled me to concentrate primary display in front of me.
To create this eﬀect, I set up two Finder windows. Remember … the OS X Finder has always had the somewhat controversial capability of displaying the same content in two diﬀerent windows. (Whether I like or dislike this capability, I’m willing to take advantage of what it oﬀers in this case.) Each window displaying that content is updated when the underlying ﬁles and folders change.
The ﬁrst window was the one I watched on my laptop’s primary display. It was set up with my standard Finder window settings, although I found it useful to switch to column view when dragging ﬁles into and out of subfolders.
The second window mirrored the ﬁrst for demonstration purposes. It was moved to the secondary display, where my slides would normally appear, as part of my preparation for the talk. I selected speciﬁc View Options for this Finder window.
The ﬁrst goal was to make the window as readable as possible by the audience when projected. The second goal was to focus on the version number of applications, so I enabled that normally-hidden column in the Finder list view. I set these View Options while practicing with a second display and then dragged it into position on the projection screen for the talk.
The Finder handles the heavy lifting so that the second window becomes a real-time duplicate of the ﬁrst window.
At the conference, I arranged everything before the presentation began. Then, at the appropriate moment, I dropped out of Keynote and switched to the Finder for the demonstration. When the demo was done, I switched to Keynote to continue with slides.
My earlier advice about using this technique sparingly applies here, as well.