Determining the OS X version on a nonbooted-but-bootable disk

Happens every time: Client comes in with a nonbooting Mac that turns out to need an OS reinstall, but they don’t have their installer media. It’s less of an issue with recovery partitions and Internet Recovery, but it happens often enough to be annoying. Here’s how to find the installed OS version.

  • Start the problem machine in target disk mode and connect it to a functional box.
  • On the working machine, open Terminal and enter
strings /path/to/mach_kernel | grep 'Darwin'
  • The path to the mach_kernel will be /Volumes/drivename/mach_kernel.
  • The returned data should look something like this
Darwin Kernel Version 12.3.0: Sun Jan 6 22:37:10 PST 2013; root:xnu-2050.22.13~1/RELEASE_X86_64
Darwin
  • grepping ‘Darwin Kernel Version’ returns marginally cleaner results, but requires too much typing.
  • Anyway, now cross reference your kernel version with Wikipedia’s Darwin release history tableet voíla, your installed system version.

Sometimes, it’s the little things. Hat tip to Mac Help for the right command.

Installing and Packaging Circos on OS X 10.8

Circos is a software package for visualizing data and information. It visualizes data in a circular layout — this makes Circos ideal for exploring relationships between objects or positions. There are other reasons why a circular layout is advantageous, not the least being the fact that it is attractive.

What is less immediately apparent until you start digging into the documentation is that actually making Circos run is a bit of a trick. I needed it not only running, but packaged for InstaDMG and Casper distribution. The documentation links to a variety of sources that are a confusing mash of helpful, slightly outdated, now-wrong and missing. To keep myself sane, I decided to document my own process, thus this post.

Easily the best starting point is Paulo Nuin’s excellent and clearly-written install procedure. Unfortunately, even at 10 months old, it’s slipping slightly out of date, and packages available from MacPorts enable skipping a few steps. Here’s how I did things.. A general familiarity with the command line is assumed.

Gather Your Materials

Other instructions provide direct links to files. Those links go stale quickly, so I’ve linked to source directories where possible.

  • Circos (currently at 0.63-4)
  • MacPorts
  • GD perl module (I have elected to use 2.49 rather than the current version, for reasons I shall explain shortly)
  • Xcode
  • JAMF Composer (or packaging tool of your choice, but I highly recommend something capable of snapshot comparisons…I won’t cover packaging this manually, as the tree just becomes needlessly complex)

Set Up Your Environment

Standard packaging rules: Clean system with no other apps running. I set mine up in a Mountain Lion VM and it worked a treat.

  • Install MacPorts
  • Install Xcode
    • Launch Xcode and accept the license agreement and device support install
    • Open Preferences > Downloads and install the Command Line Tools
    • Quit Xcode
  • Configure and update cpan
    • Open Terminal and issue the following commands (accepting the defaults as prompted)
    • sudo cpan
    • install CPAN <- Case sensitive
    • reload cpan

Take Your Snapshot

At this point you’re ready to start installing the modules required to run Circos, so take your starting snapshot. This will be a simple, standard package.

Install and Test Circos

Decompress the Circos download, and put the resulting directory where ever you want to run Circos for simplicity’s sake, I followed Paulo’s suggestion and placed it at /Applications/circos-0.63-4/. Circos comes with its own module tester, so let’s use it. Open Terminal, and

cd /Applications/circos-0.63-4/
./test.modules

This should return a list of installed and missing modules needed to run Circos. On a vanilla 10.8 install, that’ll look about like this:

ok Carp
ok Clone
fail Config::General is not usable (it or a sub-module is missing)
ok Cwd
ok Data::Dumper
ok Digest::MD5
ok File::Basename
ok File::Spec::Functions
ok File::Temp
ok FindBin
fail Font::TTF::Font is not usable (it or a sub-module is missing)
fail GD is not usable (it or a sub-module is missing)
fail GD::Image is not usable (it or a sub-module is missing)
fail GD::Polyline is not usable (it or a sub-module is missing)
ok Getopt::Long
ok IO::File
ok List::MoreUtils
ok List::Util
fail Math::Bezier is not usable (it or a sub-module is missing)
ok Math::BigFloat
ok Math::Round
fail Math::VecStat is not usable (it or a sub-module is missing)
ok Memoize
ok POSIX
ok Params::Validate
ok Pod::Usage
fail Readonly is not usable (it or a sub-module is missing)
ok Regexp::Common
fail Set::IntSpan is not usable (it or a sub-module is missing)
ok Storable
ok Sys::Hostname
ok Text::Balanced
fail Text::Format is not usable (it or a sub-module is missing)
ok Time::HiRes

Install items required by Circos

It’s those “fail” entries we’re concerned with, of course. So at a bare minimum, we need to install:

