Richard's profileRichard Siddaway's BlogPhotosBlogLists Tools Help

Blog


    February 14

    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 6006\6005 shutdown & start respectively
    for ($i = 1; $i -le $events.count-2; $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 6005\6006 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.

     

    Comments (3)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    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.
    Feb. 16
    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 things
    a) 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 simple
    b) I wanted to combine the event log and WMI approaches
    c) I wanted to show some of the checks that should do into a script when it becomes production ready

    The colour script I did by using the PowerShell ISE in v2 and using this script with it
    http://blogs.msdn.com/powershell/archive/2009/01/13/how-to-copy-colorized-script-from-powershell-ise.aspx
    it has been updated
    http://www.leeholmes.com/blog/MorePowerShellSyntaxHighlighting.aspx

    The 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
    Feb. 16
    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?
    Feb. 16

    Trackbacks

    The trackback URL for this entry is:
    http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!2068.trak
    Weblogs that reference this entry
    • None