header
header Register : : Login header
header
divider
menuleft
menuright
submenu
left

[August 25th, 2008] Check the home page regarding PowerShell related news from a brand new sponsor: Idera

Ping remote computers & Email Alert
Last Post 13 Nov 2007 09:39 PM by bsonposh. 43 Replies.
Printer Friendly
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Page 1 of 212 > >>
Author Messages
aalborzUser is Offline
New Member
New Member
Posts:56

--
06 Nov 2007 06:00 PM  
May be somebody has already written a powershell script for this, but I can't find it:

Continuously monitor remote computers by pinging their IP address, wait for 30 seconds per attempt and then send an email once per status changes to fail or success.

Any ideas?

TIA

ALEX
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
06 Nov 2007 06:04 PM  
I just answered this not to long ago on EE... Let me go look for it
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
06 Nov 2007 06:05 PM  
Here it is... let me know if you have problems.. the guy never got back

Param($ip,$count,$email)
# Send Email Function
function Send-Mail{
    Param($msg,$relay,$from,$to,$subject,[switch]$html)
    $SmtpClient = new-object system.net.mail.smtpClient 
    $MailMessage = New-Object system.net.mail.mailmessage 
    $SmtpClient.Host = $relay
    $mailmessage.from = $from 
    $mailmessage.To.add($to) 
    $mailmessage.Subject = $subject
    if($html)
    {
        $mailmessage.IsBodyHtml = 1 
        $mailmessage.Body = $msg
    }
    else
    {
        $mailmessage.Body = $msg
    }
    $smtpclient.Send($mailmessage)
}
# Counter for Pings. Will ping 4 times per go.
for($i = 0;$i -lt $count;$i++)
{
    # Capture ping output in $result
    $result = ping.exe $ip
    # Send email... need to fill this out with your info
    Send-Mail -msg $result -relay -from -to -subject
    # Sleep for a Second
    Start-Sleep 1
}
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
06 Nov 2007 06:07 PM  
btw.... you can use a wmi ping if you wish... It looks like all you want is success or fail.

Actually.. maybe its better to get a more detailed idea of what your wanting
aalborzUser is Offline
New Member
New Member
Posts:56

--
06 Nov 2007 06:19 PM  
Thanks Brandon! Basically I want to be able to ping whole bunch of servers continuously and send an email alert if there's no response.

I'll be testing your script shortly.

Thanks again

Alex
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
06 Nov 2007 06:25 PM  
Define "no response." You mean if you drop any packets? Or do you have an exceptable limit? All machines lose packets every now and again.
aalborzUser is Offline
New Member
New Member
Posts:56

--
06 Nov 2007 06:40 PM  
By "no response" I mean the equivalent of usual four timeout Replies you get when you ping from a command prompt.
Right now I'm using a utility called "FreePing" that pings machines every 30 seconds and if the reply times out, it sends a NetSend popup message to my box. I just want to be able to do the same thing, but get email instead of the popup alert.

Btw pardon my ignorance, but how do I feed the list of my servers to your script?

Thx

ALEX
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
06 Nov 2007 06:55 PM  
I need to refactor a bit... See how this works

Param($list = (Throw "List is required"),$count=4,$email)
# Send Email Function
function Send-Mail{
    Param($msg,$relay,$from,$to,$subject,[switch]$html)
    $SmtpClient = new-object system.net.mail.smtpClient 
    $MailMessage = New-Object system.net.mail.mailmessage 
    $SmtpClient.Host = $relay
    $mailmessage.from = $from 
    $mailmessage.To.add($to) 
    $mailmessage.Subject = $subject
    if($html)
    {
        $mailmessage.IsBodyHtml = 1 
        $mailmessage.Body = $msg
    }
    else
    {
        $mailmessage.Body = $msg
    }
    $smtpclient.Send($mailmessage)
}
function Ping-Server {
   Param([string]$server)
   $pingresult = Get-WmiObject win32_pingstatus -f "address='$Server'"
   if($pingresult.statuscode -eq 0) {$true} else {$false}
}

while($true)
{
    foreach($server in (get-Content $list))
    {
        $x = 0
        for($i=0;$i -lt 4;$i++)
        {
            $result = Ping-Server $Server
            if(!$result)
            {
                $x++
                if($x -eq 4){Send-Mail -msg "Server Failed Ping" -relay -from -to -subject}
            }
        }
    }
}
aalborzUser is Offline
New Member
New Member
Posts:56

--
06 Nov 2007 07:06 PM  
PS is complaining about "Throw":