Config::General
Font::TTF::Font
GD
GD::Image
GD::Polyline
Math::Bezier
Math::VecStat
Readonly
Set::IntSpan
Text::Format

We’ll do this using a mix of CPAN, build from source, and MacPorts. Since GD2 is available via MacPorts, let’s start there. The trick to know is that as of the 2.0.35 build of GD2, letting MacPorts install the fontconfig dependency seems to hard-hang the process. So:

sudo port install fontconfig
sudo port install gd2

Now, crank up CPAN, and let’s get started on the perl modules. Note that CPAN commands are case sensitive.

sudo cpan
install Config::General
install Font::TTF::Font
install Math::Bezier
install Math::VecStat
install Readonly
install Set::IntSpan
install Text::Format
exit

If you run the test.module script at this point, everything should pass but the GD modules. Let’s take care of that. (A word about versions: There is a newer version of GD available from the BitBucket repo Paulo mentions, but they’ve changed compilation methods and I can’t for the life of me get it to build. If you can, I’d appreciate a how-to!) In the Finder, locate your GD-2.49 download and decompress it. In Terminal, move to the GD-2.49 directory you just decompressed, and issue the following commands:

perl Makefile.PL
make
sudo make install

When that’s done, cd back to Circos’ bin directory and re-run test.modules. Everything should now register okay. Then:

sudo ln -s /usr/bin/env /bin/env

This symlinks env to /bin. Circos is picky about finding it there. You could also add it to your path. At this point, Circos should be ready to rock.

cd /Applications/circos-0.63-4/example
./run
ls  -lah

You should see circos.png and circos.svg with a creation date/time of…well, now.

Take your finished snapshot

All that remains is to finish your snapshot and package Circos! Use your standard procedure…no tweaking of permissions is required. But be sure to remove the extraneous junk that CPAN, et. al. leave strewn around your home directory!

What to do when OS X asks for a username and password (authentication) when deleting files

A client recently presented with an oddity: Every time he tried to delete a file from his Desktop directory, the OS queried for authentication. He stated that the problem began immediately after he upgraded to OS X 10.7, and that it only affected his Desktop folder.

This case, in retrospect, serves as a reminder of three things:

  1. Never take the client’s word that they have tested the situation to your satisfaction. In this instance, I asked if it was just the Desktop, and the client said yes. Turns out it affected all source directories.
  2. Never succumb to age-old temptation to conflate “last action taken” with “source of current problem”. I spent a while down the rabbit hole of errors in the Lion installer (and to be fair, that may have been it, but it unnecessarily restricted my search criteria).
  3. Occam’s Razor: Always check both ends of a transaction before running off looking for more complicated solutions.

I looked for known Lion installer problems. Nothing. I briefly suspected the all deny delete ACL on ~/Desktop, until I remembered that this was normal for Lion. I ran a permissions repair, thinking that perhaps some odd inheritance was going on. This was actually good, as it fixed a metric ton of other, unrelated problems, but was otherwise unhelpful. I looked into the console for indications of trouble, found an out-of-place entry for something called Safe Connect, and spent a while running that down. No dice.

The problem here is that I kept looking for problems with the source directory: ~/Desktop. I eventually broadened my search criteria a bit and found this post, which nailed the problem squarely. The problem was that ownership of the target directory — ~/.Trash — had been changed to root. Had I checked the two ends of the delete transaction to start with, I could’ve saved myself a whole lot of trouble and my client a lot of time.

I still have no idea what actually caused the problem. It’s not unreasonable to suspect the Lion installer. But the source of the problem is less important than finding a solution for it.

CrashPlan PROe versus Java on OS X

We’ve recently begun changing our clients from local backup drives to CrashPlan PROe for backups. This is good. At the same time, Apple have dropped direct support for Java (which CrashPlan requires), and turned responsibility for development over to Oracle. Broadly, I think this is also good.

Since new Macs no longer ship with Java, users wanting the latest and greatest can simply download and install the SE 7 package from Oracle. CrashPlan, as of v3.3, wants SE 6. This is double-plus ungood, because once you have SE 7 installed, the Apple-provided SE 6 package will refuse to install, citing the presence of a newer version. Adding to the confusion is the fact that users with SE 6 who upgrade to SE 7 will have no problem, since installing 7 leaves 6 untouched. So the takeaways here are as follows.

  1. If a user has SE 6 installed, and upgrades to SE 7, CrashPlan will see and use the older version just fine.
  2. If a user has SE 7 installed and installs CrashPlan, the client will not operate. Resolve this by downgrading to SE 6. Open /Library/Java/JavaVirtualMachines, and remove the clearly-labeled 1.7 VM. Download the 1.6 installer from Apple (as of this writing, it’s 1.6.0_35), and install it. If the user needs or wants 1.7, you may subsequently install Oracle’s 1.7 package without repercussion. Then launch (or install) CrashPlan.

