MacOS – Run a shell script when switching to battery power

launchdmacbook promacos

User Story:

As a MacBookPro user I want to run a script that ejects my USB drive when I disconnect the power source so that I don't have to remember to eject it before grabbing my laptop and hurrying off to a meeting.

Acceptance Criteria:

  1. NO third party apps
  2. NO polling. It must be event driven

I already have a script that I use for detecting network cable changes. I launch it using launchctl with a WatchPath like this in my .plist file:

<key>WatchPaths</key>
<array>
    <string>/Library/Preferences/SystemConfiguration</string>
</array>

I'm hoping to find a similar way to launch a different script when my power cord is connected/disconnected.

I already know how to detect whether AC power is connected or not… I just need to find an event that tells me I can do it.

AC_POWER=`ioreg -l | grep ExternalConnected | cut -d"=" -f2 | sed -e 's/ //g'`

if [[ "$AC_POWER" == "No" ]]
then
    for MEDIA_PATH in "/Volumes/Backup Drive 1/" /Volumes/MyPhotos/
    do
        if [ -e "$MEDIA_PATH" ]
        then
            echo "Ejecting $MEDIA_PATH"
            diskutil eject "$MEDIA_PATH"
        else
            echo "$MEDIA_PATH not mounted"
        fi
        done
else
    echo "AC Power connected"
fi

Best Answer

ControlPlane, which picked up where the cool-but-buggy Marco Polo left off, allows you to build context-based rules that can do things for you based on where you are and what you're doing. It uses an evidence-based approach to determining where you are and, once your location criteria passes a certain confidence threshold, executes actions for you based on the confidence that you're "in that location".

It's pretty cool.

One of the evidence sources it supports is current power source. And its evidence source support is all based around event-driven sources.

And it's open source.

And free.

You can set it up to run an AppleScript (or a shell script) for you when ever the power source changes or just when it changes in one direction.