Friday, July 07, 2006

Automating Installs from DMG Images

This post is the first in a series documenting the development of a simple nightly update system for OS X. The system is intended to be a quick-and-dirty 80% solution for keeping standard OS X computers in our department up to date. We've been doing something similar for Linux for many years, and the OS X solution is an outgrowth of this.

I'll begin with the following script for installing software from dmg images, which I'll describe below:

Script dmg-install:
#!/usr/bin/perl

use strict;
use File::Basename;

my $DMG = shift;
$DMG =~ s/(\s)/\\$1/g;

# Attach and mount image:
print "Mounting image $DMG... ";
my $result = `yes| hdiutil attach $DMG | tail -1`;

# Get mounted volume information:
$result =~ /^.*\/dev\/disk.*(\/Volumes\/.*)$/;
my $mountpoint = $1;
$mountpoint =~ s/(\s)/\\$1/g;
print "$DMG is mounted on $mountpoint.\n";

# Find packages and application bundles:
my @apps = glob("$mountpoint/*.app");
my @pkgs = glob("$mountpoint/*.pkg");
push (@pkgs,glob("$mountpoint/*.mpkg"));

unless ( @apps or @pkgs ) {
my $list = `ls -al $mountpoint/`;
die "No application bundles or packages found in disk image.\nHere's what I see:\n$list";
}

for my $a (@apps) {
$a =~ s/(\s)/\\$1/g;
print "Installing application bundle $a...\n";
print `/common/manager/app-install "$a"`;
$? && die "Failed to install application bundle $a\n";
}

for my $p (@pkgs) {
$p =~ s/(\s)/\\$1/g;
print "Installing package $p...\n";
print `/common/manager/pkg-install "$p"`;
$? && die "Failed to install package $p\n";
}

print "Unmounting image $DMG from mountpoint $mountpoint...\n";
print `hdiutil detach $mountpoint`;


The dmg-install script takes the name of a dmg file as its only argument. The script uses hdiutil to mount the image, answering "y" to any questions asked during the process. Hdiutil returns information about the location of the mount point, and the script uses this to look there for any application bundles, pkg bundles or multi-packages. The list of application bundles is fed to a separate installation script called "app-install" (which I'll describe in a later post) and the list of pkg and mpkg bundles is fed to a script called "pkg-install" (also to be described later). After all bundles are installed, dmg-install unmounts the dmg image and exits.

No comments: