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
2 REPLIES 2

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!