Download Older Versions of macOS and Mac OS X

I’ve posted a few old links in my time (as I near 4,000 posts it would be hard not to have some that are broken). But Apple App Store downloads seem to do better with not breaking links. So here are some to old versions of macOS and OS X, in case like me, you always seem to need some old thing for testing:

Old versions of server are actually easier. You can download OS X Lion Server: or macOS Server:  and most versions are available on the developer portal at

A Bit About Python Module Imports

The first lines of practically every python script ever begin with the word import. Per the python docs at a module is “a file containing Python definitions and statements.” To open a python environment, simply open Terminal and type Python


To import a module just type import followed by the name of the module. A common one is os, so let’s import that:

import os

Now let’s use str to see where it is:


You’ll then see what the script was that is actually the os module and where it can be found/edited/viewed. Now let’s do a couple of basic tasks with os. First, let’s grab the user who’s running the script’s id (still from a standard python interpreter):


Here, we’re using a function that’s built into that os script, and the () is the parameters we’re passing to the function. When run in that interactive mode, you can use os.environ to see what environment variables your python script has access to (e.g. if you’re shelling out a command).


Now let’s use that os to actually shell out a bash command. Here, we’ll set a variable in the python interpreter:

bashCommand="cat /test.log"

Basically, we just set a variable called bashCommand to contain a simple cat of a log file (quoting it since it has special characters and all that). Next, we’ll use os.system with the variable of the command as the parameter we’re sending into the command:


Now I can clear the contents of that bashCommand variable using the del command, still from within that python console:

del bashCommand

When a module is imported, the interpreter first searches for a built-in module with the name you supply. If the interpreter can’t find a module, it will then search through the current working directory, then the PYTHONPATH wet in sys.path and . If not found, it then searches for a file named in a list of directories given by the variable sys.path. Now, let’s import urllib and check out what functions it has:

import urllib dir(urllib)

Then let’s ask for help for one of them:


The response will look something like this (ymmv):

urljoin(base, url, allow_fragments=True)

    Join a base URL and a possibly relative URL to form an absolute

    interpretation of the latter.

Now you know what goes in the parenthesis when you actually call the function from within your scripts.

Looping cURLy Braces

No, this article is not about my daughter’s curly hair and that expander thingie she had in her mouth for awhile (that sucked for her, booo). Instead we’re talking about expanding braces in shell scripts so we can expand braces in the script.

What’s a brace? As with grammar, a brace is a type of bracket meant to denote a series of characters. The bash interpreter will then allow for the expansion to include a series, such as 1..100 or 1 to 100 or a..z or a through z, useful in loops where the variable name (num in the below example) when invoked in the loop as $num will expand to be the number in the series in the loop. In the below example, we start with a set command and use -B to expand the curly braces:

set -B
for num in {1..100}; do
echo `curl -s -k 'GET' -H 'header info' ''$num`
echo ''$num

Note: In the above example, I did an echo just as a debugging line. I’d remove that before actually running the script (or more to the point automating it to run).

If we hadn’t of used the brace, we’d just be typing a lot more to get a 1 to 100 series to expand (e.g. for (( i = 0; i < 20; i++ ))) You can also use curly braces to do some much cooler expansion than a series of numbers. For example, {a,b{1..100},c,d{1…100},e,f{1…100},g} would do a then b1 through b100 then c, etc. In the above e script, once we’ve enabled brace expansion with that -B for set, we can then simply echo a curl onto the screen that loops through a series of 100 log files, using the $i within the loop.

A simpler example might be to use the following , which uses a series of letters instead:

set -B
for letter in {a..z}
echo $letter

If you actually wanted to learn more about palatal expanders then I’m sorry to bore you with everything else – here’s a better place for learning about that:

Updated My Apple Admin Conferences Page

I’ve been keeping a list of Apple Admin conferences for a few years now. I probably should have versioned it and kept each iteration, but… no need to pollute the interwebs with more outdated stuffs than I already have. So here’s the link for the latest version, updated with all the event dates announced thus far:

Hope to see you at some!

Disable Finder Animations

The more I push my machines, the more I disable some of the cool stuff in macOS. So this is a minor one, but you can easily disable finder animations by dropping the DisableAllAnimations key into using the defaults command, as follows:

defaults write DisableAllAnimations -bool true; killall Finder

To reverse the change:

defaults write DisableAllAnimations -bool true; killall Finder

Enable The Safari Debug Menu

I can’t believe I’ve never posted this: Safari has a Debug menu. I guess I’ve mentioned the Develop menu before. But I also like to use the debug menu on my daily driver, out of the box. I’ve been enabling this thing for what seems like forever in my deployment workflows.

defaults write IncludeInternalDebugMenu 1

Once enabled, you’ll see a bunch of awesome debugging tools.

Super-Simple Bash Graphs

The sparkr gem is installed by default in macOS. To use it to produce simple graphs, simply run it followed by a series of integers:

sparkr 12 110 250 110 12

The result would be as follows:

This is useful for a quick and dirty visualization in scripts. For example, a series of 5, 10, 200 numbers that don’t have that much range where you’re just looking for a simple pattern. Like number of lines in logs, etc. Obviously, you can pay a lot of money for graphing frameworks and very fancy-schmancy tools. This is really just for me in small scripts. 

Note: sparkr isn’t installed on all Mac systems. to install it manually use:

