PLEX server should keep Mac awake after wake-on-lan

I’ve again updated my script. The original version had the benefit of being very simple, so was easy to understand. The new version is more complex, but has two key benefits:

  1. It prevents sleep more reliably (because instead of calling caffeinate every 5 minutes, it calls caffeinate once but keeps it active until you’ve stopped using Plex).
  2. It prevents its log files from growing forever (because it discards old logs every day).

Here are the steps to update your script:


  1. From the Dock, click Launchpad > Other > Terminal

  2. In the Terminal window that pops up, copy-paste the following (and hit return):

echo "" >> ~/Library/Scripts/PlexCaffeinate.sh && open -a TextEdit ~/Library/Scripts/PlexCaffeinate.sh
  1. In the TextEdit window that pops up, delete all of the existing text, then copy-paste the following:
#!/bin/bash

# Put Plex into debug logging mode
defaults write com.plexapp.plexmediaserver logDebug true

# Paths
plexLog=~/Library/Logs/Plex\ Media\ Server/Plex\ Media\ Server.log
caffLog=~/Library/Logs/Plex\ Media\ Server/Plex\ Caffeinate.log

# Kill subprocess on exit
trap '[[ -z "$(jobs -p)" ]] || kill $(jobs -p)' EXIT

# Functions
timestamp()      { date "+%b %d %H:%M:%S"; }
today()          { date "+%d"; }
plexUpdateTime() { stat -f %m "$plexLog" 2>/dev/null; }
plexUserAction() { tail -20 "$plexLog" | \
                   grep "authenticated user" | \
                   tail -1 2>/dev/null; }

# Init globals
initDay()        { day=$(today); }
initPlexState()  { updateTime=$(plexUpdateTime);
                   userAction=$(plexUserAction); }

# Day check
isSameDay()
{
    local myDay=$(today)
    if [ "$myDay" = "$day" ]; then
        return 0
    else
        day=$myDay 
        return 1
    fi
}

# Idle check
isPlexIdle()
{
    local myUpdateTime=$(plexUpdateTime)
    if [ -z "$myUpdateTime" ] || \
       [ "$myUpdateTime" = "$updateTime" ]; then
        return 0
    else
        updateTime=$myUpdateTime
        return 1
    fi
}

# Housekeeping check
isPlexHousekeeping()
{
    local myUserAction=$(plexUserAction)
    if [ -z "$myUserAction" ] || \
       [ "$myUserAction" = "$userAction" ]; then
        return 0
    else
        userAction=$myUserAction
        return 1
    fi
}

# Wait until user has finished using Plex
waitForUser()
{
    initPlexState
    while true; do
        echo "$(timestamp) Caffeinating..." >> "$caffLog"

        sleep 120

        if isPlexIdle;         then break; fi
        if isPlexHousekeeping; then break; fi
    done
}

# Check Plex and caffeinate if needed
initDay
initPlexState
while true; do
    sleep 30

    # Rotate logs
    if ! isSameDay; then mv "$caffLog" "$caffLog".1 2>/dev/null; fi

    # Check Plex
    if isPlexIdle; then
        echo "$(timestamp) Plex is idle" >> "$caffLog"
    elif isPlexHousekeeping; then
        echo "$(timestamp) Plex is running background tasks" >> "$caffLog"

    # Caffeinate
    else
        echo "$(timestamp) Caffeinate" >> "$caffLog"
        waitForUser &
        caffeinate -is -w $! 2>/dev/null
        echo "$(timestamp) Caffeinated" >> "$caffLog"

        initPlexState
    fi
done
  1. In the TextEdit menu bar, click File > Save, then File > Close

  2. Go back to the Terminal window, and copy-paste the following (and hit return):

launchctl unload ~/Library/LaunchAgents/PlexCaffeinate.plist && sleep 3
launchctl load ~/Library/LaunchAgents/PlexCaffeinate.plist

That’s it - the new script is now being used, and you can safely quit Terminal.

1 Like