1

NOTE: If you have this problem, the answer from @abc helps mitigate it--but there are still unknown conditions under which this solution won't keep the osascript from executing and hanging.

background

I've been working on a backup script that runs occasionally via launchd. When it runs, it prompts me with something like:

osascript -e "display dialog \"Is now a good time to back up?\""

This works great when the system is open/online, but it seems to hang if the lid is closed or screen is locked/off. A tolerable way to test this is to SSH into the system as the same user with the desktop active, run a command like the one above, and observe that the dialog pops up.

If I run the same command with the system locked, it just hangs. If I unlock/open the system, the command doesn't finish, and the dialog doesn't appear.

When running on battery power, I can simulate the same condition by running:

pmset displaysleepnow; osascript -e "display dialog \"never never land\""

question

Is anyone aware of a way to detect this condition (at launchd, bash, or applescript level) so that I can do any of:

  1. keep the job from running at all until the system is active
  2. sleep the script until I can display a dialog without it hanging
  3. abort the script run before it hangs

I'm not keen on it, but the best I've been able to figure out so far involves putting a long timeout on the first dialog in the script and bailing out if it never gets answered, i.e.:

osascript -e "display dialog \"Is now a good time to back up?\" giving up after 600"
  • I’m going to remove all the “edit” - that’s not how we work - each version should read like it’s the only version. You did great to remove the accept, just make it clear how you need more details. People will put bounties on questions when they are very clear what’s needed to change. – bmike Jan 3 at 18:47
  • Fair (and thanks for explaining the edit). But I'm moving the information back to the top. The point is to help later readers (including, inevitably, a future version of myself) save time and effort understanding the state of the question. – abathur Jan 3 at 19:21
  • 1
    When you feel the important information needs to be at the top, it’s because the question is too long. The question should be short. Put all half answers and research in the answer section would be my advice, but that’s just an opinion - it’s your question so we defer to you on placement. – bmike Jan 3 at 19:33
2

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?"
| improve this answer | |
  • Tentatively accepting this since initial test suggests this works pretty straightforwardly. Thanks! I don't have the energy at the moment, but I'll try to convert this solution into something fairly equivalent with an approach I found this evening involving the pmset command, so that I can road-test both for a little bit and see if there are any edge-case conditions. – abathur Apr 3 '19 at 6:03
  • @abathur @abc: Just outa' curiosity, could caffeinate have a role in keeping the system fully awake while the backup script is running? – Seamus Apr 3 '19 at 12:52
  • @Seamus I would assume so (but I don't think it would address the hang at issue in the thread). – abathur Apr 3 '19 at 14:09
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
| improve this answer | |
1

System Events knows when the screen is locked. I believe all AppleScript delays and timeouts pause when the Mac is actually asleep. I switched to a heredoc as it is getting lengthy. Should really save it as a bona fide script file.

Try adapting something like:

osascript <<'SCRIPT'
delay 5
set userInteractionBlocked to true
repeat until userInteractionBlocked is false
  tell application "System Events" to set userInteractionBlocked to (running of screen saver preferences)
  if userInteractionBlocked then delay 300
end repeat
display dialog "Now a good time for a backup?" with icon 2 buttons {"Later", "Backup"} default button 2
SCRIPT

I used the delay 5 in to provide time to start the screen saver for testing—not important to its function.

| improve this answer | |
  • Good idea. It doesn't look like this works for lock/sleep/lid-closed conditions, but this probably works well for desktop systems configured to use a screensaver. I optimistically checked the equivalent security preferences object, but no dice. – abathur Apr 2 '19 at 21:46
  • Huh. I cannot reproduce your hang behaviour then. Bummer. I'll edit the answer to suit. "Comments are not for conversation", but does it stay awake when closing the lid? Will keep poking—yours is a great and obvious question. Suspecting though that the 'right answer' will not be written in Apple Script. – Joel Reid Apr 3 '19 at 0:04
  • It can if it's plugged in, at least. Also, edited question both to clarify that applescript isn't a requirement for the fix, per se (it's just hanging during the execution of the applescript) and to give the simplest way I've found to re-produce the condition. – abathur Apr 3 '19 at 5:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .