There are a number of syntax errors in your script; I'll go over those at the end. But first, it looks there's a simpler way to scan a /24 subnet, with fping
's -g
(generator) option. I don't have fping
installed to test with, but from the documentation, this should work:
#!/bin/bash
read -p "Enter Gateway IP Address: " gateway
fping -c1 -t500 -a -g "${gateway%.*}.0/24" > /dev/null
The ${gateway%.*}
part takes the entered gateway IP, an trims starting at the last "." (i.e. the last octet). So if gateway is "192.168.0.254", that's "192.168.0". The script then adds ".0/24" to it to give "192.168.0.0/24" as the subnet string.
Problems in the original script:
Start your scripts with an appropriate shebang line. Generally, that'll be #!/bin/bash
or #!/usr/bin/env bash
. You'll also see #!/bin/sh
, but that can cause trouble if you use any bash syntax extensions in your script. If you don't know the subtleties of bash vs plain sh syntax, stick with a bash shebang.
Your for
statement is missing its do
. It should be for ip in $(seq 1 254); do
.
bash v3 doesn't allow negative string indexes (e.g. ${gateway::-1}
). If you have bash version 4, that'll work; if you have v3, you need to subtract one from the string length: ${gateway::${#gateway}-1}
. Or you could use the trim-from-end operator, %
, as I did in my code above. If you use ${gateway%.*}
, that'll remove the last "." as well as the number, so you need to add it back. Other advantage is this'll also work if the final octet is more than one digit (e.g. some people put their routers at .254 for some reason).
You should almost always put double-quotes around variable references, to avoid various forms of misparsing of spaces, wildcards, etc. In this case it's probably safe, but I'd still avoid it. But in your script, you're counting on word splitting to have each address passed as a separate argument to fping
. The best-practise way to do this in a shell script is to use an array rather than a plain variable, with each argument being a separate array element. The syntax for this is a bit messy, but the basic operations are these:
args=(arg1 arg2 "arg with spaces") # The parentheses tell bash this is an array
for x in list of things; do
args+=(additionalarg) # Add elements to array. Both + and () are REQUIRED
done
somecommand "${args[@]}" # Yes, all those parentheses, brackets, etc are needed
You can't use spaces in an assignment (unless you quote or escape them, in which case they're part of the assigned string). When you use var = something
, the shell treats that as running the command var
, with =
and something
as arguments. So your assignment should look something like this:
allips="$allips ${gateway::-1}$ip"
...except that as I said above, you should be using an array. So set it to empty before the loop (allips=()
), and then use:
allips+=("${gateway%.*}.$ip")
And then after the loop, use it like this:
fping -c1 -t500 -a "${allips[@]}" > /dev/null