You don't need the separate script (or the bash shell). Shell code can also be given as argument with the -c option (that's what the system("shell code") function of most languages use):
if
echo host1 host2 host3 |
xargs -n1 -P0 sh -c '! "$0" "$@"' ping -c1 -w2
then
echo 'They all failed'
else
echo 'At least one succeeded'
fi
In:
sh -u -ce -o xtrace -- 'shell code' 'script name' 'arg 1' 'arg 2'
(here -u, e and -o xtrace to show you can have more options before or after -c)
- the first non-option argument (here
shell code) is the code to interpret - the second (
script name) a name you want to give to that inline script (the equivalent of the file name for a script in a file). It has these effects:- it's used for instance in error messages that the shell generates to tell the user the error is coming from that script.
- it's what the
$0special parameter expands to.
- and the remaining arguments make up the arguments of the inline script, so are available in the
shell codeas$1,$2... with"$@"the verbatim list of them all.
So, here with sh -c '! "$0" "$@"' ping -c1 -w2, we're creating an inline script which we call ping. xargs will pass -c1, -w2 and one word read from stdin at a time as arguments to that script, and that script runs the command called ping with those arguments and the exit status reversed with !.
You may argue that shell error messages if any showing as "ping" error messages, may be confusing to the user, so you could change it to sh -c '! "$@"' sh ping -c1 -w2 for the inline script's name to be sh instead.
But here I'd argue that to scan networks, you'd rather use things like nmap than ping in a loop.