"The term 'throw' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again.
At C:\#PERSONAL\My Scripts\Scripts\PowerShell\Ping_Email_Alert.ps1:1 char:21
+ Param($list = (Throw  <<<< "List is required"),$count=4,$email)"
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
06 Nov 2007 07:32 PM  
Whoops.. I forgot the $... it should be
$list = $(Throw "List is Required")
marco.shawUser is Offline
Co-Community Director
Basic Member
Basic Member
Posts:177

--
07 Nov 2007 02:45 AM  
Posted By aalborz on 11/06/2007 10:00 AM
May be somebody has already written a powershell script for this, but I can't find it:

Continuously monitor remote computers by pinging their IP address, wait for 30 seconds per attempt and then send an email once per status changes to fail or success.

Any ideas?

TIA

ALEX


Brandon scripts are always easy to read because he uses functions which is great.  You still need the email sent based only on whether there is a status change though?  You'd want to write out fails maybe to a CSV file, then import that back in on each run to compare against the new failures/successes found.  That way you have a state-based alerting script.  I'll put something together if Brandon doesn't beat me to the punch... ;-)
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
07 Nov 2007 05:16 AM  
Its already there. If if fails ping 4 times it sends email :)
marco.shawUser is Offline
Co-Community Director
Basic Member
Basic Member
Posts:177

--
07 Nov 2007 05:15 PM  
Posted By bsonposh on 11/06/2007 9:16 PM
Its already there. If if fails ping 4 times it sends email <img src="/DesktopModules/NTForums/themes/_default/emoticons/smile.gif" align=absMiddle border=0>


Originally, the requestor wanted something that would alert when the status changes.  So if one runs the script every 5 minutes, one would get notified every 5 minutes that a server is down. 

What I had understood, is that a script that would only email out when the status actually changes.  So the script might run every 5 minutes, but if a server is down for 30 minutes, then back up, one would only have received "1 ping failed" email, then "1 ping now working" email.

Maybe I got it wrong...
aalborzUser is Offline
New Member
New Member
Posts:56

--
07 Nov 2007 05:45 PM  
When I run the script I get the following error in an infinite loop:

"+     foreach($server in (get-Content  <<<< $list))
Get-Content : Cannot bind argument to parameter 'Path' because it is null."

Also where do I specify which email address send the alerts to?

Thx
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
07 Nov 2007 05:57 PM  
Alrighty.. I added status change. Also.. for the email you need to setup the line and uncomment. Make sure to add relay, from, to, and subject
#Send-Mail -msg "Server Change Status to Dead" -relay -from -to -subject

Param($list = $(Throw "List is required"),$count=4,$email,[switch]$Verbose)
# Send Email Function
function Send-Mail{
    Param($msg,$relay,$from,$to,$subject,[switch]$html)
    $SmtpClient = new-object system.net.mail.smtpClient 
    $MailMessage = New-Object system.net.mail.mailmessage 
    $SmtpClient.Host = $relay
    $mailmessage.from = $from 
    $mailmessage.To.add($to) 
    $mailmessage.Subject = $subject
    if($html)
    {
        $mailmessage.IsBodyHtml = 1 
        $mailmessage.Body = $msg
    }
    else
    {
        $mailmessage.Body = $msg
    }
    $smtpclient.Send($mailmessage)
}
function Ping-Server {
   Param([string]$server)
   $pingresult = Get-WmiObject win32_pingstatus -f "address='$Server'"
   if($pingresult.statuscode -eq 0) {$true} else {$false}
}
if($Verbose){$VerbosePreference  = "Continue"}
$status = @{}
while($true)
{
    foreach($server in (get-Content $list))
    {
        $x = 0
        Write-Verbose "Processing Server $Server"
        for($i=0;$i -lt 4;$i++)
        {
            Write-Verbose "  Ping Count $i"
            $result = Ping-Server $Server
            if(!$result)
            {
                Write-Verbose '  Ping Failed Upping $x'
                $x++
                if($x -gt 3)
                {
                    if($status.$Server -ne "Dead")
                    {
                        Write-Verbose "Setting Server Status to Dead"
                        $Status.$Server = "Dead"
                        #Send-Mail -msg "Server Change Status to Dead" -relay -from -to -subject
                    }
                }
            }
            else
            {
                if($status.$Server -ne "Alive")
                {
                    Write-Verbose "Setting Server Status to Alive"
                    $Status.$Server = "Alive"
                    #Send-Mail -msg "Server Change Status to Alive" -relay -from -to -subject
                }
            }
        }
    }
    start-Sleep 30
}
aalborzUser is Offline
New Member
New Member
Posts:56

--
07 Nov 2007 09:53 PM  
I get "List is required". Where do I specify the list of the servers?
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
07 Nov 2007 09:56 PM  
PathtoScript\ScriptName.ps1 -list

I was going to have the number of times it pings, timeout, and email configurable, but I think for now see how you like it.
aalborzUser is Offline
New Member
New Member
Posts:56

