Restart Machine Script with tags

I had a client that was using an existing script to restart their machines. However we ran into an issue. As the number of machines increased, the script was resetting the restart process. As this script hadn’t been updated for years we decided to clean it up and add some new functions to it. To use this script, just save it to a machine that has the Citrix Powershell Snap-ins on it. Most places will just use their Desktop Delivery Controllers. Edit the fifth line to select where you want your logs to be written.

To execute the script just create a scheduled task to launch powershell.exe -file <thispowershellscript.ps1> <Tag on machines> for example

powershell.exe -file c:\scripts\ctxrestart.ps1 Friday_Reboots

Currently the code doesn’t support spaces in the Tags, so keep them contiguous for now.

So what this script will do, is enumerate all machines that have that particular tag. It will place them in maintenance mode, and then will sleep for 1 hour. That allows users to log off of those machines, and not accept new sessions. I updated this script and included 15 minute increment notifications, so that users will be notified of the pending restarts, and to logoff of their sessions. If you are doing A-side:B-side reboots with tags this will allow them to login to a machine that is not part of this restart window. If you are doing an entire Catalog at once, you may want to modify the Message Text that users will see during the restart process.

After 1 hour it will go through the list again and set the Restart flag on the every machine. This flag will be picked up by the Delivery Controllers, and they will be rebooted in staged groups to prevent boot storms.

The script then sleeps again for 1 hour. This will give the controllers enough time to fully recycle all those machines. After that hour it will go through all the machines again, taking them out of Maintenance Mode.

If you misspell the tag, or select a tag that has no machines it will notify you of this in the log and then shut down the script.

Speaking of logging, this will create a text file that gets re-written at each execution, and will be named after the tag. This allows you to use the same script for multiple separate tags, and provide individual logs for each of them.

Add-PSSnapin citrix*
$tag = $args[0]
$ServerList = Get-BrokerMachine -MaxRecordCount 1500 | where {($_.Tags -contains $tag)}

Start-Transcript -Path (Join-Path "<Path to log files>\"$tag".txt") -Force
Write-Output "Starting Reboot script for $tag"

if ($ServerList){
$ServerList | ForEach-Object {
Write-Output "Putting $($_.MachineName) into maintenance mode."
# Set the target machines to maintenance mode to drain sessions
Set-BrokerMachine -Machinename $_.MachineName -InMaintenanceMode 1
}

# Wait 1 hour before starting to reboot any machines
Write-Output "Waiting for 1 hour to allow users to logoff of sessions.  Users will be notified every 15 minutes until restarted."

# User Notification
# 1 Hour Notification
$ServerList | ForEach-Object {
$sessions = Get-BrokerSession -UserName *
Send-BrokerSessionMessage $sessions -MessageStyle Information -Title "Reboot Notification" -Text "This machine will reboot in 60 minutes.  Please save your work and logoff.  You can then immediately log back in."
}
Write-Output "Sending 60 minute reboot notice"
start-sleep 900

# 45 minute Notification
$ServerList | ForEach-Object {
$sessions = Get-BrokerSession -UserName *
Send-BrokerSessionMessage $sessions -MessageStyle Information -Title "Reboot Notification" -Text "This machine will reboot in 45 minutes.  Please save your work and logoff.  You can then immediately log back in."
}
Write-Output "Sending 45 minute reboot notice"
start-sleep 900

# 30 minute Notification
$ServerList | ForEach-Object {
$sessions = Get-BrokerSession -UserName *
Send-BrokerSessionMessage $sessions -MessageStyle Information -Title "Reboot Notification" -Text "This machine will reboot in 30 minutes.  Please save your work and logoff.  You can then immediately log back in."
}
Write-Output "Sending 30 minute reboot notice"
start-sleep 900

# 15 minute Notification
$ServerList | ForEach-Object {
$sessions = Get-BrokerSession -UserName *
Send-BrokerSessionMessage $sessions -MessageStyle Information -Title "Reboot Notification" -Text "This machine will reboot in 15 minutes.  Please save your work and logoff.  You can then immediately log back in."
}
Write-Output "Sending 15 minute reboot notice"
start-sleep 900

#Reboot the machine
$ServerList | ForEach-Object {#new-brokerhostingpoweraction -Action Restart -MachineName $_.MachineName
Write-Output "Setting Restart flag on $($_.MachineName)"
}
Write-Output "Waiting for 1 hour to allow machines to cycle through reboots."
start-sleep 3600

$ServerList | ForEach-Object {
Write-Output "Taking $($_.MachineName) out of maintenance mode."
#Remove maintenance mode
Set-BrokerMachine -MachineName $_.MachineName -InMaintenanceMode 0

#End Powershell Session
}
$today = Get-Date
Write-Output ""
Write-Output ""
Write-Output "All machines have left maintenance mode."
Write-Output "======================================================================"
Write-Output ""
Write-Output "Reboot schedule has completed at`t$today"
return
}
Write-Output "There are no machines with that tag."
Write-Output "Please doublecheck the spelling of your tag and try again."

Leave a comment

Your email address will not be published. Required fields are marked *