Restart Script (Forked)

alexjdale
Valued Contributor III

Hi folks,

I just wanted to share a restart method I've written that can be easily embedded into any bash script. It leverages CocoaDialog (you'll need to change the path variable for your installation location) to create a countdown progress bar and forks a restart script via a launchdaemon, so you can include it at the end of a JSS policy and the policy will be able to complete and upload policy logs to the JSS. I prefer this over other methods of initiating restarts because the timing can be precisely controlled and it provides a better UI for the user.

Hopefully some of you find this useful or it sparks some ideas. This method of echoing a script and launchdaemon to the /tmp folder has many other uses, allowing you to fork scripts/launchdaemons for one-time use which will disappear on reboot without needing to package anything.e56e890bd81c4b7faf86b51388c9c1aa

#!/bin/bash

cocoaDialogPath="/etc/CocoaDialog/CocoaDialog.app/Contents/MacOS/CocoaDialog"
rebootSeconds=300
restartTitle="Software Update Completed"

initRestart() {
# Create restart script
echo > /tmp/restartscript.sh '#!/bin/bash
timerSeconds=$1
cdPath=$2
cdTitle=$3
rm -f /tmp/hpipe
mkfifo /tmp/hpipe
sleep 0.2
$cdPath progressbar --title "$cdTitle" --text "Preparing to reboot this Mac..." 
--posX "left" --posY "top" --width 300 --float 
--icon-file "/System/Library/CoreServices/loginwindow.app/Contents/Resources/Restart.tiff" 
--icon-height 48 --icon-width 48 --height 90 < /tmp/hpipe &
exec 3<> /tmp/hpipe
echo "100" >&3
sleep 1.5
startTime=`date +%s`
stopTime=$((startTime+timerSeconds))
secsLeft=$timerSeconds
progLeft="100"
barTick=$((timerSeconds/progLeft))
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 restart." >&3
done
shutdown -r now'

# Create and load a LaunchDaemon to fork a restart
echo "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.company.restart</string>
    <key>UserName</key>
    <string>root</string>
    <key>ProgramArguments</key>
    <array>
        <string>sh</string>
        <string>/tmp/restartscript.sh</string>
        <string>$rebootSeconds</string>
        <string>$cocoaDialogPath</string>
        <string>$restartTitle</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>" > /tmp/restart.plist
launchctl load /tmp/restart.plist
}

initRestart
3 REPLIES 3

matt_jamison
Contributor

I tried it, didn't even get a popup on the screen, let alone a reboot. :( Running 10.10.3

Any ideas?

I put the app in /Library/Application Support/JAMF/bin/

matt_jamison
Contributor

Found the issue. Two issues to be exact, one was my fault. First, I fat fingered the cocoaDialogPath=.

Second, I had to put double quotes around $cdPath before progressbar, since I have a space in my cocoaDialogPath.

Working great now, thanks so much for the script!

carolpominville
New Contributor

Looking for a way to restart computers at 2am, basically to remove the people that don't log out, and then the next person can't login. Looking at your script above..being a newbie, I just need some clarification. Is this a script one would invoke with Jamf and scope it to a group of computers? Is this a script you put on the computer, and if so where...Somewhere I will add pkill -f Microsoft* to kill any open of their apps as they prevent restarts...  When you say "you will need to change the path variable for your installation location"... this suggests you put this script on the computer.... thanks