我正在运行一个依赖于网络启动和网络共享安装的脚本。该脚本在登录时运行(启动后自动发生)。问题是,当脚本运行时,我通常还没有 IP 地址 (DHCP)。目前我只是让脚本休眠 15 秒,但我根本不喜欢这种方法,因为我希望能够告诉用户是否出现问题。
我的计划是,在我还没有 IP 地址时循环,并在有 IP 地址时继续。至关重要的是,它必须在一段时间后超时。我想出的是,if [ ifconfig | grep "192.168.100" ];
但发生的情况是 grep 消耗了];
并且不喜欢它。然后 bash 也会感到不安,因为它找不到];
which grep ate。然后我什至还没有实现超时。
有人建议保留一个变量,并在每次迭代中休眠一秒钟,然后每次增加该变量。这是我的完整(非工作)脚本(我对 bash 脚本相当陌生):
x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
echo "no nework"
if "$x" -gt 200; then
#Time out here
exit 1
x=$((x+1))
sleep .1
fi
done
#continue with rest of script...
任何正确方向的指示将不胜感激!
答案1
外壳语法
您似乎对 shell 脚本中的条件感到困惑。每个 shell 命令都有一个退出状态,它是 0 到 255 之间的整数,其中 0 表示成功,任何其他值表示失败。类似的陈述if
和while
期望布尔操作数检查命令的退出状态并将 0(成功)视为 true,将任何其他值(失败)视为 false。
例如,grep
如果找到模式,则该命令返回 0;如果未找到模式,则返回 1。所以
while ifconfig | grep "192.168.100." > /dev/null; do …
只要192.168.100.
在 的输出中找到该模式,就会重复循环ifconfig
。请注意,该模式192.168.100.
匹配诸如 之类的字符串192x168 1007
,因为.
在正则表达式中可以匹配任何字符;要搜索文字字符串,请将选项传递-F
给grep
.要反转条件,请放在!
前面。
while ! ifconfig | grep -F "192.168.100." > /dev/null; do …
在脚本中,您希望将变量的值与数字进行比较。您使用-gt
运算符,它是语法的一部分条件表达式理解为test
命令。test
如果条件表达式为 true,则该命令返回 0;如果条件表达式为 false,则返回 1。
if test "$x" -gt 200; then
通常使用[
该test
命令的备用名称。该名称要求命令以参数 结尾]
。该命令的两种编写方式完全相同。
if [ "$x" -gt 200 ]; then
Bash 还提供了第三种编写此命令的方法,即使用特殊语法[[ … ]]
。这种特殊语法可以支持比 多一些的运算符[
,因为[
是 一个遵循通常解析规则的普通命令,而[[ … ]]
是 shell 语法的一部分。
再次记住,这[
是为了条件表达式-n
,这是带有, -gt
, …等运算符的语法[
,并不意味着“布尔值”:任何命令都有布尔值(退出状态 = 0?)。
检测网络是否连通
您检测网络是否正常的方法并不可靠。特别要注意的是,只要任何网络接口获取指定范围内的 IP 地址,您的脚本就会被触发。特别是,此时 DNS 很可能尚未启动,更不用说安装任何网络共享了。
当有人登录时,您真的需要运行这些命令吗?当网络启动时,让命令自动运行会更容易。执行此操作的方法取决于您的发行版以及是否使用 NetworkManager。
如果您需要将这些命令作为登录脚本的一部分运行,请测试您真正需要的资源,而不是测试是否存在 IP 地址。例如,如果要测试是否/net/somenode/somedir
已挂载,请使用
while ! grep -q /net/somenode/somedir </proc/mounts; do
sleep 1
done
如果你有 upstart 或 systemd...
然后你就可以使用它了。例如,与暴发户,将您的作业标记为start on net-device-up eth0
(替换eth0
为提供所需网络连接的接口的名称)。使用 Systemd,请参阅导致脚本在网络启动后执行?
答案2
您可以使用该hostname
命令。
使用选项-I
,您将获得本地 IP 地址,这将是您的 DHCP 服务器返回的地址。
hostname -I
# (if has network) return: 192.168.100 or other IP local
检查这个非常简单的例子:
while [ "$(hostname -I)" = "" ]; do
echo -e "\e[1A\e[KNo network: $(date)"
sleep 1
done
echo "I have network";
我一直在思考并检查其他答案。
也许您想检查与服务器的连接。
我转录相同的脚本,但现在正在等待与服务器的连接。
# ip server
serverAdr="192.168.0.1"
ping -c 1 $serverAdr > /dev/null 2>&1
while [ $? -ne 0 ]; do
echo -e "\e[1A\e[K $(date): Connecting - ${serverAdr}"
sleep 1
ping -c 1 $serverAdr > /dev/null 2>&1
done
echo "$(date): Connected - ${serverAdr}";
答案3
ip add show
只需计算例如的输出:
root@xxxxxxlp01 ~ $ ip add sh dev eth3 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth1 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet
inet xxx.xxx.64.91/24 brd xxx.xxx.95.255 scope global eth0
inet6 fe80::224:e8ff:fe78:4dfb/64 scope link
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet | wc -l
2
然后您可以根据需要在返回的行数上进行分支。您可能只是检查它是否为零,如果是,则睡眠并重复循环。
未经测试的代码用于说明:
while [ 1 ]; do
if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
break
fi
sleep 1
done
答案4
@fitorec 的改进脚本版本
设置max_count,以避免无限循环。
PS:我在 busybox 版本上没有“ping -i”...
测试连接.sh
# ip server
serverAdr="10.0.0.3"
count=0
count_max=10
ping -c 1 $serverAdr > /dev/null 2>&1
while [ $? -ne 0 ]; do
echo -e "\e[1A\e[K $(date): test connection [$count/$count_max] - ${serverAdr}"
sleep 1
let "count+=1"
[[ ${count} -gt ${count_max} ]] && exit 1
ping -c 1 $serverAdr > /dev/null 2>&1
done
echo "$(date): Connected - ${serverAdr}"
exit 0
使用:
./test_connect.sh || echo "ERROR !!"