Skip to main content

Hi folks,

I'm looking for an elegant way to keep a running countdown timer on the screen for when we schedule a system reboot (usually a one-hour timer). I could probably hack something together (like a constantly-refreshing CocoaDialog window) and have done so in the past, but I imagine there has to be a better solution out there.

Has anyone run across something that fits the bill? A standard OS notification bubble would be ideal.

Thanks!

There are a few options.

jamfHelper has a counter display and a countdown function. You can make jamfHelper windows appear with no buttons, so in essense it would be a window they couldn't dismiss but would show a countdown. The only issue is the default text when using a countdown is "Please make a selection" or something like that, which doesn't make sense since the users wouldn't be selecting anything. Just watching it count down.

Another (and I think better) option is cocoaDialog. I hadn't even thought of doing this until I saw your post, but you can make the progress bar function count down backwards to indicate the time left, a bit like an hourglass. When the sand runs out, its Reboot time!

I just threw this script together after reading your post and tested it and it works pretty nicely. Check it out. Change the path to cocoaDialog if you need to. Ours is deployed to the same location as jamfHelper.

This script does a 5 minute countdown (from 300 seconds down to 0) before disappearing. If you couple that with something like a shutdown -r +300 & command in your script right at the time the progress bar appears, it would start a 300 second reboot time and push it to the background and allow the rest of the script to run, meaning right after the progress bar disappears the Mac will reboot. You can change the variables up a little but the $progLeft one should stay at 100 to start with since that's the "full" progress bar it starts off with.

#!/bin/sh

cdPath="/Library/Application Support/JAMF/bin/cocoaDialog.app/Contents/MacOS/cocoaDialog"

rm -f /tmp/hpipe
mkfifo /tmp/hpipe
sleep 0.2

sudo "$cdPath" progressbar --title "" --text "Preparing to reboot this Mac..." 
--icon-file "/System/Library/CoreServices/loginwindow.app/Contents/Resources/Restart.png" 
--icon-height 48 --icon-width 48 --width 450 --height 90 --float < /tmp/hpipe &

## Send progress through the named pipe
exec 3<> /tmp/hpipe

echo "100" >&3

sleep 1.5

progLeft="100"
secsLeft="300"

while [[ "$progLeft" -gt 0 ]]; do
    sleep 3
    let progLeft=( $progLeft-1 )
    let secsLeft=( $secsLeft-3 )
    echo "$progLeft $secsLeft seconds until your Mac reboots. Please save any work now." >&3
done

Hmm that is a good idea, I will try that out, I'm already using the CocoaDialog progress bar to display software update installation progress (the softwareupdate command can pipe into it very nicely). My biggest issue with that sort of script is getting the time synced properly to avoid any potential drift with repeated sleep commands and deal with system sleep/wake.

I didn't know jamfhelper had a countdown function, I must have missed it in the help section. I'm going to try that out too!


Yeah, the time sync could end up being an issue, but in that case I would simply add a few seconds buffer to the reboot command, as in shutdown -r 305 to make it reboot in 305 seconds and the progress bar end in 300 seconds. Most users wouldn't complain about getting an extra 5 seconds before reboot :)

Or, you could do away with a background reboot function altogether and simply wait for the progress bar to finish and then do shutdown -r now, after maybe a 1 second sleep.

Either approach would help account for time drift. Not sure about how it would handle if a Mac went to sleep in the middle of it though.


Ok, here is my modified script which corrects for any drift and displays minutes as well as seconds. Going to keep working on this, I think it may be a better way to go since the jamfHelper countdown option has hard-coded dialogue which doesn't fit my needs, and I agree with doing a "shutdown now" at the end rather than a delayed shutdown command running the whole time.

I'm sure this could be cleaned up:

#!/bin/bash

timerSeconds="3600"

cdPath="/etc/cocoadialog/cocoaDialog.app/Contents/MacOS/cocoaDialog"

rm -f /tmp/hpipe
mkfifo /tmp/hpipe
sleep 0.2

