Often after monthly security and critical updates, a system requires a restart. System Configuration tools like SCCM provides a way to suppress the restart so that servers can be restarted in planned manner.
It would be completely fine to restart few handful of servers however, as the number increases it may become quite laborious to restart the servers manually.
My team was in similar situation where we have to restart some 40 – 50 odd servers.
Given this challenge of restart, I have written a powershell script that schedule & restart the servers.
A small 101 on the Automatic Server Restart script.
First run the following powershell commands. This will create a registry key to track server restart schedule. This needs to be done only once per system.
New-Item -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\ -Name ScheduleRestart New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\ScheduleRestart -Name Scheduled -Type DWord -Value 0 -Force
Next, save the below script and schedule a daily task to check if server requires reboot. If server requires reboot, the script will create 2 schedule jobs.
- Restart Server
- Restart Automatic Services
The script will then remove the above 2 jobs on next run.
<# .NOTES =========================================================================== Created on: 6/11/2018 2:41 PM Created by: Navdeep Singh Organization: Alivebits Filename: AutomaticServerRestart.ps1 =========================================================================== .DESCRIPTION A description of the file. #> # Get the next Sunday Date. By default, it return time as 00:00 (start of the day) function GetSunday { [CmdletBinding()] param ( [Parameter(Mandatory = $True, Position = 0)] [string]$Day ) Switch ($Day) { Monday{ (get-date).AddDays(6).Date } Tuesday{ (get-date).AddDays(5).Date } Wednesday{ (get-date).AddDays(4).Date } Thursday{ (get-date).AddDays(3).Date } Friday{ (get-date).AddDays(2).Date } Saturday{ (get-date).AddDays(1).Date } Sunday{ (get-date).AddDays(0).Date } } } # Get Current Day of the Week $Currentday = (get-date).DayOfWeek # Check registry key for Pending Reboot. This registry key deletes itself after successful restart. # http://ilovepowershell.com/2015/09/10/how-to-check-if-a-server-needs-a-reboot/ if (Test-Path('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired')) { if ((Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\ScheduleRestart -Name Scheduled).scheduled -eq 0) { # Define Schedule $JobSchedule_RestartServer = GetSunday $Currentday $JobSchedule_RestartService = $JobSchedule + "00:30" $ServerRestartSchedule = New-JobTrigger -Once -At $JobSchedule_RestartServer $ServiceRestartSchedule = New-JobTrigger -Once -At $JobSchedule_RestartService # Create Schedule Jobs $ScheduleRestart = Register-ScheduledJob -Name ScheduleRestart -ScriptBlock { shutdown /r /f } -Trigger $ServerRestartSchedule $RestartServices = Register-ScheduledJob -Name RestartServices -ScriptBlock { (Get-WmiObject win32_service -Filter "State='Stopped' AND StartMode='Auto'") | Start-Service } -Trigger $ServiceRestartSchedule # Capture last boot time $sysinfo = systeminfo | findstr /i boot # Update custom registry Key Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\ScheduleRestart -Name Scheduled -Value 1 -Force #Send Email Send-MailMessage -To user@domain.com -From "Server Restart Scheduled <donotreply@noreply.domain.com>" ` -Subject "Restart Scheduled for `"$env:COMPUTERNAME`" on `"$JobSchedule_RestartServer`" " -Body $sysinfo[0].ToString() -SmtpServer SMTPServerOrFQDN } } # Check if server has rebooted. If yes, then remove the schedule jobs and reset the custom registry key elseif ((Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\ScheduleRestart -Name Scheduled).scheduled -eq 1) { $CurrentDateTime = (get-date) Unregister-ScheduledJob ScheduleRestart -Force Start-Sleep -Seconds 10 Unregister-ScheduledJob RestartServices -Force $sysinfo = systeminfo | findstr /i boot #Send Email Send-MailMessage -To user@domain.com -From "Server Restart Completed <donotreply@noreply.domain.com>" ` -Subject "Server Restart Completed Successfully for `"$env:COMPUTERNAME`" on `"$CurrentDateTime`" " -Body $sysinfo[0].ToString() -SmtpServer SMTPServerOrFQDN Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\ScheduleRestart -Name Scheduled -Value 0 -Force } else { # Do Nothing }
Now, it could be tricky if you were to run the powershell script via task scheduler. Either because system doesn’t allow unsigned PS scripts or task scheduler not executing the scripts.
I have found the following method works during most of the time.
Specify the Program to run as powershell and following as arguments
-noprofile -noexecutionpolicy bypass -file pathToPowerShellScript
here is how it looks in TaskSchedule properties.

Automatic Server Restart Schedule Task
You can further improve the script email and reporting capabilities but for now it serves the purpose.
Hope you find it useful.
Reference
http://ilovepowershell.com/2015/09/10/how-to-check-if-a-server-needs-a-reboot/
Comments are closed.