
Hey, Scripting Guy! Calculating server uptime p is up and down is down. THE MICROSOFT SCRIPTING GUYS ANSWER Seems rather obvious – ex- U cept, that is, when you’re How can I use the System event talking about server uptime. To know uptime, you need to know downtime. log to find server uptime? Nearly every network administrator is concerned about server uptime. (Ex- it generally makes sense to see what When you subtract one time value cept, that is, when he is worried about type of data is being used. from another, you are left with an in- server downtime.) Most administrators To examine the data the script is stance of a System.TimeSpan object. have uptime goals and need to provide using, you can simply print it to the This means you can choose how to dis- uptime reports to upper management. screen. Here’s what you get: play your uptime information without What’s the big deal? It seems like PS C:\> $wmi.LocalDateTime having to perform a lot of arithmetic. you could use the Win32_Operating- 20080905184214.290000-240 You need only choose which proper- System WMI class, which has two ty to display (and hopefully you count The number seems a bit strange. properties that should make such an your uptime in TotalDays and not in What kind of a date is this? To find out, operation pretty easy: LastBootUp- TotalMilliseconds). The default dis- use the GetType method. The good Time and LocalDateTime. All you need play of the System.TimeSpan object is thing about GetType is that it is near- to do, you think, is subtract the Last- shown here: ly always available. All you need to do BootUptime from the LocalDateTime, is call it. And here’s the source of the Days : 0 and then all is right with the world Hours : 0 problem – the LocalDateTime value is Minutes : 40 and you can even go catch a quick nine Seconds : 55 being reported as a string, not as a Sys- holes before dinner. Milliseconds : 914 tem.DateTime value: Ticks : 24559148010 So you fire up Windows PowerShell TotalDays : 0.0284249398263889 PS C:\> $wmi.LocalDateTime.gettype() TotalHours : 0.682198555833333 to query the Win32_OperatingSystem TotalMinutes : 40.93191335 WMI class and select the properties, as IsPublic IsSerial Name BaseType TotalSeconds : 2455.914801 -------- -------- ---- -------- TotalMilliseconds : 2455914.801 shown here: True True String System.Object The problem with this method is PS C:\> $wmi = Get-WmiObject -Class Win32_ that it only tells you how long the OperatingSystem If you need to subtract one time from server has been up since the last re- PS C:\> $wmi.LocalDateTime - $wmi.LastBootUpTime another time, make sure you’re dealing start. It does not calculate downtime. with time values and not strings. This But when you run these commands, This is where up is down – to calculate is easy to do using the ConvertToDate- you are greeted not with the friend- uptime, first you need to know the Time method, which Windows Power- ly uptime of your server, but by the downtime. Shell adds to all WMI classes: rather mournful error message you see So how do you figure out how long PS C:\> $wmi = Get-WmiObject -Class Win32_ in Figure 1. OperatingSystem the server has been down? To do this, The error message is perhaps a bit you need to know when the server PS C:\> $wmi.ConvertToDateTime($wmi.LocalDateTime) – misleading: “Bad numeric constant.” $wmi.ConvertToDateTime($wmi.LastBootUpTime) starts and when it shuts down. You can Huh? You know what a number is and you know what a constant is, but what does this have to do with time? When confronted with strange er- Figure 1 An error is ror messages, it’s best to look directly returned when trying to at the data the script is trying to parse. subtract WMI UTC time Moreover, with Windows PowerShell, values TechNet Magazine February 2009 71 Hey, Scripting Guy! get this information from the System event log. One of the first processes that starts on your server or worksta- tion is the event log, and one of the last things that stop when a server is shut down is the event log. Each of these start/stop events generates an eventID – 6005 when the event log Figure 2 The event log service starts and 6006 when the event log starts shortly after computer stops. Figure 2 shows an example of startup an event log starting. By gathering the 6005 and 6006 events from the System Log, sort- Figure 3 CalculateSystemUpTimeFromEventLog 3 ing them, and subtracting the starts #--------------------------------------------------------------- from the stops, you can determine the # CalculateSystemUpTimeFromEventLog.ps1 amount of time the server was down # ed wilson, msft, 9/6/2008 # between restarts. If you then subtract # Creates a system.TimeSpan object to subtract date values # Uses a .NET Framework class, system.collections.sortedlist to sort the events from eventlog. that amount from the number of min- # utes during the period of time in ques- #--------------------------------------------------------------- #Requires -version 2.0 tion, you can calculate the percentage Param($NumberOfDays = 30, [switch]$debug) of server uptime. This is the approach if($debug) { $DebugPreference = " continue" } taken in the CalculateSystemUpTi- meFromEventLog.ps1 script, which is [timespan]$uptime = New-TimeSpan -start 0 -end 0 $currentTime = get-Date shown in Figure 3. $startUpID = 6005 The script begins by using the Par- $shutDownID = 6006 $minutesInPeriod = (24*60)*$NumberOfDays am statement to define a couple of $startingDate = (Get-Date -Hour 00 -Minute 00 -Second 00).adddays(-$numberOfDays) command-line parameters whose val- Write-debug "'$uptime $uptime" ; start-sleep -s 1 ues you can change when you run the write-debug "'$currentTime $currentTime" ; start-sleep -s 1 script from the command line. The write-debug "'$startingDate $startingDate" ; start-sleep -s 1 first, $NumberOfDays, lets you specify $events = Get-EventLog -LogName system | a different number of days to use in the Where-Object { $_.eventID -eq $startUpID -OR $_.eventID -eq $shutDownID ` -and $_.TimeGenerated -ge $startingDate } uptime report. (Note that I have sup- plied a default value of 30 days in the write-debug "'$events $($events)" ; start-sleep -s 1 script so you can run the script with- $sortedList = New-object system.collections.sortedlist out having to supply a value for the parameter. Of course, you can change ForEach($event in $events) { this if necessary.) $sortedList.Add( $event.timeGenerated, $event.eventID ) } #end foreach event The second, [switch]$debug, is a $uptime = $currentTime - $sortedList.keys[$($sortedList.Keys.Count-1)] switched parameter that lets you ob- Write-Debug "Current uptime $uptime" tain certain debugging information For($item = $sortedList.Count-2 ; $item -ge 0 ; $item -- ) from the script if you include it on { Write-Debug "$item `t `t $($sortedList.GetByIndex($item)) `t ` the command line when running the $($sortedList.Keys[$item])" script. This information can help you if($sortedList.GetByIndex($item) -eq $startUpID) { feel more confident in the results you $uptime += ($sortedList.Keys[$item+1] - $sortedList.Keys[$item]) Write-Debug "adding uptime. `t uptime is now: $uptime" get from the script. There could be } #end if times when the 6006 event log serv- } #end for item ice-stopping message is not present, "Total up time on $env:computername since $startingDate is " + "{0:n2}" -f ` perhaps as a result of a catastrophic $uptime.TotalMinutes + " minutes." $UpTimeMinutes = $Uptime.TotalMinutes failure of the server that rendered it $percentDownTime = "{0:n2}" -f (100 - ($UpTimeMinutes/$minutesInPeriod)*100) unable to write to the event log, caus- $percentUpTime = 100 - $percentDowntime ing the script to subtract an uptime "$percentDowntime% downtime and $percentUpTime% uptime." value from another uptime value and skew the results. 72 Visit TechNet Magazine online at: http://technet.microsoft.com/en-gb/magazine/default.aspx After the $debug variable is supplied erals. The get eventIDs are equal either from the command line, it is present to $startUpID or to $shutDownID. You on the Variable: drive. In that case, the should also make sure the timeGener- value of the $debugPreference varia- ated property of the event log entry is ble is set to continue, which means the greater than or equal to the $starting- script will continue to run and any val- Date, like so: ue supplied to Write-Debug will be vis- $events = Get-EventLog -LogName system | ible. Note that, by default, the value of Where-Object { $_.eventID -eq $startUpID -OR $_.eventID -eq $shutDownID -and $debugPreference is silentlycontinue, $_.TimeGenerated -ge $startingDate } so if you don’t set the value of $debug- Keep in mind that this command Preference to continue, the script will will only run locally. In Windows run, but any value supplied to Write- PowerShell 2.0, you could use the – Debug will be silent (that is, it will not computerName parameter to make be visible). the command work remotely. When the script runs, the resulting Figure 4 Debug mode displays a The next step is to create a sorted list output lists each occurrence of the tracing of each time value that is added to the uptime calculation object. Why? Because when you walk 6005 and 6006 event log entries (as you through the collection of events, you can see in Figure 4) and shows the up- are not guaranteed in which order the time calculation. Using this informa- out the number of minutes during the event log entries are reported. Even if tion, you can confirm the accuracy of period of time in question: you pipeline the objects to the Sort- the results. $minutesInPeriod = (24*60)*$NumberOfDays Object cmdlet and store the results The next step is to create an instance back into a variable, when you iterate of the System.TimeSpan object. You Finally, you need to create the through the objects and store the re- could use the New-Object cmdlet to $startingDate variable, which will hold sults into a hash table, you cannot be create a default timespan object you a System.DateTime object that repre- certain that the list will maintain the would use to perform date-difference sents the starting time of the reporting results of the sort procedure.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages5 Page
-
File Size-