sudo gem install sparkr

Thanks to Armin Briegel for pointing out that sparkr isn’t installed by default on the latest OSen.

Managing nvram on a Mac

A number of settings on a Mac are stored in Non-Volatile RAM, or NVRAM. NVRAM has a number of keys that contain values that define how the hardware is configured on a device that aren’t otherwise stored in the settings of an operating system.

You can list all of the variables available using the -p option, as follows:

nvram -p

Variables in the available key pairs are managed using the nvram command as well. Each setting, which we’ll provide a list of below, can then be edited provided you have elevated privileges to do so, without any options defined. Most values are true and false and will need to be supplied as %01 for true and %00 for false. As an example, the following command will turn on Location Services on a Mac:

nvram LocationServicesEnabled =%01

And the following will turn it back off:

nvram LocationServicesEnabled=%00

Some settings won’t apply to certain models if the hardware doesn’t support that setting, but the following is a list of settings available on most models:

  • ac-rk-token
  • act-results: The results of the last Apple Diagnostics or Apple Hardware Test.
  • ALS_Data and Test_ALS_Data
  • AutoBoot: Defines how the system boots (e.g. %00-%03)
  • blacklight-level: Defines the level of the backlight (e.g. %d9%0a)
  • bluetoothActiveControllerInfo: Shows information about the active Bluetooth Controller (e.g. %8f%82%ac%05%02%00%00%003%14dv%ba%b5%c3A)
  • bluethoothInternalControllerInfo: Shows information about the internal Bluetooth Controller (e.g. %00%ac%05%00%00%00%00%00%00%8c%85%90@%a4k)
  • bodega-boot-to-black
  • boot-args: Provides for arguments for use when booting the kernel (or instructions sent to the kernel such as don’t bring any chicken, er, I mean don’t allow 32-bit software to be run or disable rootless (sudo nvram boot-args=“rootless=0″). Also includes:
    • debug=0x1d4e
    • debugshell=2
    • kdp_match_name=mojo
    • watchdog=0
    • smc=0x2
    • -pbmkp rtc=1
    • nvme=0x1
    • medetect_panic=1
    • dither=0
    • legacy_hda_tools_support=1
    • intcoproc_unrestricted=1
    • -tconpanic
    • -pbmkp
    • -v: boots in verbose mode
  • BootAudio: Indicates whether the startup chime will be played on models from 2017 or earlier (e.g. %00 or %01)
  • caterr-reset-disable:
  • csr-active-config: Shows the policy on third party kernel extensions (e.g. %ff)
  • csr-data: Defines a policy on third party kernel extensions
  • DisableEfiPackageCstates
  • display-config: Resolution for supported displays.
  • EFIBluetoothDelay: Time system waits for a wireless keyboard during boot (useful in data centers)
  • efi-Apple-payload0, eft-apple-payload0-data, efi-apple-payload1, and efi-apple-payload2: UUID, EFI path, etc (e.g. <array><dict><key>IOMatch</key><dict><key>IOProviderClass</key><string>IOMedia</string><key>IOPropertyMatch</key><dict><key>UUID</key><string>7CD53879-001B-4AC9-8D3C-13768C6883B9</string></dict></dict><key>BLLastBSDName</key><string>disk0s1</string></dict><dict><key>IOEFIDevicePathType</key><string>MediaFilePath</string><key>Path</key><string>\EFI\APPLE\UPDATERS\MULTIUPDATER\ThorUtil.efi</string></dict></array>)
  • efi-apple-recovery: Path to firmware information
  • efi-backup-boot-device-data: path to a backup efi file
  • efi-backup-boot-device-data-data: Same as above but encoded (I think).
  • efi-boot-device: Path with efi but with last booted (BLLastBSDName)
  • efi-boot-device-data: Just the path to the efi file with the UUID directory
  • Eos-fdr-cache-uuid: The UUID, but not the useful one used elsewhere
  • eos-restore-failure-uuids
  • fmm-computer-name: The name given to the computer at boot time
  • gpu-policy: Enables the GPU on some models of computers
  • HW_BOOT_DATA: Hardware boot data
  • InstallWindowsUEFI
  • LocationServicesEnabled: Enables (e.g. %01) or disables (e.g. %00) location services
  • multiupdater-0: Encoded multi updater used in efi-apple-payload0
  • previous-system-uuid: Previous uuid used, if available.
  • prev-lang:kbd: The previously selected keyboard language (e.g. en-US:0, en:2, GB:2)
  • security-mode: Used on some models to enable firmware passwords
  • security-password: When security-mode is used, used to set the firmware password
  • SmcFlasherResult (e.g. %00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00)
  • SystemAudioVolume: How loud the audio volume is (e.g. 7)
  • SystemAudioVolumeDB: Audio volume encoded %de which decodes to 222
  • ThorUpdateResult: Thunderbolt updater (e.g. %00%00%00%00%00%00%00%00)

The above list is not complete as I’ve not managed to change all of these in a useful manner. If you know what one is that I didn’t define, let me know! If you get in over your head, never fear, the following article will allow you to clear the values back to defaults:

Cisco, NetApp, Qlogic, the former Xserve RAID and a number of other appliances I’ve used over the years also use nvram to store similar variables. I’ll try and write up the similarities and discrepancies at some point. And good luck if you’re mucking around with this stuff.