The Surly Admin

Father, husband, IT Pro, cancer survivor

Simple Server Status

A little while back the Microsoft Scripting Guy, Ed Wilson, blogged about creating a simple web page with server uptime.  It was an interesting use of some of the Powershell capabilities and the output was pretty good, if a little uninspiring–not his fault I might add, more a limitation of the Powershell tools he was trying to use.  I didn’t do anything about the script at the time, but it always intrigued me.  Then the other day a very similar request came across on Spiceworks.  At first I just gave the guy the same link I put above, but now the bug was in my ear and I decided to write something up.

There is a new version of Simple Server Status and I talk a little bit more about it here.

Already there

The interesting thing is, most of this script was already written.  Ed had the Uptime information already in his script, and I’ve recently been working on updating my Employee Directory with Photo’s webpage converting it from vbScript to Powershell (more on that next week).   So the basics were already there.

The first part, and by far the hardest part, of this script was writing the HTML.  While I like to think I’m pretty good at Powershell–but not at Guru status yet–when it comes to HTML and CSS I’m frankly still at the beginning stages.  But something like this I can handle!  So I broke out trusty Notepad++ and started stealing CSS from some of my other scripts.  By the way, if you haven’t tried Notepad++ you should, it’s really a good text editor.  In fact, I use it so much I created an alias in my Powershell profile to use it:

set-alias npp 'C:\Program Files (x86)\Notepad++\notepad++.exe'

I then spent the next hour or so playing with CSS and my HTML until I had a mock up of the webpage I wanted.  Once I had what I wanted it was a simple matter of copying and pasting the code into a here-string and then getting down to the business of getting the status information.

Param (
[array]$Servers = (Get-Content "c:\utils\servers.txt"),
[string]$Path = "c:\utils\uptime.html"
)

First, a couple of variables to setup.  $Servers will be an array of server names either from a default file called servers.txt or from a parameter.  The other variable is where to put the HTML file when it’s ready, again with a default that you can change to fit your environment.  After that I set my here strings with the static HTML, which I won’t post here because it’s too long and this is not a CSS or HTML blog!

