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:
- It prevents sleep more reliably (because instead of calling
caffeinateevery 5 minutes, it callscaffeinateonce but keeps it active until you’ve stopped using Plex). - It prevents its log files from growing forever (because it discards old logs every day).
Here are the steps to update your script:
-
From the Dock, click Launchpad > Other > Terminal
-
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
- 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
-
In the TextEdit menu bar, click File > Save, then File > Close
-
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.