--
07 Nov 2007 10:16 PM  
And that gives me the following:

Missing an argument for parameter 'list'. Specify a parameter of type 'System.Object' and try again.
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
08 Nov 2007 04:24 AM  
bleh.. darn tags the post removed the value after list. Here is an example

PS> c:\temp\ping-list.ps1 -list c:\temp\mylistfile.txt
aalborzUser is Offline
New Member
New Member
Posts:56

--
08 Nov 2007 02:33 PM  
Thanks actually I figured it was something like that. I created the text file with only one entry that I  know it should fail and ran the script with it.

So now the outcome should be an email either way or only if a server is down I will get an email?
But I'm not getting an email either way. Perhaps the problem is the email piece. The value in front of
"-relay" should be smtp.mycompany.com, right?

Also meanwhile the script will be running continuously until I kill it, right?
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
08 Nov 2007 03:04 PM  
Ok.. so what it should do
1) it sets the intial state (Alive or Dead)
2) it pings
- if state is same it doesnt do anything and goes to the next
- if state is dead and ping returns... it sets state to alive and emails
- if state is alive and the ping fails 4 times... it sets the state to dead and emails
3) it will run until killed

To be frank I didnt do ALOT of testing, but I did run it for a while and played with different states.

Q: "-relay" should be smtp.mycompany.com, right?"
A: Yes
aalborzUser is Offline
New Member
New Member
Posts:56

--
08 Nov 2007 04:14 PM  
Ok so shouldn't it display what it's doing at each step? I see few write-verbose statements
like this:

Write-Verbose "Processing Server $Server"
        ....
            Write-Verbose "  Ping Count $i"
            ...
                Write-Verbose '  Ping Failed Upping $x'
                ...
                        Write-Verbose "Setting Server Status to Dead"
                        ...
                    Write-Verbose "Setting Server Status to Alive"

Also you said:
" 1) it sets the intial state (Alive or Dead)
2) it pings
- if state is same it doesnt do anything and goes to the next "

What if the first state is Dead? It won't do anything and will go to the next?
Can it keep sending emails if the state continues to be Dead?


bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
08 Nov 2007 06:50 PM  
it will only display if you add the -verbose

This only notifies if the state changes as per your request. If you just want an email when the machine dies use my first script.
aalborzUser is Offline
New Member
New Member
Posts:56

--
08 Nov 2007 07:48 PM  
The original script works, but not the new one because of the initial Dead state.
So basically if the server has never been "Alive", no email will be ever generated.

At this point, I'll be happy with the original script, but as long as it doesn't keep sending emails about server being down.
Can it be stopped thru some sort of counter may be?



bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
08 Nov 2007 07:58 PM  
I can modify the script for you, but I would like you to try first.

Use my initial script as a starter and the new script for the state changes... see if you can get them to be like you want.

Let me know if you get stuck.
aalborzUser is Offline
New Member
New Member
Posts:56

--
09 Nov 2007 04:37 PM  
Ok thanks.

The initial script works. If you could modify it to stop emails continuously for Dead machines it would be great. May be it can be set to send it every 5 or 10 minutes.

Also it would be really useful to have the "Dead" server name included in the email, so I know which server is down.
aalborzUser is Offline
New Member
New Member
Posts:56

--
09 Nov 2007 04:49 PM  
Don't worry about the 2nd part of my request. I took care of it.
I would just need your help with stopping the continuous emails.

Thanks
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
09 Nov 2007 07:23 PM  
Effectively you have to maintain state. I used a hash table for this.

Kinda like this
$status = @{}    # Create Hash Table
if(!$status.$server){$status.add($server,'state')}
else{$status.$server = "New State"}
aalborzUser is Offline
New Member
New Member
Posts:56

--
12 Nov 2007 08:39 PM  
Now I would like to be able to run it using Scheduled Tasks when the system restarts.
I tried using a batch file; e.g. C:\PowerShell.exe myscript.ps1, but it didn't work.

How can I make PowerShell start in a specific drive & folder and run a specific script?

Thanks
bsonposhUser is Offline
Basic Member
Basic Member
Posts:388

--
12 Nov 2007 08:46 PM  
C:\PowerShell.exe myscript.ps1 will not work. You will have to specify full path

Like
C:\PowerShell.exe C:\Scripts\myscript.ps1

You will probably want the -NonInteractive and -noprofile as well
C:\PowerShell.exe C:\Scripts\myscript.ps1 -NonInteractive -noprofile
You are not authorized to post a reply.
Page 1 of 212 > >>


Active Forums 4.1
right
   
footer Sponsored by Quest Software • SAPIEN Technologies • ShellTools, LLC • Microsoft Windows Server 2008 footer
footer