header1   header
header
header Register : : Login header
header
connector   connector
menuleft menuright
submenu   submenu
left
ConditionalForcedServerRestart.ps1
Last Post 16 May 2008 09:28 PM by Joel "Jaykul" Bennett. 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:128

--
20 Mar 2008 11:03 AM

    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/4...0485 
    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)

    My blog: http://blogs.powershellcentral.com/kscriss/
    Joel "Jaykul" BennettUser is Offline
    Basic Member
    Basic Member
    Posts:112
    Avatar

    --
    16 May 2008 09:28 PM

    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.3
    right
    footer   footer
    footer Sponsored by Quest Software • SAPIEN Technologies • Compellent • Microsoft Windows Server 2008 R2 footer
    footer   footer