The long-term fix, of course, is for Code42 to update their client to recognize the 1.7 VM.

Note: This applies to OS X 10.7 and 10.8.

UPDATE: Code 42 has finally given me a formal response.

We still do not have a work-around for the issue of needing Java 6 for the CrashPlan PROe client. Our engineering team is working on getting this sorted, but, as this will require a change in code, nothing will be available until at least the the next patch release.”

Given the frequency of Java patches, I’m not sanguine about this not becoming an ongoing problem now that Oracle is providing OS X Java. We shall, I suppose, see.

Cisco VPN Client, Ralink Wi-Fi Drivers and Random Kernel Panics

A client came in recently with a series of odd, apparently unpredictable kernel panics. A few minute of log trolling led to four panic logs. Knowing that she’d installed Ralink USB Wi-Fi device drivers on the machine under Snow Leopard, I initially suspect them as the root cause (I’ve never liked Ralink’s ugly, kludgy software, and tend to suspect it on principle.)

Two logs showed a crash on loading Airport extensions, and two on USB drivers, but the common link was the extension loaded just prior…in each case, a kext for Cisco’s VPN client. This surprised me not just because I’d expected to find the Ralink stuff, but because we switched from the Cisco native VPN client to AnyConnect over a year ago. Apparently, a significant portion of the old VPN client had remained on her system, and been carried forward through at least one upgrade cycle.

