Best Way to Force Restart in Policy

el2493
Contributor III

I have a script that runs after an application is installed to alert users that they need to restart (and after 5 minutes it automatically restarts). I'm purposely using this over the built-in JSS Restart options because most software updates are done to lab computers and I don't want to have to go to each computer and click "OK" to allow the update.

#!/bin/bash -v

appName=("$4")

loggedInUser=$(stat -f%Su /dev/console)
echo $loggedInUser

#message information
msgprompthead="Software Restart Required"
msgrestart="This computer needs to restart to finish installation of the following application:

"${4}"

Please save any open files to external media. Restart will occur automatically in 5 minutes.

To restart immediately, please click Ok after closing all applications."

dialogicon="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/Resources/Message.png"
jamfhelper="/Library/Application Support/JAMF/bin/jamfHelper.app/Contents/MacOS/jamfHelper"

restartprompt=$("${jamfhelper}" -windowType utility -heading "${msgprompthead}" -description "${msgrestart}" -icon "${dialogicon}" -button1 "Ok"  -defaultButton 1 -timeout 300)

sudo -u $loggedInUser pkill -u $loggedInUser
sudo -u $loggedInUser shutdown -r +1

exit 0

I initially had it without the pkill command, but found that the computers wouldn't restart if there was an app that hung (like Excel on an unsaved spreadsheet). Adding the pkill command does indeed end all running processes, but it also seems to cancel the script so that it doesn't proceed to the shutdown command.

I also tried reversing the commands so that shutdown ran before pkill (hoping that it would tell the computer to reboot in 1 minute and that while it was waiting that 1 minute the pkill command would run). I tried running the policy with an unsaved Excel spreadsheet open (I had clicked to close it so it had the popup window up asking if I wanted to save it), but all that happened was the screen went black (except for Excel) then Excel closed and a Microsoft Error Reporting screen came up and the computer didn't reboot.

Any ideas? I definitely don't want the computer to ask a user if they want to restart because I want the whole process to be unattended except for the warning messages (which should automatically close after a given time). Is there maybe a way to run the pkill command as written but tell it to exclude the script that the JSS is running?

8 REPLIES 8

sdagley
Esteemed Contributor II

@el2493 If you're running this script from a Jamf Policy it's running as root, so not sure why you're trying to run the pkill and shutdown commands as the logged in user.

el2493
Contributor III

If I run the pkill command as straight sudo, it brings the computer back to the login screen and doesn't restart. Only by adding the -u $loggedInUser would it run as expected and kill the processes that were currently running.

I can't remember why I started doing the shutdown as the user, I thought at one point it was necessary but could be wrong on that.

I'm testing replacing the pkill command with this, I'm far from an expert on this but in my mind it'll provide a list of process IDs (exempting Jamf) and then kill those processes:

nonJamfProc=$(ps axc | grep -v jamf | awk '{print $1}')

for proc in "${nonJamfProc[@]}"
do
    echo "Found non-Jamf running process with PID: ${proc}. Killing it..."
    kill $proc
done

el2493
Contributor III

The above command seems like it's overstepping; running it restarts the computer immediately (without waiting for the shutdown command) and does that thing where the policy still shows as "Pending" and the connection to the JSS is broken for a while.

alexjdale
Valued Contributor III

We just run the "shutdown -r now" command. I've never had to kill any processes when I do it that way.

I use a launchdaemon to spin off a restart timer, so the policy can finish and send logs to the JSS.

sdagley
Esteemed Contributor II

What @alexjdale said - you really want to give the policy a chance to complete and report in.

el2493
Contributor III

@alexjdale interesting, I hadn't heard of using a launchdaemon for that purpose. What's involved with doing that?

I know it's important to allow policies to complete normally, which is why I had added the +1 to the shutdown command (in the past that or +2 had provided enough time for policies to finish running and report back to JSS). In this specific case the for proc in "${nonJamfProc[@]}" command strongarmed it, and I didn't intend to keep using it after finding that it did that.

alexjdale
Valued Contributor III

Here's an example of what I do: https://www.jamf.com/jamf-nation/discussions/14940/restart-script-forked

el2493
Contributor III

Interesting...so instead of the restart countdown occurring while the policy is still running (as part of the policy), you create a launchdaemon that triggers a script (which is also created by the initial script). Then the countdown runs after the policy is finished (thus giving the computer a chance to report back to the JSS).

Thanks for this alternate method, I'll look into using it going forward!