sudo "$cdPath" progressbar --title "" --text "Preparing to reboot this Mac..." 
--posX "center" --posY "199" --width 450 --float 
--icon-file "/System/Library/CoreServices/loginwindow.app/Contents/Resources/Restart.png" 
--icon-height 48 --icon-width 48 --height 90 < /tmp/hpipe &

## Send progress through the named pipe
exec 3<> /tmp/hpipe

echo "100" >&3

sleep 1.5

startTime=`date +%s`
stopTime=$((startTime+timerSeconds))
secsLeft=$timerSeconds
progLeft="100"

while [[ "$secsLeft" -gt 0 ]]; do
    sleep 1
    currTime=`date +%s`
    progLeft=$((secsLeft*100/timerSeconds))
    secsLeft=$((stopTime-currTime))
    minRem=$((secsLeft/60))
    secRem=$((secsLeft%60))
    echo "$progLeft $minRem minute(s) $secRem seconds until your Mac reboots. Please save any work now." >&3
done

I am such an idiot, I didn't even see that CocoaDialog has a version 3, I've been using 2.1 and was wondering where you saw several of those options.

Big facepalm.


Looks good! Wow, you're giving them a 60 minute countdown? That's pretty generous. Or was that just for testing purposes?
BTW, I actually timed the script using my iPhone stopwatch and there is no drift from what I can tell. It displayed for exactly 5 minutes in my tests.

Only thing I'd modify is the width of the progress bar. The 450 pixels I had it set to isn't enough with the additional text display you added, so some of its being truncated. Looks like about 510 is a good width.

Edit: yes, regarding version 3.0.0 beta 7, this is what I use. Being a beta there are a couple of issues with some of the other window types I've run into, but version 3 adds some nice pixel positioning capabilities and adds some other window types like checkboxes, etc. that aren't even documented beyond a post about them buried on the github pages by the developer.


This is a great idea and a great script. I think I'll be borrowing this for the office here. ;-)

I did notice one thing in my limited testing, and you may want to verify. When the progress bar dialog is up, the end user can quit the dialog by pressing Command-Q. The timer still keeps counting down and executes any code after your last done statement, if there is any. However, if the user can quit that, they may think the timer has stopped.

Not sure if there is a way to prevent that or not.


@stevewood - Yeah I've seen that too. For some reason the dialog responds to Command + Q which is annoying. I haven't found a good way to prevent that. None of the available options like --float or anything else seems to prevent that. Even if its run by root as is the case when done via policy. :(
I also wish I could find a way to stop that from being possible. If I ever figure something out I'll be sure to post about it.


Regarding drift and system sleep: I just ran a quick test and since the timer is constantly syncing with the system clock, time spent sleeping counts towards the timer. Sleep/resume works as you would expect in that scenario. I'm actually not sure which behavior I would prefer, I will have to think about that.

There is definitely work to be done in wrapping this with the shutdown command and whatnot, but it answers my original question. Thanks for all the input!


This is brilliant! Thank you!


Can someone share with me the syntax for jamfHelper -countdown...

Thanks JAMF Nation!!!!


@Potter you need to use the -timeout switch to set the number of seconds before the window times out. The -countdown switch then displays the timer counting down. If you do not put the -countdown switch in, there will be no timer counting down on the jamfHelper Window.


Thanks stevewood...

Is it possible to change the "Please make selection in" or just get rid of it???


I don't believe there is. I don't use countdown timers, but you may want to look at CocoaDialog and see if the timer function there allows you to remove it or change it.

http://mstratman.github.io/cocoadialog/


cocoaDialog can customize the timeout text or just remove it altogether, but even there your options are limited. You can leave the default text which states something like "timeout in [time left]" where [time left] is an actual countdown that ticks by. Or you can specify a blank text string which removes the timeout indicator completely. Or you can specify some static text to display but you won't get an actual countdown appear in the dialog.

Still, it's more flexible than what jamfHelper lets you do currently.