header
header Register : : Login header
header
divider
menuleft
menuright
submenu
left

[August 25th, 2008] Check the home page regarding PowerShell related news from a brand new sponsor: Idera

ConditionalForcedServerRestart.ps1
Last Post 17 May 2008 05:28 AM by Jaykul. 1 Replies.
Printer Friendly
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Author Messages
kscrissUser is Offline
Basic Member
Basic Member
Posts:119

--
20 Mar 2008 07:03 PM  

  1. #
  2. #      \\\\ ////
  3. #     \\  - -  //
  4. #         @ @
  5. # ---oOOo-( )-oOOo---
  6. #
  7. # PowerShell Script: ConditionalForcedServerRestart.ps1
  8. #
  9. # Author: Kevin Criss
  10. #
  11. # Description:
  12. #   Reboots servers if they have not been rebooted in the last 30 minutes.  Sometimes Windows Updates do not require a
  13. #   system restart for every sever in an Systems-Application group of servers.  Some systems require either all their 
  14. #   server are rebooted or none of their servers are rebooted.  You might run two copies of this script.  One copy
  15. #   would perform a conditional forced restart on your group-a servers and then scheduled to run at a later time the 2nd
  16. #   copy of this script will perform a condition forced restart on the group-b servers.  To do this you would renamed
  17. #   this script and then change the hard-coded $Inputfile.  These Powershell scripts would be run as a .bat file scheudled tasks from you
  18. #   run-hosting server. 
  19. #
  20. ################################################
  21. # Function Get-Uptime written by Brandon Shell #
  22. ################################################
  23. # From Brandon Shell's blog at http://www.bsonposh.com/modules/wordpress/?p=18
  24. # Filed on: February 7, 2007 @ 12:57 pm  
  25. # With modifications by me necessary for this script and some Don Hite magic. 
  26. Function Get-Uptime
  27. {
  28.     Param([string]$server)
  29.     Begin
  30.        {
  31.           function PingServer
  32.              {
  33.                  Param([string]$srv)
  34.                  $pingresult = Get-WmiObject win32_pingstatus -f "address='$srv'"
  35.                  if($pingresult.statuscode -eq 0) {$trueelse {$false}
  36.              }
  37.           function myUptime
  38.              {
  39.                  param([string]$srv)
  40.                  $os = Get-WmiObject Win32_OperatingSystem -ComputerName $srv
  41.                  $LastBootUptime = $os.ConvertToDateTIme($os.LastBootUpTime)
  42. #                Don Hite's magic formula has been applied to Brandon Shell's script.
  43. #                http://www.myitforum.com/articles/40/view.asp?id=10485 
  44. #                $uptime = $os.LastBootUpTime                 
  45. #                return $uptime
  46.                  return $LastBootUptime
  47.              }
  48.           function ConvertDate
  49.              {
  50.                  param($LastBootUptime,[string]$srv)
  51. #                param([string]$date,[string]$srv)
  52. #                $year = $date.substring(0,4)
  53. #                $Month = $date.Substring(4,2)
  54. #                $day = $date.Substring(6,2)
  55. #                $hour = $date.Substring(8,2)
  56. #                $min = $date.Substring(10,2)
  57. #                $sec = $date.Substring(12,2)
  58. #                $RebootTime = New-Object System.DateTime($year,$Month,$day,$hour,$min,$sec)
  59.                  $RebootTime = $LastBootUpTime
  60.                  $now = [System.DateTime]::Now
  61.                  $uptime = $now.Subtract($RebootTime)
  62.                  $uptimeval = "$($uptime.days) days, $($uptime.Hours) hours, $($uptime.Minutes) minutes, $($uptime.seconds) seconds"
  63.                  $lastReboot = $rebootTime.toString()
  64.                  $sObject = New-Object -typename System.Object
  65.                  $sObject | Add-Member -memberType noteProperty -name ServerName -Value $srv
  66.                  $sObject | Add-Member -memberType noteProperty -name Days -Value $uptime.days
  67.                  $sObject | Add-Member -memberType noteProperty -name Hours -Value $uptime.Hours
  68.                  $sObject | Add-Member -memberType noteProperty -name Minutes -Value $uptime.Minutes
  69.                  $sObject | Add-Member -memberType noteProperty -name Seconds -Value $uptime.seconds
  70.                  $sObject | Add-Member -memberType noteProperty -name uptime -Value $uptimeval
  71.                  $sObject | Add-Member -memberType noteProperty -name LastReboot -Value $rebootTime.ToUniversalTime()
  72.                  $sObject | Add-Member -memberType noteProperty -name LastRebootUtc -Value $rebootTime.ToFileTimeUtc()
  73.                  $sObject | Add-Member -memberType noteProperty -name LastRebootTime -Value $rebootTime
  74.                  $sObject | Add-Member -memberType noteProperty -name PingServer -Value $True
  75.                  Write-Output $sObject
  76.              }
  77.           $process = @()
  78.           $objCollection = @()
  79.     }
  80.     Process
  81.        {
  82.            if(PingServer $server)
  83.               {
  84. #                 $result = myUptime $server
  85. #                 $srvObject = ConvertDate $result $server
  86. #                 $srvObject = ConvertDate $result $server
  87.                   $LastBootUpTime = myUptime $server
  88.                   $srvObject = ConvertDate $LastBootUptime $server
  89.                   $objCollection += $srvObject
  90.               }
  91.            else
  92.               {
  93.                   $sObject = New-Object -typename System.Object
  94.                   $sObject | Add-Member -memberType noteProperty -name ServerName -Value $srv
  95.                   $sObject | Add-Member -memberType noteProperty -name Days -Value $Null
  96.                   $sObject | Add-Member -memberType noteProperty -name Hours -Value $Null
  97.                   $sObject | Add-Member -memberType noteProperty -name Minutes -Value $$Null
  98.                   $sObject | Add-Member -memberType noteProperty -name Seconds -Value $Null
  99.                   $sObject | Add-Member -memberType noteProperty -name uptime -Value $Null
  100.                   $sObject | Add-Member -memberType noteProperty -name LastReboot -Value $Null
  101.                   $sObject | Add-Member -memberType noteProperty -name LastRebootUtc -Value $Null
  102.                   $sObject | Add-Member -memberType noteProperty -name LastRebootTime -Value $Null
  103.                   $sObject | Add-Member -memberType noteProperty -name PingServer -Value $False
  104. #                 Write-Output $sObject
  105.                   $srvObject = $sObject
  106.                   $objCollection += $srvObject
  107.                   Write-Host "Server [$server] not Pingable" -foregroundcolor red
  108.               }
  109.            Write-Output $objCollection
  110.        }
  111.     End
  112.       {
  113.       }
  114. # End of Brandon Shell's Get-Uptime function which includes sub functions: PingServer, myUptime, and ConvertDate
  115. }
  116. ############################################
  117. # Script Block $Check_If_Boot_Required     #
  118. ############################################
  119. $Check_If_Boot_Required =
  120.    {
  121.       $ServerName = $_.ServerName
  122.       "Processing Server = $ServerName" | Out-Host
  123.       $result = Get-Uptime $ServerName
  124.       If ($result.PingServer)
  125.          {
  126.             $LastReBoot = $result.LastReBoot
  127.             $LastReBootTime = $result.LastRebootTime
  128.             $Uptime = $result.uptime
  129.             "Time Last Boot Time = $LastRebootTime" | Out-Host  
  130.             "Universal Last Boot Time  = $LastReBoot" | Out-Host
  131.             $LastBootTimeSpan = [TimeSpan]((get-date- $LastReBoot)
  132.             $MinutesSinceLastReboot = [int]$LastBootTimeSpan.TotalMinutes
  133.             "Minutes Since Last Reboot = $MinutesSinceLastReboot" | Out-Host
  134. #           List the hotfixes for this server since yesterday.
  135. #           $TodaysDate = Get-Date 
  136. #           $A = Get-WmiObject Win32_QuickFixEngineering -ComputerName $ServerName | Where-Object { $_.InstalledOn }
  137. #           $B = $A | Where-Object {$(get-date($_.installedOn)) -ge $TodaysDate.AddDays(-1)}
  138. #           $B | foreach-object {$HotfixID = $_.HotfixID; $InstalledOn = $_.Installedon; $Description=$_.Description; $Body = $Body + " $HotfixID $Installedon $Description `r`n"}
  139. #           The above 4 lines of code work, but I currently lack the confidence in this GWMI (or my familiarity with) to use it on our production servers.
  140.             If ($MinutesSinceLastReboot -gt [int]30)
  141. #           Has it been more than 30 minutes since this server was last restarted???  If so lets restart it.            
  142.                {
  143.                   "This sever $Server needs to be rebooted" | Out-Host
  144.                   $Body = $Body + "`r`n Server = $Servername - Uptime = $Uptime.  "
  145.                   $Body = $Body + "`r`n Server = $ServerName - Will be rebooted by this script.  Its last reboot was on $LastRebootTime.  "
  146.                   $Body = $Body + "`r`n " 
  147. #                 Shutdown  -r  -f  -m  \\$ServerName -c "A non-restarting Windows Update occurred requiring a system restart for application reasons"
  148. #                 ####################################################################################################################################
  149. #                 The business end of this script.  Uncomment out the above line of code to conditionally restart the servers in your $InputFile.
  150. #                 ####################################################################################################################################
  151.                }
  152.             Else
  153.                {
  154. #                 No need to restart this server.               
  155.                   "This server $Server appears to have been restarted within the last 30 minutes." | Out-Host
  156.                   $Body = $Body + "`r`n  Server = $Servername - Uptime = $Uptime.  "
  157.                   $Body = $Body + "`r`n  Server = $ServerName - Was not rebooted by this script.  Its last reboot was on $LastReBootTime.  "
  158.                   $Body = $Body + "`r`n " 
  159.                }
  160.          }
  161.       Else
  162.          {
  163. #                This server does not ping and can not be managed by this script.         
  164.                  $StaffAlertWarning = $True
  165.                  $Body = $Body + "`r`n *** Warning ***.  "
  166.                  $Body = $Body + "`r`n Server = $ServerName - Is not currently pingable and therefore can not be managed by this script.  "
  167.                  $Body = $Body + "`r`n " 
  168.          }
  169.    }
  170. #
  171. #
  172. ############################################
  173. # Main Routine                             #
  174. ############################################
  175. #
  176. ################################################### Initializations ###########################################################
  177. $StartDate = Get-Date 
  178. Set-Location "C:\Program Files\Scripts\"
  179. $InputFile = "C:\Program Files\Scripts\GroupA-ConditionalForcedRestartServers.csv"
  180. # $DoNotSendSpam = "C:\Program Files\Scripts\ManagersAndOnCallStaff.csv"
  181. ####################################################### Step 1 ################################################################
  182. Import-Csv $InputFile | ForEach-Object -Process {.$Check_If_Boot_Required}
  183. ####################################################### Step 2 ###############################################################
  184. $mail = New-Object System.Net.Mail.MailMessage
  185. $mail.From = New-Object System.Net.Mail.MailAddress("kcriss@iot.in.gov");
  186. $mail.To.Add("EmailRecipient1@yourDomain.com");
  187. # $mail.To.Add("EmailRecipient2@yourDomain.com");
  188. # $mail.To.Add("EmailRecipient3@yourDomain.com");
  189. # $mail.To.Add("EmailRecipient4@yourDomain.com");
  190. # $mail.To.Add("EmailRecipient5@yourDomain.com");
  191. If ($StaffAlertCritical -eq $True)
  192.    {
  193. #    Import-Csv $DoNotSendSpam | ForEach-Object -Process {$EmailAddress=$_.EmailAddress;$Mail.To.Add("$EmailAddress")}
  194.      $Body = $Body + "`r`n *** Critical error detected notify the primary applications contact.  "
  195.      $Body = $Body + "`r`n *** Critical error detected notify the primary system administration contact.  "  
  196.   }
  197. $date=date
  198. $ShortDate=$date.toshortdatestring()
  199. $ShortTime=$date.toshorttimestring()
  200. $mail.Subject = "ProjectName Conditional Forced Server Restart "+"$ShortDate"+" at "+"$ShortTime";
  201. $Span = [TimeSpan]((get-date- $StartDate)
  202. $ElapseTime =$Span.tostring()
  203. $Body = $Body + "`r`n "
  204. $Body = $Body + "`r`n Elapse runtime = $ElapseTime"
  205. "Elapse runtime = $ElapseTime" | Out-Host
  206. " " | Out-Host 
  207. $DynamicSubject = $Null 
  208. If ($StaffAlertWarning)  { $DynamicSubject = " with Warning Errors!" }
  209. If ($StaffAlertError)    { $DynamicSubject = " with Severe Errors!" }
  210. If ($StaffAlertCritical) { $DynamicSubject = " with Critical Errors!" }
  211. $mail.Subject += $DynamicSubject 
  212. $mail.body = $Body
  213. # ./Highlight-syntax.ps1 ./ConditionalForcedServerRestart.ps1 -Linenumbers | Out-File "C:\Program Files\Scripts\ConditionalForcedServerRestart.html"  
  214. # The above line of code requires another script which is available free from the Sapiens scripting vault.
  215. # $mail.attachments.add("C:\Program Files\Scripts\ConditionalForcedServerRestart.html")
  216. $smtp = New-Object System.Net.Mail.SmtpClient("YourMailrelay.YourDomain.Com");
  217. $smtp.Send($mail)

JaykulUser is Offline
New Member
New Member
Posts:31

--
17 May 2008 05:28 AM  

This one also ought to go on the PowerShellScripting.com/scripts (not to say that you shouldn't put it here, just that it looks useful, and will have a better audience there -- especially as we've got some improvements in mind for the script repository, and we'll be bringing the existing scripts over.

My main suggestion would be to move from the huge scriptblock to having another function.

If you take like 118 and 119 and change them from this:

   $Check_If_Boot_Required = {

to this:

   function Test-BootRequired { PROCESS {

and then close it with two }} on line 169 ...

Then I believe you can rewrite line 182 to be more efficient, and clearer, as well.  Of course, you can invoke the scriptblock directly too (just like the function) -- if you put the PROCESS{...} around your code in your scriptblock, you could just pipe

Import-CSV $inputFile| &$Check_If_Boot_Required

-- but I think it's generally a better idea to store your scriptblocks in the function provider instead of in the variable provider.  Your line would end up like this:

 

   Import-Csv $InputFile | Test-BootRequired

By the way, does this send an email regardless of whether a reboot has been performed? I haven't run it yet...

You are not authorized to post a reply.

Active Forums 4.1
right
   
footer Sponsored by Quest Software • SAPIEN Technologies • ShellTools, LLC • Microsoft Windows Server 2008 footer
footer