osascript display dialog hangs when screen is off; detect unavailable GUI/display from bash or applescript?

Solution 1:

This should keep waiting until the screen is on:

set screenOff to true
repeat until screenOff is false
    set screenOff to (do shell script "ioreg -c AppleBacklightDisplay | grep dsyp") contains "\"dsyp\"={\"min\"=0,\"max\"=2,\"value\"=0}"
end repeat

display dialog "Is now a good time to back up?"

Solution 2:

NOTE: I stumbled into what looked like a more direct answer, presented below, but @abc's method has proven more accurate over the course of the day. I suspect there may still be a good way to use queries in pmset to accomplish this fairly directly (perhaps by combining more than one indicator), but I'll probably only pursue that further if I notice any edge cases with @abc's ioreg approach.


I noticed something in the first half of the output from pmset -g assertions:

Assertion status system-wide:
   BackgroundTask                 0
   ApplePushServiceTask           0
   UserIsActive                   1
   PreventUserIdleDisplaySleep    0
   PreventSystemSleep             0
   ExternalMedia                  0
   PreventUserIdleSystemSleep     1
   NetworkClientActive            0

The next to last option, PreventUserIdleSystemSleep, appears to be 0/false when the lock screen is up or the lid is closed but the system hasn't gone to sleep yet (EDIT: this understanding is incomplete; I've since observed 0 values here even while the system is full-on and in use). It looks like this supports something similar to @abc's answer, either by skipping the backup routine when idle:

active="$(pmset -g assertions | grep -oP "PreventUserIdleSystemSleep\s+\K\d")"
if [ $active -ne 0 ]; then
    # backup
fi

Or holding off until the system isn't idle:

active="$(pmset -g assertions | grep -oP "PreventUserIdleSystemSleep\s+\K\d")"
until [ $active -ne 0 ]; do
    active="$(pmset -g assertions | grep -oP "PreventUserIdleSystemSleep\s+\K\d")"
    sleep 10
done