Machine UpTime

The February copy of TechNet magazine dropped through the letter box this morning. In the UK we get our own version so some of this may be a bit older than this months edition.  There is a nice article by Marco Shaw on using PowerShell with System Center Operations Manager that is well worth reading.

The article that really got me thinking was the one about calculating server uptime using information from the event logs. The script is actually measuring the availability of the event log service but it is very close to the available time.

One thing that really leapt out was that the main script was using PowerShell v2 – it had a #Requires –version 2.0

statement at the top.  As v2 is still in CTP that didn’t seem right.  The whole script looked over complicated so I started playing around and came up with this:

$days = 30
$now = Get-Date
$start = (Get-Date -Hour 00 -Minute 00 -Second 00).AddDays($days)
"Checking Last Boot Time"
$os = Get-WmiObject -Class Win32_OperatingSystem
$lastboot = $os.ConvertToDateTime($os.LastBootUpTime)
if ($lastboot -lt $start){ Write-Host "Server continually up for whole period"; Return}
else {Write-Host "Server restarted since start of period – analysis continuing"}

"Reading Event Logs"
$events = Get-EventLog -LogName system | where{(($_.EventId -eq 6005) -or ($_.EventId -eq 6006)) -and $_.TimeGenerated -ge $start } | Select EventId, TimeGenerated, Index

## should start with a 6005 – log service started event
if ($events[0].EventId -eq 6005){
    $totaluptime = $now  $events[0].Timegenerated
}
else {
    Write-Host "Error reading log – startup is not first entry"
    Return
}

#check the last
$last = $events | select -Last 1
if ($last.EventId -eq 6006){      ## shutdown
    $totaluptime += ($last.TimeGenerated  $start)
}

## events should be paired 60066005 shutdown & start respectively
for ($i = 1; $i -le $events.count2; $i += 2){
    if ($events[$i].EventId -eq 6006){      ## shutdown
        if ($events[$i+1].EventId -eq 6005){      ## Startup
            $totaluptime += ($events[$i].Timegenerated  $events[$i+1].Timegenerated)
        }
        else {
            Write-Host "Error in log sequence at " $event[$i+1]
            Return    
        }
    }
    else {
        Write-Host "Error in log sequence at " $event[$i]
        Return    
    }
}
## calculate uptime
$totaltime = $now  $start
$percUptime = (($totaltime.TotalHours  $totaluptime.TotalHours)/$totaltime.TotalHours)*100

"Uptime for period $($start.ToLongDateString()) to $($now.ToLongDateString())"
"Total time available: {0:n2} hours" -f $($totaltime.TotalHours)
"Total Uptime: {0:n2} hours" -f $($totaluptime.TotalHours)
"Percentage Uptime: {0:n2} %" -f $percUptime
"Percentage Downtime: {0:n2} %" -f (100  $percUptime)

 

We start by defining some variables – the number of days we want to analyse, current date and our starting point.

The first check is on when the server was actually started – if it was before the beginning of our period then we have 100% up time and the bonus is in the bank.  We can check this using WMI.  The only awkward bit is converting the boot time to a format we can work with.

Assuming that our server was started since the start of out analysis period then we need to look at the logs.  We can read the system event log looking for eventids 6005 and 6006 as shown. We only want events since the start of our period.

The event logs are writing in chronological order and are returned in the same order with the youngest returned first.  I have yet to see an instance of pulling information from the logs when this wasn’t the case.

The first (youngest) event should be a 6005 – event log service started.  We create a timespan by subtracting that time from the current time which gives us up time since the last restart. If this isn’t the case then we have a problem that needs to be investigated so the script stops.

A check is made to see if the last event is a shutdown – in which case we need to calculate the uptime from the start of the period to shutdown and add it to the total.

The 60056006 events should be paired after this with a 6006 (shutdown) followed by a 6005 (startup) – remember we are working backwards in time.  Assuming we find our pairs of events as expected we calculate the timespan between the events and add it to our total uptime.  If the pairings don’t match up then we have an issue to be investigated so the event information is written to screen to give a starting point for analysis.

We then calculate the total timespan of our period and the percentage uptime.  Finally we print out our results.

I think this is easier to follow and seems to work correctly in my testing environment. Remember that this runs on the local machine as written.  It can be made to work on remote machines – Get-WmiObject accepts a computer name parameter as does get-eventlog in PowerShell v2.  If you are using v1 then you could access the remote logs using WMI.

 

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

5 Responses to Machine UpTime

  1. Chris says:

    Just curious, couldn’t we just use uptime.exe to get an instant report of the uptime of a system? It does require an extra dependency, but it’s super fast and accurate. Just a thought.More to the point though, I’m brand new to blogging and I chose spaces.live.com based on your snazzy colored script in this post. I’m learning Powershell and would like to post scripts in a readable format as you’ve done here.What do you use if I may ask?

  2. Richard says:

    Yes – you could use uptime.exe. Haven’t tested it against Win 2008 but I assume it would work. This post was based on a couple of thingsa) I wanted to write a simpler version of the script in TechNet magazine. I think sometimes the PowerShell experts forget that there a lot of people still new to the game – so a need to keep it simpleb) I wanted to combine the event log and WMI approachesc) I wanted to show some of the checks that should do into a script when it becomes production readyThe colour script I did by using the PowerShell ISE in v2 and using this script with ithttp://blogs.msdn.com/powershell/archive/2009/01/13/how-to-copy-colorized-script-from-powershell-ise.aspxit has been updated http://www.leeholmes.com/blog/MorePowerShellSyntaxHighlighting.aspxThe original script crashes my version of Live Writer so I just paste ordinary text, publish as draft and then paste the colorised script using the editor on the blog. I’ll try Lee’s version and see if that is better with Live Writer

  3. Chris says:

    Thanks Richard for the colorized copy stuff. Much appreciated!!Also for breaking down the event log stuff. I’m using it to help understand a different problem I’m working on.You rock.

  4. Mohan says:

    Hi Richard I am trying this script but I am running into an error with Event ID 6008 unexpected shutdown. How could you calculate the 6008 along with the 6006 Event ID. Thank for your help.

  5. Jacob says:

    Ran this on my home PC, came out 51% uptime, 49% downtime. And it’s nearly always shut off or in sleep mode when I’m not in front of it.
    I need to turn my life around 😐
    Thanks Richard for providing some momentum…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s