我尝试创建一个 bash 脚本来显示所有可用的本地 IP 地址。由于常规 ping 选项每个 IP 地址的执行速度不能快于 1 秒,并且 fping 在 for 循环中执行时会显示太多输出,因此我尝试这样做:
read -p "Enter Gateway IP Address: " gateway
for ip in $(seq 1 254);
allips = $allips ${gateway::-1} $ip
done
fping -c1 -t500 -a $allips > /dev/null
但每次我尝试运行这个小脚本时,它都会显示
local.sh: line 2: : command not found
local.sh: line 4: syntax error near unexpected token `allips'
local.sh: line 4: ` allips = $allips ${gateway::-1} $ip'
答案1
您的脚本中有许多语法错误;我将在最后检查这些错误。但首先,似乎有一种更简单的方法来扫描 /24 子网,使用fping
's -g
(generator) 选项。我没有fping
安装来测试,但从文档,这应该有效:
#!/bin/bash
read -p "Enter Gateway IP Address: " gateway
fping -c1 -t500 -a -g "${gateway%.*}.0/24" > /dev/null
该${gateway%.*}
部分采用输入的网关 IP,并从最后一个“。”(即最后一个八位字节)开始修剪。因此,如果网关是“192.168.0.254”,则为“192.168.0”。然后脚本将“.0/24”添加到其中,以将“192.168.0.0/24”作为子网字符串。
原脚本存在的问题:
使用适当的 shebang 行开始您的脚本。通常,它将是
#!/bin/bash
或#!/usr/bin/env bash
。您还会看到#!/bin/sh
,但如果您在脚本中使用任何 bash 语法扩展,这可能会引起麻烦。如果您不知道 bash 与普通 sh 语法的微妙之处,请坚持使用 bash shebang。您的
for
陈述缺少了 itsdo
。应该是for ip in $(seq 1 254); do
。bash v3 不允许负字符串索引(例如
${gateway::-1}
)。如果您使用的是 bash 版本 4,那么这种方法可行;如果您使用的是 v3,则需要从字符串长度中减一:${gateway::${#gateway}-1}
。或者,您可以使用 trim-from-end 运算符,%
就像我在上面的代码中所做的那样。如果您使用${gateway%.*}
,那么它将删除最后一个“。”以及数字,因此您需要将其添加回来。另一个优点是,如果最后的八位字节多于一位数字(例如,出于某种原因,有些人将他们的路由器放在 .254),这种方法也会有效。您几乎总是应该在变量引用周围加上双引号,以避免各种形式的空格、通配符等错误解析。在这种情况下,它可能是安全的,但我还是会避免它。但在您的脚本中,您依靠分词将每个地址作为单独的参数传递给
fping
。在 shell 脚本中执行此操作的最佳实践是使用数组而不是普通变量,每个参数都是一个单独的数组元素。这个语法有点混乱,但基本操作如下: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
您不能在赋值中使用空格(除非您引用或转义它们,在这种情况下它们是赋值字符串的一部分)。当您使用 时
var = something
,shell 会将其视为运行命令var
,并使用=
和something
作为参数。因此您的赋值应如下所示:allips="$allips ${gateway::-1}$ip"
...除了我上面说的,你应该使用数组。所以在循环之前将其设置为空(
allips=()
),然后使用:allips+=("${gateway%.*}.$ip")
然后在循环之后,像这样使用它:
fping -c1 -t500 -a "${allips[@]}" > /dev/null