I am trying to ping all ip's on 192.168.2-254 simultaneously and get the return status of each one. this is what I have so far but it doesn't work and instead just returns the status of xargs. Any help is appreciated! I do not want to use nmap...
subnet="192.168.1"
num="2"
while [ "$num" -lt "254" ]; do
num=$((num 1))
printf "${subnet}.${num}\n"
done | xargs -n 1 -I ^ -P 50 ping -c2 -t3
CodePudding user response:
The well-established and documented behavior of xargs
is to return an exit code of its own which indicates what happened to all of the subprocesses you started. To wit;
xargs
exits with the following status:0 - if it succeeds
123 - if any invocation of the command exited with status 1-125
124 - if the command exited with status 255
125 - if the command is killed by a signal
126 - if the command cannot be run
127 - if the command is not found
1 - if some other error occurred.
(Source: GNU xargs
man page. The POSIX spec is slightly less specific, and simply lumps all of 1-125 into "A command line meeting the specified requirements could not be assembled, one or more of the invocations of utility returned a non-zero exit status, or some other error occurred.")
There is no simple way to communicate the status of multiple processes in a single exit code (recall that the value is a single byte, so even if you were to encode return values as bit fields, indicating only success or failure, you could still only cram eight of them into one value) but if I understand your request correctly, just run ping
in the loop you are running anyway, and wait
individually for each one. The following uses a Bash array to keep track of the individual processes:
declare -a procs
for((num=2; num<254; num )); do
ping -c2 -t3 "192.168.1.${num}" &
procs =($!)
done
for p in "${procs[@]}"; do
wait $p; echo $?
done
The output from over 200 ping
processes running in parallel will be rather noisy; perhaps add >/dev/null
after the first done
. (Redirecting everything once is more efficient than redirecting each ping
separately.)
This doesn't yet keep track of which process ID belonged to which IP address; if you need that, probably use an associative array (Bash 4 ) or put the IP addresses into a second array and keep them aligned so that ${ip[x]}
is the IP address belonging to process ${procs[x]}
(e.g. MacOS still ships with Bash 3.2.57(1)-release which doesn't support associative arrays).
Here's a refactoring to use an associative array.
declare -A procs
for((num=2; num<254; num )); do
ping -c2 -t3 "192.168.1.${num}" &
procs[$num]=$!
done >/dev/null
for p in "${!procs[@]}"; do
wait ${procs[$p]}
printf "%s:%i\n" "192.169.1.$p" $?
done
CodePudding user response:
@M Horton Will this serve your purpose .
In xargs field use xargs -n1 -P50 ping -c2