I’m running Plex 1.1.4 on Sierra and had noticed that Caffeinate was constantly caffeinating with the original script, since Plex Server is always busy as you’ve said. However, I do NOT get any “authenticated user” lines in my log. This might have something to do with the fact I don’t use the Plex client app, but rather a Cambridge Audio Minx Xi, which relies on Plex’s standard DLNA server function.
So anyhow, I see there is also another log file “Plex DLNA Server.log” which seems to be getting updated only when I’m actually browsing / listening to music. I’m going to try using the original, simpler version of the script but with the following instead:
@rickenplex Difficult to say for sure. I’m guessing copying-and-pasting those commands into Terminal has caused the && characters to be escaped / differently-encoded. Are you running an old version of OS X?
I have been working hard to get WOL to work. I had several issues to fix before the script worked great, but now it is al running smoothly I started with a script which is running on a DD-WRT router. This router needs to support TCPdump. More info about this script is available on the Windows forum: https://forums.plex.tv/discussion/comment/1428700#Comment_1428700
First of all I’d like to say that setting up the router correctly is very important to prevent issues later while using the WOL script. I’ve had help setting up my DD-WRT router as a second router because I am bound to mu ISP router. Unfortunately the help I got was on a Dutch forum so not everybody will be able to follow this, for those who do: page 36/37 on the following site:
After setting up the router WOL worked, and using the script from jaoptc, it also worked when opening PLEX apps. The first two problems followed. 1) after a few minutes of sleep, the Plex apps didn’t trigger WOL anymore. Manual WOL still worked. 2) Opening the PLEX app on my LG WebOS 3 tv didn’t trigger WOL at all.
The problem seemed to be that the Mac address disappeared from the router ARP table. Long story short: the solution to this problem was to add another line to the script under Purgecount (see script at the bottom of the post).
# To Broad cast the WOL when Server is out of the ARP table.
arp -i br0 -s $TARGET $MAC
While testing this solution another problem came up (don’t worry if this happens to you also, the added line works). The following problem was that the Mac woke up after a minute of sleep. It would then fall asleep after another minute and so forth.
While this seemed to be one problem, the sleep and wake where separate problems. Due to the fact that both of these problems need you to disable SIP (System Integrity Protection) I will explain the solutions of both here. The reason you need to disable SIP is to enable you to edit system files you normally can’t edit.
The first solution is for the sudden wakes of the Mac. I looked deeper in to the reason why the Mac waked by entering the following command in Terminal:
Step 1 is to disable SIP:
To disable SIP you start up the Mac in Recovery Mode. This is achieved by shutting down the Mac. When powering the Mac back on hold the CMD + R buttons until the Apple logo appears. From there go to Utilities > Terminal and enter the following
csrutil enable
Hit enter and when you see the confirmation restart the Mac and let the Mac boot normally.
After SIP is disabled and the Mac has restarted open Terminal and enter the following command:
Go to the line /usr/sbin/mDNSResponder and insert the following line:
<string>-NoMulticastAdvertisements</string>
After a reboot the wake reason RTC (Alarm) should be fixed.
The second problem which requires SIP to be disabled is the problem that the Mac fell asleep after a short wake period (< 1 minute). The core problem appeared to be that the Mac didn’t fully wake, but did a Dark Wake. The Mac checked if there was a valid reason for the WOL. If not, the Mac returned to the sleeping state. The solution is:
1 Open a Terminal window.
2 Type the following: cd /Library/Preferences/SystemConfiguration
and hit enter
3 Edit com.apple.Boot.plist by typing: sudo nano com.apple.Boot.plist
4 Move the insertion point down to the associated with the Kernel Flags
5 Type darkwake=0
6 Hit CTR + X, enter Y and hit Enter to save and quit the file.
7 Reboot the system.
After a reboot you need to enable SIP again.
This is done the same as disabling it, but by typing
csrutil enable
After these modifications my Mac sleeps and wakes perfectly.
In the process I found a lot of information about Sleep modes on the Mac and on Hibernation.
WOL also works when Hibernation is enabled. Since this is not a standard setting there is another command needed.
More info about Sleep vs Hibernate is on those two sites:
Beneath you can find my final DD-WRT script. The TARGET, BROADCAST and MAC sections need to be edited according to your setup.
Hope this helps some of you!!
Regards
Patrick
———————————————————————————————————————————
#!/bin/sh
#Enable JFFS2 and place script in /jffs/ then run on startup in web interface.
#You can check the log from http://192.168.1.1/user/wol.html
INTERVAL=2
PINGTIME=1
OLD_TIME=""
PORT=32400
WOLPORT=9
TARGET=192.168.1.252
BROADCAST=192.168.1.255
MAC=XX:XX:XX:XX:XX
WOL=/usr/sbin/wol
LOGFILE="/tmp/www/wol.html"
# Never change LOGLINESTOSTORE to under 100. It will create pretty much a loop on the cleanup log procedure
LOGLINESTOSTORE=500
PURGECOUNT=0
# To Broad cast the WOL when Server is out of the ARP table.
arp -i br0 -s $TARGET $MAC
echo "<meta http-equiv=\"refresh\" content=\"10\">" > $LOGFILE
echo "["`date`"] AUTO WOL Script started. <br>" >> $LOGFILE
echo "For server: $TARGET:$PORT and MAC: $MAC on port $WOLPORT <br>" >> $LOGFILE
tcpdump -q -n -i any -p -P out -K -l -O -U 'dst host '$TARGET' and dst port '$PORT'' 2>/dev/null | while read NEW ; do
# Get the line in seconds, to minimize the number of processed commands.
NEW_TIME=`echo $NEW | awk -F'.' '{print $1}'`
if [ "$NEW_TIME" != "$OLD_TIME" ]; then
# Get the source IP for logging
SRC=`echo $NEW | awk -F'[.| ]' '{print $4"."$5"."$6"."$7}'`
# If box is alive (responding to ping)
if ping -qw $PINGTIME $TARGET >/dev/null; then
echo "[`date`] NOWAKE - $TARGET accessed by $SRC <br>">> $LOGFILE
#touch /dev/null
else
echo "[`date`] _WAKE_ - $TARGET accessed by $SRC <br>">> $LOGFILE
$WOL -i $BROADCAST -p $WOLPORT $MAC >> $LOGFILE
echo "<br>" >> $LOGFILE
fi
OLD_TIME=$NEW_TIME
# Cleanup log file procedure, keeping the header and the last 10 last WAKE log lines
if [ "`wc -l $LOGFILE | awk -F'[ ]' '{print $1}'`" -gt "$LOGLINESTOSTORE" ]; then
head -n 3 $LOGFILE > /tmp/www/wol.tmp
PURGECOUNT=$((PURGECOUNT+1))
echo "Log File purged $PURGECOUNT times, last one at $NEW_TIME <br> " >> /tmp/www/wol.tmp
grep _WAKE_ $LOGFILE | tail -n 10 >> /tmp/www/wol.tmp
mv /tmp/www/wol.tmp $LOGFILE
echo "<br>" >> $LOGFILE
fi
sleep $INTERVAL
fi
done
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 caffeinate every 5 minutes, it calls caffeinate once 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):
@Parnty thanks for the great script! After setting it up last night and testing it, it seems to work great, however I noticed that Plex may have actually implemented their own process to prevent sleep.
My desktop has Plex server on it, and when I open up plex and start a stream from my laptop web browser I get these two PreventUserIdleSystemSleep processes:
The second one is from the caffeinate process running in your script, but the first one comes from Plex Media Server. Oddly, it is a PreventUserIdleSystemSleep process but it is named PreventUserIdleDisplaySleep? Have you noticed this before?
Both processes go away when I close the tab running plex on my laptop. So I’m wondering, is your script necessary anymore? Thanks!
@djcoma Interesting - I see the same thing on my system. I’d never noticed that before, but I hadn’t really been looking for it, so I’m not sure if it’s a new thing or not.
In any case, I just tried disabling my script on my Plex server, and then accessing Plex as I usually do via the Plex app on my Samsung TV. As before, I’m getting freezes and network errors while browsing my library, so I think my script is still needed.
But I’m hoping that someday the (fantastic) Plex development team will do a proper fix of this issue once and for all! Let’s not forget, Plex is free software, so we’ve got to be pretty grateful to these guys. Apart from this minor issue, Plex works amazingly well.
@Parnty Thank you for your script! I have set it up yesterday and tried to test it, but for some reason it does not seem to work for me.
I opened up Console and it is spammed with following messages every 10 seconds. 16.01.2018 16:21:15,480 com.apple.xpc.launchd[1]: (PlexCaffeinate[904]) Service exited with abnormal code: 126 16.01.2018 16:21:15,480 com.apple.xpc.launchd[1]: (PlexCaffeinate) Service only ran for 0 seconds. Pushing respawn out by 10 seconds.
I am running El Capitan on Mac Mini. I’m not sure what additional information may be relevant in this case but (or course) I can provide additional details.
Any help would be greatly appreciated.
@nakiin Can you do the following and post back the results:
From the Dock, click Launchpad > Other > Terminal
In the Terminal window that pops up, enter the following and hit return:
~/Library/Scripts/PlexCaffeinate.sh
If successful, this should appear to do nothing, as it is now running in a loop. Open another Terminal window by clicking Shell > New Window > New Window in the menu bar, then in the window that pops up, enter the following and hit return:
tail -10f ~/Library/Logs/"Plex Media Server/Plex Caffeinate.log"
Do you now see Plex is idle or Plex is running background tasks messages appearing in this window?
When you’re done, enter <ctrl+c> in both Terminal windows, and then quit Terminal.
@Parnty I tried to run the script and immediately got an error: -bash: /Users/andrzejkrzyzanowski/Library/Scripts/PlexCaffeinate.sh: /bin/bash^M: bad interpreter: No such file or directory
I’m running a Polish version of El Capitan - could it have something to do with localization settings?
Well, there weren’t any additional characters… At least not that I could see.
Anyway I deleted this part and entered it manually. Now when I run the script I get this: : command not foundanowski/Library/Scripts/PlexCaffeinate.sh: line 5: : command not foundanowski/Library/Scripts/PlexCaffeinate.sh: line 9: : invalid signal specificationrary/Scripts/PlexCaffeinate.sh: line 11: trap: EXIT : command not foundanowski/Library/Scripts/PlexCaffeinate.sh: line 12: 'Users/andrzejkrzyzanowski/Library/Scripts/PlexCaffeinate.sh: line 27: syntax error near unexpected token </code> <code>'Users/andrzejkrzyzanowski/Library/Scripts/PlexCaffeinate.sh: line 27:isSameDay()
I have no idea what’s going on… I think I’ll rewrite it all by hand. Maybe there are more weird artefacts…
Got it!
I’m running my Mac Mini headless and use TeamViewer to control it. Apparently when I copied the script from my Windows laptop via TeamViewer it added these artefacts. Probably different coding.
I copy&pasted the script again from within and now it works!
Thank you very much for your help
@bg3 Thanks a lot for this. I read your posts, and I think you might be right.
As you point out, it looks like Plex is currently using assertion kIOPMAssertionTypePreventUserIdleSystemSleep, which doesn’t seem to be having the desired effect of preventing sleep while using Plex.
You suggested that the Plex devs should use kIOPMAssertionTypePreventSystemSleep instead, which sounds like a good idea. There’s also kIOPMAssertionTypeNoIdleSleep, which might also work.
It’s great that you’ve done some investigating! Hopefully it’ll help the devs to do a proper fix.
The "NetworkClientActive” assertion might also be the right one here, since that’s what iTunes streaming uses, but I’m not sure if that’s a documented call or something just Apple uses.
As you point out, it looks like Plex is currently using assertion kIOPMAssertionTypePreventUserIdleSystemSleep, which doesn’t seem to be having the desired effect of preventing sleep while using Plex.
You suggested that the Plex devs should use kIOPMAssertionTypePreventSystemSleep instead, which sounds like a good idea. There’s also kIOPMAssertionTypeNoIdleSleep, which might also work.
It’s great that you’ve done some investigating! Hopefully it’ll help the devs to do a proper fix.
Pulling up this thread as I am experiencing the same problem with PMS on my Mac mini and I could not find a more recent discussion on this topic.
Has anybody from Dev ever responded to this matter?
@“Andreas B.” I’m not aware of any Devs picking this up. @bg3 raised the issue on his thread above, but it’s not clear if anyone’s doing anything about it. In the meantime, I’m making do with my script, which works ok.
$0.99 App Wimoweh is on the Apple App Store.
It does the job but not as elegantly as your script, but I haven’t been able to get your script working on Mac OS 10.13.6 High Sierra.