Ip addresses on your subnet with xargs
xargs strikes again. This time I'm going to use it's parallel
feature to ping 255 machines very quickly. xargs has a parem -Px
where x is
the number of parallel processes to spawn of the subsequent process.
Update - 11/04/2019 Added MacOS Xargs syntax
Together with the bash {1..255}
expression that expands to output 1 to 255, we
can do something like this
$ s=192.168.11.
$ echo ${s}{1..254} | xargs -P254 -d' ' -L1 ping -c1 -w1 | grep 'bytes from'
In this example, -P254
tells xargs to spawn 254 procceses, -d' '
says to
split commands with a space instead of the normal newline, and -L1
says to
finish building the command after 1
amount of input.
To achieve the same result in powershell is not quite as simple. Out of the box
you could use a ForeEach-Object
loop like so:
PS> $s='192.168.11.'
PS> echo $s[1..254] | %{ Test-Connection $_ -Count 1 -TTL 1 -EA SilentlyContinue }
But it's just a sequential loop. Instead we are going to have to leverage the .Net ping class.
Lee Holmes shared this on twitter back in 2015:
Sweep a /16 in 30s:
$t=$ips|%{ (New-Object Net.NetworkInformation.Ping).SendPingAsync($_,250)}; [Threading.Tasks.Task]::WaitAll($t); $t.Result
Before you run this, build out an array of ips, like so:
PS> $ips=[1..254] | %{"192.168.11.$_"}
This use of powershell seems a bit too obtuse for me, and not something likely to stick in my head.
I did find other ways to do it in powershell. A collegue of mine Darryl, dardie on github added this commit to a module I maintain which has pretty good results. Again however not something you could commit to memory as you need to write a function to use it.
Final thoughts
In this case it looks to me like bash wins, if not in performance, but by being simpler to implement and commit to memory, or recreate from memory. But if I ever need to do this in powershell again, I can just come back to my site for reference.
If you have any comments or feedback, please email me and let me know if you will allow your feedback to be posted here.
MacOS
For completeness and because I tried to run this and failed on MacOS today I'm adding it's syntax:
Xargs on MacOS is a BSD variant, seemlingly pulled from FreeBSD going by the
man page. It still supports the -Px
, however -d
is not required as it
splits on newline and spaces by default. The other difference is that instead
of -L1
we use -n1
with essentially the same effect.
Also of note is the differences with ping. Rather than -w1
to reduce time
waiting for a ping reply, -t1
is used.
echo "192.168.11."{1..254} | xargs -P254 -n1 ping -c1 -t1 |
awk '/bytes from/ {
match($0,"[0-9]+.[0-9]+.[0-9]+.[0-9]+");
n=substr($0,RSTART,RLENGTH);
print n
}'
In this example, I'm using an awk script to only print hosts that respond
Tags: bash-v-powershell, powershell, xargs, bash, ping, awk