在 bash 脚本中等待网络

在 bash 脚本中等待网络

我正在运行一个依赖于网络启动和网络共享安装的脚本。该脚本在登录时运行(启动后自动发生)。问题是,当脚本运行时,我通常还没有 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 表示成功,任何其他值表示失败。类似的陈述ifwhile期望布尔操作数检查命令的退出状态并将 0(成功)视为 true,将任何其他值(失败)视为 false。

例如,grep如果找到模式,则该命令返回 0;如果未找到模式,则返回 1。所以

while ifconfig | grep "192.168.100." > /dev/null; do …

只要192.168.100.在 的输出中找到该模式,就会重复循环ifconfig。请注意,该模式192.168.100.匹配诸如 之类的字符串192x168 1007,因为.在正则表达式中可以匹配任何字符;要搜索文字字符串,请将选项传递-Fgrep.要反转条件,请放在!前面。

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 !!"

相关内容