ForEach ($Server in $Servers)
{ Write-Host "Testing $Server..."
If (Test-Connection $Server -Quiet)

Next up we need to loop through the $Servers variable and test if the server is up or down using the Test-Connectivity cmdlet.  Normally Test-Connectivity returns an object with server name, ping times, IPv4 and IPv6 information and a little bit more (Test-Connectivity is essentially PING repackaged) but for this script all I want to know is if the server is there or not.  To do that we use the -Quiet parameter which will return a $true value when the server is there and a $false value when it isn’t.

$WMI = Get-WmiObject Win32_OperatingSystem -ComputerName $Server
If ($WMI)
{ $Uptime = New-TimeSpan -Start $($WMI.ConvertToDateTime($WMI.LastBootUpTime)) -End (Get-Date)
$UpText = "$($Uptime.Days) days, $($Uptime.Hours) hours, $($Uptime.Minutes) minutes"
}
Else
{ $UpText = "Up"
}
$DetailHTML += "<tr><td>$Server</td><td class=""up"">$UpText</td></tr>`n"

In order to get the Uptime information we need to use WMI.  Specifically we want the Win32_OperatingSystem class and the LastBootUpTime property.  Unfortunately, LastBootUpTime is not a proper DateTime variable type so we’ll need to use the .ConvertToDateTime method on it.  I could have seperated that conversion out and assigned it to another variable, then use Get-Date to get today’s date (since Today minus LastBootUpTime would equal the amount of uptime) and assign that to another variable and to be honest that would probably be easier to read, but I find with Powershell I often don’t assign variables if I don’t need them.  If I only need something once then why waste the lines of code by assigning it to a variable and then testing against that variable or using it in another cmdlet?  Just put it all in the one line and be done with it.  I did the same thing with the Test-Connectivity cmdlet above.

New-Timespan is a great little cmdlet for calculating the time between two dates.  It actually does a bunch of other things too so run Get-Help New-Timespan -Full in your Powershell prompt to see what I mean.  But for this script simply using the -Start and -End parameters and putting the dates I want into it loads the $Uptime variable with the information I need.  Here’s the available properties from New-Timespan.

There’s a lot of information coming out of New-Timespan but the 3 properties I’m interested in are Days, Hours and Minutes.  So I build a text string with those 3 values in it and then build the HTML code I’ll need.

You may have noticed the If ($WMI) test in there?  As sometimes happens with WMI, the WMI call may not work.  It’s also possible the machine we’re testing won’t be a Windows so we’ll test if $WMI is “not $null” in which case we’ll do the uptime information, but if the test fails (meaning $WMI is a $null) then we’ll just report that the computer is up, we just won’t know any other information about it.

Else
{ $DetailHTML += "<tr><td>$Server</td><td class=""down"">DOWN</td></tr>`n"
}

Going back to our original connectivity test, if it fails then we want to know that too.  So add the HTML with that information (using a different td class of “down” which give us a nice red cell) and move on to the next server in the array.

$HTML = $HeaderHTML + $DetailHTML + $FooterHTML
$HTML | Out-File $Path

Almost done.  First we have to combine the two here strings that contain the static HTML in them with the detailed HTML we created scriptomatically and finally save all of that to the file you designated in $Path.  The result?  A nice little web page giving you server status and uptime.

I have updated this script to include “Lowest Disk Status”, which means the disk with the lowest amount of disk space available is on the main status page and gives you some information about that disk (v1.5).  I’ve also included a Detail Disk Report (v1.6) that shows you all of the disks on every server.

Get Source Code here.

October 11, 2012 - Posted by | PowerShell | , ,

7 Comments »

  1. […] they were trying to use so I asked them to post the relevant code and, lo and behold, it was my Simple Server Status script!  He was having a problem with authentication because the ID he was running the script […]

    Pingback by New Version: Simple Server Status « The Surly Admin | May 7, 2013 | Reply

  2. Dear Sir, thanks for your script its very helpful to me, please help me on below points

    1. how to add the command to send the email to my ID.
    2. how can I give the different color to the server not rebooted more than 30 Days

    Comment by Ravindra Pawar | September 20, 2013 | Reply

    • Hmm… the email wouldn’t be too hard, just and a Send-MailMessage at the bottom and attach the HTML file that the script created.

      Different color for a server that hasn’t rebooted in 30 days, that’s actually a pretty cool idea! Two things you’d have to do. You’d have to create a DIV with the color your wanted (or reuse RED) in the CSS, which is in the $HeaderHTML variable. Next, right around line 339 you see $UpText where the cell with uptime is created. You could put an IF statement right there that checked $UpTime.Days -gt 30, and if it is you put the cell in there with the style reference to the DIV you created (or RED) and if it’s false you put in the cell that’s already in the script.

      Comment by Martin9700 | September 20, 2013 | Reply

  3. […] I set out adding those capabilities, and even added a cool bar graph that I had developed for the Simple Server Status […]

    Pingback by ConvertTo-AdvHTML – New Advanced Function for HTML Reporting « The Surly Admin | February 27, 2014 | Reply

  4. Thanks for the great stuff. But is there anyway to sort the output result according to status (machine uptime) or sort all the machine with %free accensding. Thanks

    Comment by Ho | July 28, 2016 | Reply

    • Ho, anything is possible. I don’t really have time to support this anymore but you are more than welcome to start development on your own. I’ve posted the script out on GitHub so feel free to fork it and start development. If it’s a cool update make sure to issue a pull request and I’ll merge it into the primary script.

      https://github.com/martin9700/SimpleServerStatus

      Comment by Martin9700 | July 28, 2016 | Reply

  5. Why Query failed on Online servers?

    Comment by AS | June 4, 2019 | Reply


Leave a reply to ConvertTo-AdvHTML – New Advanced Function for HTML Reporting « The Surly Admin Cancel reply