Script done : emails when server is down with conditions.

by izde61 at 2012-09-24 06:08:16

i have this project where;

1) send two ping to multiple servers from txt file containing only ipaddress
2) create a new text file with timestamp, ipaddress, alive/dead
3) repeat that every 15mins
4) email output file to admins in html table format whenever there is a dead server

ive tried searching all over and im done with 1,3,4. it’s no. 2 that i cant find. cos the original txt file is in this format;

ipaddress
10.1.1.1
10.2.3.4

then the output file should be in this format

timestamp,ipaddress,status
ddmmyyhhmm,10.1.1.1,alive
ddmmyyhhmm,10.2.3.4,dead

so that when i email the html file it would be in a nice table.

so yeah, help!!!

thanks!
by DonJ at 2012-09-24 06:33:18

function Test-Connections {
foreach ($item in (import-csv filename.csv) {
$ipaddress = $item.ipaddress
if (test-connection $ipaddress -quiet) {
$status = ‘alive’
} else {
$status = ‘dead’
}
$timestamp = (get-date).tofiletime()
$props = @{‘timestamp’,$timestamp;‘ipaddress’=$ipaddress;‘status’=$status}
$obj = new-object -type psobject -prop $props
write-output $obj
}

Test-Connections | Export-CSV output.csv
Import-CSV output.csv | ConvertTo-HTML | Out-File output.html
# Put a Send-MailMessage here, attaching the output.csv or output.html file


You would then schedule this to run in Task Scheduler. Seriously… every 15 minutes? I’d hate to be on the receiving end of that! The trick is to modularize, which is why I’ve written this as a function.
by izde61 at 2012-09-24 19:50:23
alright! thanks man! tweaking begins!
by izde61 at 2012-09-27 04:58:54
Finished the PS script guys! Hahaha. It’s not secure and very noob-ish with the logics. So if you guys know anyway to shorten/improve it, it’ll be great! ;D

Basically what it does is;

- It contains three functions, namely; logstamp, Test-Connections, SendOut-EmailFail.
- It will be looping in a while($true) manner in the main body
- It will create two .csv files; one for emailing purposes, one for logging.
- It will only send a warning e-mail if dead pings of the servers exists in two time stamps.
- It loops every 15 minutes.(But in the test I put it to 1 second)

- In the loop, it will do;
1 - Test connection with a list of server. Checks and tags the servers that are "Up" or "Down" using the Test-Connection function.

2 - It will then output a .csv file with the following format;

#TYPE System.Management.Automation.PSCustomObject
"Timestamp","IPAddress","Status"
"27/09/2012-19:18","10.5.0.64","Down"
"27/09/2012-19:18","10.5.0.65","Up"

^ This format can be read by Import-csv.

3 - Next it import the previous outputs a .csv in this format(using Format-Table -Wrap -AutoSize) ;

Timestamp IPAddress Status
--------- --------- ------
27/09/2012-19:02 10.1.1.1 Down
27/09/2012-19:02 10.1.1.2 Up

^This format cannot be read by Import-csv, but it looks more pleasant thus this becomes the log file. Plus the log will always be written because of the -append function.

4 - There is a $count in the Test-connection

{
$status = ‘Down’
$count = $count + 1
if ($count -gt 0){
$count = 0
$global:i = 1}

^This is just a math logic(or whatever it’s called) that I created so that when there’s a down ping $count will become 1, then the conditional will reset $count and create global variable $i with value 1 –> to be used in the main body.

5 - This is where the global variable $i will be used.

if ($global:i -eq 1)
{
$global:x = $global:x + 1
$global:i = 0
}

^ Basically when $i -eq to one(due to a down ping that exists in the time stamp), it will create a global variable $x which will increment with every time stamp that has a down ping. Then it will reset $i to 0 so that in the next loop, if there are no dead pings…

6 - This will not happen

if ($global:x -eq 2)
{
SendOut-EmailFail
}

^ So ONLY when $x equals to 2(when it is greater than 2, it will not send an e-mail. To prevent spam.), it will send out a warning e-mail. Note :- This was the part where I got stuck the longest.

7 - It will then sleep for 900 seconds and restart the loop.

So there you have it! Took me four days to complete such a simple script, then again, I started with zero knowledge of PowerShell. :smiley: :smiley: :smiley:

BTW : - The part that is not secure is in the e-mail. Cos I use this;

$c = get-credential -credential "domain\username"
$c.password | convertfrom-securestring | set-content "~filepath~*.txt"

To save the credentials to a text file then use this;

$global:password = get-content "~filepath~*.txt" | ConvertTo-SecureString
$global:credential = New-Object System.Management.Automation.PsCredential($global:user,$global:password)

To convert the text file back.




Here’s the full view of the code for your perusal.

# Variables #

$global:timestamp = logstamp
$count = 0
$global:i = 0
$global:x = 0

# E-mail Items #
# Insert To, From, Subject, SMTP Server, User, Credentials in this block
$global:From = "~email~"
$global:To = "~email~"
$global:smtp = "~smtp server~"
$global:user = "~user~"
$global:password = get-content "~filepath~.txt" | ConvertTo-SecureString
$global:credential = New-Object System.Management.Automation.PsCredential($global:user,$global:password)

#----------------------------------------------------------------------------------#
# Function : Logstamp - To create the timestamp in dd/MM/yyyy-HH:mm format
function logstamp
{
(get-date).ToString(‘dd/MM/yyyy-HH:mm’)
}

#----------------------------------------------------------------------------------#
# Function : Test Connection - To ping the servers listed in the .csv file and has a count logic for "Down" servers
# Outputs with a Timestamp IPAddress Status format for the .csv file
function Test-Connections {
foreach ($item in import-csv "~filepath~") {
$ipaddress = $item.IPAddress
if (test-connection $ipaddress -count 2 -quiet) {
$status = ‘Up’
}
else {
$status = ‘Down’
$count = $count + 1
if ($count -gt 0){
$count = 0
$global:i = 1}
}
$props = @{‘Timestamp’=$global:timestamp;‘IPAddress’=$ipaddress;‘Status’=$status;}
$obj = new-object -type psobject -prop $props
write-output $obj
}
}

#----------------------------------------------------------------------------------#
# Function : Sends warning e-mail "Dead" servers
function SendOut-EmailFail
{
foreach ($item in import-csv "~filepath~")
{
$ip = $item.IPAddress
$stat = $item.Status
if ($stat -eq "Down")
{
$subject = "Warning : Server with IP : $ip is down at $timestamp"
$body = "What’s up Jim? This is a test e-mail."

Send-MailMessage -to $global:To -from $global:From -Credential $credential -subject $subject -smtpServer $global:smtp -body $body
}
}
}

#----------------------------------------------------------------------------------#
# Main Body of Script
# Script will test-connections of servers and logs to .csv
# Script will test-connections of servers and overwrites .csv. The extra .csv is for the SendOut-Email function.
# Script will send email after two "Dead" test-connections of servers
# Script will loop until it is manually aborted
while($true)
{
Test-Connections | Export-csv "~filepath~"
Import-csv "~filepath~" | Format-Table -Wrap -AutoSize |out-file "~filepath~" -append
if ($global:i -eq 1)
{
$global:x = $global:x + 1
$global:i = 0
}
if ($global:x -eq 2)
{
SendOut-EmailFail
}
start-sleep 900
}


PROBLEM :-
Because it will only e-mail after two dead pings. The only was to reset the counter is to stop the script and restart it again(after the server is brought back up).

HELP :-
Now, what I need is 2 .vbs/.bat/.ps1 script to start and stop the above script? Any hints? Which is the best way to go? .bat or .vbs?


Thanks! Please post me improvements for the script and comment if there are ways to shorten it. :slight_smile:
by Klaas at 2012-09-27 12:59:36
Well, you had four days of good Powershell training :slight_smile: but there are other monitoring solutions.
I’m using icinga: https://www.icinga.org/.
by izde61 at 2012-09-27 18:46:56
So icinga is free? D’oh!

But yea, I really like the challenge of creating the scripts and now I feel like doing some more scripts. Hahaha. Or improving the above script. :smiley: