0

I have a headless Mac mini running Darwin 15.6.0, which has several encrypted disks attached. Since it's headless, after reboot, I need to ssh in to the box, and enter the passwords for the drives. Since I'm lazy, I don't want to need to remember that "diskutil" is the command for this, and I certainly don't want to "man diskutil" on every reboot ... so I thought I'd write a script. The script needs to give me the "name" of the disk (so I know which password to enter), and then prompt me to enter it. Sample XML for parsing at the end, for completeness.

NB: there are several questions and answers around StackExchange which indicate xmllint isn't the best way to parse XML, and xmlstarlet is the way to go. But I don't want to install a package manager on this machine, so I have to go with the tools that exist. So, if there's a tool better than xmllint that shipped with Darwin 15.6.0, I'm open to that suggestion, too.

This is what I've come up with, which basically works but seems kind of gross:

#!/bin/ksh

input=`diskutil cs list -plist`
count=`echo $input | xmllint --xpath 'count(//dict/array/dict/key[text()="CoreStorageLogicalVolumeFamilies"])' - 2>/dev/null`

for i in {1..$count}
do
        uuid=`echo $input | xmllint --xpath '//dict/array/dict['$i']/key[text()="CoreStorageLogicalVolumeFamilies"]/following-sibling::array/dict/key[text()="CoreStorageLogicalVolumes"]/following-sibling::array/dict/key[text()="CoreStorageUUID"]/following-sibling::string/text()' - 2>/dev/null`
        lvname=`diskutil cs info $uuid | grep LV.Name | cut -f2 -d":"`
        echo Unlock $lvname
        diskutil cs unlockLV $uuid
done

Questions:

1) Is this (parsing the output of diskutil cs list and passing it back to diskutil cs unlock) really the best way to do this? (There's no command that says "prompt me to unlock all encrypted disks?)

2) Assuming this is the best way to do this, is there a better way to parse and loop through the output of diskutil?

2a) It seems like at a minimum there must be a better way to write that xpath argument in the loop.

2b) For that matter, requiring the loop in the first place seems less than ideal. Even if I do have to parse the XML, isn't there a way to extract all those values in a single call?

2c) this doesn't gracefully handle the case where the encrypted drives are already unlocked, and it probably should.

Below is the XML output. One more thing that might be relevant: man diskutil says, "A Logical Volume Family (LVF) exports one or more Logical Volumes (LVs). However, at the present time, only and exactly one LV per LVF is supported." Maybe that can be used with the xpath?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CoreStorageLogicalVolumeGroups</key>
    <array>
        <dict>
            <key>CoreStorageLogicalVolumeFamilies</key>
            <array>
                <dict>
                    <key>CoreStorageLogicalVolumes</key>
                    <array>
                        <dict>
                            <key>CoreStorageRole</key>
                            <string>LV</string>
                            <key>CoreStorageUUID</key>
                            <string>337BC4FF-B7FC-414B-8F07-9CD2C53B971C</string>
                        </dict>
                    </array>
                    <key>CoreStorageRole</key>
                    <string>LVF</string>
                    <key>CoreStorageUUID</key>
                    <string>0BA42E18-D48F-41A5-A2B8-BC30DD272F4D</string>
                </dict>
            </array>
            <key>CoreStoragePhysicalVolumes</key>
            <array>
                <dict>
                    <key>CoreStorageRole</key>
                    <string>PV</string>
                    <key>CoreStorageUUID</key>
                    <string>83F0A65B-F044-407F-88CF-C7E554172053</string>
                </dict>
            </array>
            <key>CoreStorageRole</key>
            <string>LVG</string>
            <key>CoreStorageUUID</key>
            <string>65D72B6D-7DA5-4EF7-97B5-0DEDD717E182</string>
        </dict>
        <dict>
            <key>CoreStorageLogicalVolumeFamilies</key>
            ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.