Friday, September 7, 2007

Two PowerShell filters to aid with IP addresses


There are two major differences between functions and filters in PowerShell:

  1. The keyword, function vs filter.
  2. The available current variable inside the function/filter.

Both procedures can be used in pipelines.
When a function is used, the special variable $input is available to process through the input collection. For filters, the special variable $_ contains the current pipeline object.

Filter, as its name suggests will pass on only certain objects down the pipeline.
To demonstrate it, here are two filters to help where IP address are involved.

 

I have a text file were each line contains an IP address.

###### ip.txt #####

10.0.0.138
1.1.1.1111
192.168.2.1
10.0.0.101
10.0.0.102
10.0.0.103

###### EOF #######

 

I want to get the content of this file and operate ONLY on live hosts.
The first filter will validate the IP address and stream down the pipe only valid ones.
The second filter will ping each valid host passed and test its availability,.
The third, ForEach cmdlet,  will run some code on the filtered IPs.

 

filter Validate-IPAddress {
    trap{write-host "$_ <$input>" -f red -b black; continue;}   
    [System.Net.IPAddress]::Parse($_).IPAddressToString;   
}

 

filter Ping-Host{
    begin{
        # instantiate once for all piped objects
        $ping = new-object System.Net.NetworkInformation.Ping;
    }
    process{   
        # ping test
        $stat=$ping.Send($_).status;
        if($stat -ne "Success"){write-warning "$_ is not available <$stat>";}
        else {$_;}
    }   
}

 

# cat = Get-Content
# -f = foreground
# -b = background

cat ip.txt | Validate-IPAddress | Ping-Host | foreach {    
    write-host "$_ is ALIVE, run some code" -f green -b black
}

 

# colored output , just for demonstrating

10.0.0.138 is ALIVE, run some code
An invalid IP address was specified. <1.1.1.1111>
WARNING: 192.168.2.1 is not available <TimedOut>
10.0.0.101 is ALIVE, run some code
WARNING: 10.0.0.102 is not available <TimedOut>
10.0.0.103 is ALIVE, run some code

################################################

 

Here's the filters final version. You can see that only validated IPs and live hosts are processed.

 

filter Validate-IPAddress {
    trap{continue;}   
    [System.Net.IPAddress]::Parse($_).IPAddressToString;
}

filter Ping-Host{
    begin{ $ping = new-object System.Net.NetworkInformation.Ping; }
    process{ if($ping.Send($_).status -eq "Success") {$_;} }   
}

 

cat ip.txt | Validate-IPAddress | Ping-Host | foreach {
    write-host "$_ is ALIVE, run some code" -f green -b black
}

 

# output

10.0.0.138 is ALIVE, run some code
10.0.0.101 is ALIVE, run some code
10.0.0.103 is ALIVE, run some code

2 comments:

Unknown said...

is it posble to see the hostname of the ip address?

Shay Levy said...

Yes, you can resolve the IP to name, for example:

PS > [system.net.dns]::GetHostEntry("192.168.1.1").HostName

On a side note, this blog is no longer updated, the new blog is available at: http://blogs.microsoft.co.il/blogs/ScriptFanatic/

-Shay