Fork me on GitHub

Mounting Attached Devices

This page is dedicated to the development of systems to mount attached devices. The hope is that this page will result in a variety of tools which will be able to assist pre and post action scripts.



Support for Mac OS X Devices



USB Device Support Tools

The script below supports mounting attached USB devices by name volume name. There is support for FireWire devices and non-removable drives commented out. This code should work. The script requires improvements in various areas. Improvements are welcomed via email.

The script below is a work in progress. Even though it works it is certainly not an ideal solution.

#!/usr/bin/env ruby
#
# (C)2009 Henri Shustak
# Released Under the GNU GPL
# Lucid Information Systems
# http://www.lucidsystems.org
#
# WARNING : This code is quite speggitfied. Assistance with tiding up it would be great.
#
# This is a script to detect attached but unmounted volumes by Volume name and mount them.
# Tested on the following versions of Mac OS X : 
#                         - 10.12.6 intel
#                         
#
#
# Knowen Issues :  - If you rename the disk then somtimes the partition will not be detected.
#                    If this happens re-partition the disk and try again.
#
# Version 0.3.2
#
#
# Version History
#  0.3.2 - Added support for USB-Hubs and macOS 10.12.6 - made it a bit messy
#
# Note : Using a (list of) UUID('s) is generally a good approach to mounting devices. 
#        That is not how this script works. This script mounts volumes via the volume name.
#        This approach allows you to add additional devices into a rotation set without
#        altering this script or the way you call this script. However, it is extremely 
#        important to be aware of the potential problems which may arise by using the
#        volume name to mount a device before you use this script in any kind
#        of production setting.
#


# Check we are running on Mac OS X
os_kind = `uname`
if os_kind.chomp != "Darwin" 
    puts "This script is designed to run on darwin."
    exit -1
end

# Load system profile data 
#
#   Note : it would be better to use xml - 
#          anyone care to make this work 
#          with the built in RUBy XML system.
#          It requires parsing a Mac OS X .plist  
#          Assistance with this is greatly appreciated.
#


# List of detachable drives
disks = []

# Build a list of detachable USB drives.
system_profiler_output = `system_profiler SPUSBDataType | grep -A 1 "Removable Media: Yes" | grep "BSD Name" | sed 's/^ *//g'`

# Add detachable FireWire drives to the list
#system_profiler_output = system_profiler_output + `system_profiler SPFireWireDataType`

# Add ATA drives to the list.
#system_profiler_output = system_profiler_output + `system_profiler SPParallelATADataType`

# Add SATA dirves to the list
#system_profiler_output = system_profiler_output + `system_profiler SPSerialATADataType`

device = system_profiler_output.split("BSD Name: ")
device.each { |d|
    if d.to_s.include? "disk"
        disks << "/dev/" + d
    end
}



# Generate a hash of all devices to Volumes names. Disks without volume names will be set to nil
#
#    Note : Any suggestions on how to improve this are greatly welcomed.
# 
$disk_hash = {}
disks.each { |d|
    diskcom = "diskutil list #{d}" 
    partitions_list = `#{diskcom}`
    partitions_list = `echo "#{partitions_list}" | grep -e "disk*[0-9]s*[0-9]" | awk '{print $NF}'`
    partitions = partitions_list.split("\n")
    partitions.each { |p|
        major_system_version=`uname -v | awk -F "Version " '{print $2}' | awk -F "." '{print $1}'`
    	if major_system_version.to_i < 9 
    		# 10.4 or earlier
    	    volume_name = `diskutil info #{p.chomp} | grep "Volume Name:" | awk -F "Volume Name:        " '{print $2}'`
    	else
    		# 10.5 or later
	        volume_name = `diskutil info -plist #{p.chomp} | grep -A 1 "<key>VolumeName</key>" | tail -n 1 | awk -F "<string>" '{print $2}' | awk -F "</string>" '{print $1}'`       
	    end
        if volume_name.chomp.to_s.empty?
            new_partition = {"#{p.chomp}" => nil}
        else
            new_partition = {"#{p.chomp}" => "#{volume_name.chomp}"}
        end
        $disk_hash = $disk_hash.merge(new_partition)  
    }
}


# Find the device from the volume name (global varible)
def get_device
    if $disk_hash.has_value? $volume_name_to_mount
        device_to_mount = $disk_hash.key $volume_name_to_mount.to_s
        return device_to_mount
    else
        puts "Volume is not available."
        return nil
    end
end

# check if the device is mounted
def is_device_mounted (device_to_mount)
    # find the first disk containing a volume with a matching name
    mount_point = `diskutil info -plist #{device_to_mount[0]} | grep -A 1 -i MountPoint | tail -1 | awk -F "<string>" '{print $2}' | awk -F "</string>" '{print $1}'`
    if mount_point.chomp == "" then
        return false
    else
        return true
    end
end


# mount the device
def mount_first_volume_with_name
    device_to_mount = get_device
    if device_to_mount != nil 
        if ( (is_device_mounted(device_to_mount)) == false ) 
            device_mounted = `diskutil mount #{device_to_mount} 1>/dev/null 2>&1>/dev/null`
            if device_mounted.to_i == 0 
                # puts "device already mounted."
                return 0
            else
                return -1
            end
        end
    else
        return -1
    end
end

# Pull the name of the volume to mount from the command line
if ARGV.length == 1
    name_of_volume_to_mount = ARGV[0].to_s.chomp
else
    puts "Usage : /path/to/script/ \"<volume_name>\""
    exit -1
end

# Tell this system to mount the disk
$volume_name_to_mount=name_of_volume_to_mount
result = mount_first_volume_with_name
exit result