A check of the /private/var/opt/ subdirectory showed most of the client still around. Running the vpn_unintall script removed most of the bits (which I double-checked by visiting each location specified in the script. I then manually delete the cisco_vpn subdirectory in opt. I also removed the Ralink utilities, including a preferences file in /Library/Preferences and a directory in /Library/Frameworks. Ralink provides no uninstaller.

So far, no more kernel panics. Possibly my distaste for both Cisco’s VPN client and Ralink’s just is justified.

UPDATE: This situation is a good argument for keeping a copy of John Welch’s Kext Lister utility handy.

Creating a custom Sophos Anti-Virus for Mac package and deploying via script

First, some necessary explanation.

We use Sophos Anti-virus on Windows and OS X computers, managed by a central Sophos Enterprise Console (SEC). Clients get their settings from the SEC after installation, including the critical AutoUpdate settings. Now Sophos would have you believe, on the basis of this (woefully outdated) document that you can use Sophos Update Manager for OS X (login required) to simply inject your AutoUpdate (and other) settings and get a neat, distributable metapackage.

This, in our case at least, is a filthy lie. Or at least a half-truth in dire need of a shower and shave.

You can prepopulate all your settings in the metapackage, and it will run. Until you try to alter your AutoUpdate settings on the SEC and distribute them. For reasons unknown to us, the clients don’t get the message. We learned this the hard way, after shift in the address of our SEC left us directing clients to uninstall and reinstall the software just to get updated settings. Ugly.

After a few calls to technical support, it seems you have to distribute not a simple metapackage file, but rather an entire directory with several ancillary files that Sophos requires to correctly configure trusted communications with the console. Ugly.

So here’s our entire process for creating and distributing a custom installer for Sophos. This process assumes a reasonable level of familiarity with: Sophos Enterprise Console, basic shell scripting for OS X, Sophos Anti-virus for OS X, and the Casper Suite. If anything requires clarification, I’m happy to expand. As always, YMMV.

  1. Download and install Sophos Update Manager (SUM) on your OS X box. This requires a MySophos login.
  2. Launch SUM and authenticate. Provide your Sophos EM credentials in the usual and customary locations.The “Download Updates To” location is fixed to /Sophos Anti-Virus/ESOSX for inexplicable reasons, but can be modified using special instructions from Sophos. I’ve sanitized my copy of these directions a bit and pastebinned them. This is a total hack, for which I take no responsibility, but it may be useful to you since it lets you use a local CID and put it where you like. I prefer to copy the SEC’s authoritative CID.
  3. Continuing with my way, uncheck Check for updates from Sophos, then click Apply, then quit SUM.
  4. If you have rights to your SEC: Open SEC (either on a Windows box or a VM). Click Update Managers in the toolbar. Right-click on your update server, and select Update Now. Download status will change to “Downloading binaries”. When this process completes, your CIDs will contain up-to-date binaries, and you may exit SEC. If you don’t have SEC rights, ask for them, because you should have them. In the meantime, ask your SEC administrator to update the CIDs.
  5. Back in OS X, you need to get a copy of the CID for SAV Mac. If, like us, you have this location shared and you have access, just connect to your console’s fileshare and navigate to the CID subdirectory specified by your SAV subscription (usually ending in ESOSX or ESCOSX). Copy the entire contents of this this folder into /Sophos Anti-Virus/ESOSX/ on your Mac with SUM installed, replacing all contents of the target directory. Authenticate as required. You may find it easier to delete the contents of the target first, especially on 10.7 or 10.8. For reference, you should be seeing these files: cidsync.upd, customer_ID.txt, manifest.dat, master,upd, root.upd, sdf.xml and Sophos Anti-Virus.mpkg. If you don’t have rights or a convenient way to access the CID, ask an admin to send you a zipped copy of it, and proceed from there after (again) asking for a better setup.
  6. Relaunch SUM and authenticate. Switch to SAV Preferences. Configure all your preferences as you wish, but DO NOT TOUCH THE AUTOUPDATE TAB, or you won’t be able to save your settings! If you so much as open the AutoUpdate tab, SUM will demand that you fill it out, and refuse to save if you don’t (necessitating a restart from step 1). Apply, then quit SUM.
  7. Copy /Sophos Anti-Virus/ESOSX to your desktop.

At this point, you can redistribute the directory as a zip or DMG file and run the installer from it, but the entire contents of the directory must remain together for the installer to correctly configure its connection to the SEC.

Now to make this thing distributable via JSS (or, less desirably, DeployStudio). A package won’t work, since the ancillary files have to stay with it. Composer won’t work, because each install keys itself securely to the SEC, and redistribution breaks that link. Luckily, though, we already put the zipped installer in an HTTP-reachable location (for reasons outside the scope of this writeup). So rather than reinventing at least half of the wheel, I’ll use a script — distributed via JSS policy — to pull that zip file down to the client, run the installer silently, and remove itself. Here’s the commented script. If you use a DMG instead of a zip, you’ll need to change the commands and directories, of course, but the core process should still work. In DeployStudio, a postponed installation of a payload-free package using this script as a postflight should work.

#!/bin/sh

# Make a working directory, after checking for and removing any leftover instances from a broken install

if [ -d /private/tmp/sophos/ ]; then
	rm -r /private/tmp/sophos/
	mkdir /private/tmp/sophos/
	logger "Sophos install temp directory created after removing old directory"
else
	mkdir /private/tmp/sophos/
	logger "Sophos install temp directory created"
fi

# Get installer zip. Use whatever name you like. Our docs refer to Install Sophos Mac.zip, so that's what I'll use here.

curl http://address.to.your/installer/zip/or/dmg > /private/tmp/sophos/Install\ Sophos\ Mac.zip

# Decompress

cd /private/tmp/sophos/
unzip Install\ Sophos\ Mac.zip

# Install. Normally, installer requires sudo, but the jamf binary runs with admin rights, and using sudo here breaks the script.

installer -pkg /private/tmp/sophos/Install\ Sophos\ Mac/Sophos\ Anti-Virus.mpkg -target /

# Cleanup

cd /
rm -rf /private/tmp/sophos

exit 0

Upload this script to your JSS, then set a policy to deploy it, and you’re done. Ours runs when a machine is first set up, then never again. Once a client is tied to the SEC, updates and even major version upgrades are typically very smooth.

I realize this seems like a lot of documentation for what may not be a very common situation. Still, figuring it out took long enough and was such a hassle that I figure if I save one person the headache, it’s worthwhile.

Screen Sharing vs. Remote Management

File this one under “More How Than Why.” Admittedly this is probably documented someplace else, but I found out the hard way, so maybe this will save you the trouble.

Background: By default, our machines have a universal local admin account for maintenance purposes. All are deployed with remote login enabled for this account, and remote management enabled for the local admin plus the primary user, whose account is always a cached Active Directory account. This has never presented a problem.

The Situation: User with a MacBook Pro running 10.6.8 wants remote access to her office iMac (also at 10.6.8) while traveling, using her AD credentials, and doesn’t want or need the expense and complexity of Apple Remote Desktop.

The First Solution: Logically enough, the first step was to have her VPN into our enterprise network and then connect to her machine via VNC (Go > Connect to server > vnc://my.machine.address).

The Result: Authentication failures. Repeatedly, from any account (including local administrator) and for all permutations of Remote Management settings.

The Fix: Disable Remote Management, and enable Screen Sharing.

I think, but have not confirmed, that I could then reenabled remote management and still have VNC work properly. The client was on a time-limited schedule, and once we had a fix she had to bolt. So she has a working VNC setup. Why this happens, I can only speculate. Again, it’s probably documented somewhere, but I’d say it’s gnarly settings somewhere.

A more graceful solution would, of course, be to upgrade to Lion. That’s in the works, but for now the workaround suffices.