在执行命令之前等待网络接口

时间:2014-03-09 03:05:18

标签: bash shell networking

我对如何实现这一目标有几点想法。我不确定如何编写脚本。

方法1 :(可能是更好的选择)

创建一个ping服务器的循环,直到收到回复,然后执行命令 如果在X时间内没有收到回复/运行继续脚本。

方法2:

检查网络接口是否具有有效的IP然后继续脚本

如何在脚本中添加此功能。 awk或grep会在这样的情况下使用吗?提前感谢您提供任何输入。

3 个答案:

答案 0 :(得分:5)

此命令应该等到它可以联系谷歌或它已尝试50次:

for i in {1..50}; do ping -c1 www.google.com &> /dev/null && break; done

for i in {1..50}循环50次或直到执行breakping -c1 www.google.com向Google发送1个ping数据包,&> /dev/null将所有输出重定向到null,因此没有输出任何内容。 && break仅在前一个命令成功完成时执行break,因此循环将在ping成功时结束。

答案 1 :(得分:1)

我已经在通过DHCP配置的板上进行了测试。

假设是,如果特定接口上存在默认网关(在这种情况下为eth0),则这是由于以下事实而引起的:董事会已通过以下方式分配了IP(因此是默认网关) DHCP服务器,这意味着网络已启动并正在运行。

我的问题是,对我来说,即使没有Internet连接(即无法访问8.8.8.8或www.google.com),也可以在访问LAN / Intranet中的计算机后立即建立网络。 。我也不想对Intranet中的特定IP或域名执行ping操作,因为我不想对子网或肯定会启动的设备以及它们的IP或域名进行假设。

while ! ip route | grep -oP 'default via .+ dev eth0'; do
  echo "interface not up, will try again in 1 second";
  sleep 1;
done

答案 2 :(得分:0)

  
    

如何在脚本中添加此功能     -Geofferey

  

以下是我要如何以模块化方式解决类似情况的一部分...

await-ipv4-address.sh

#!/usr/bin/env bash


## Lists IP addresses for given interface name
## @returns {number|list}
## @param {string} _interface      - Name of interface to monitor for IP address(es)
## @param {number} _sleep_intervel - Number of seconds to sleep between checks
## @param {number} _loop_limit     - Max number of loops before function returns error code
## @author S0AndS0
## @copyright AGPL-3.0
## @exampe As an array
##     _addresses_list=($(await_ipv4_address 'eth0'))
##     printf 'Listening address: %s\n' "${_addresses_list[@]}"
##     #> Listening address: 192.168.0.2
##     #> Listening address: 192.168.0.4
## @example As a string
##     _addresses_string="$(await_ipv4_address 'eth0' '1' '3')"
##     printf 'Listening address(es): %s\n' "${_addresses_string}"
##     #> Listening address(es): 192.168.0.2 192.168.0.4
await_ipv4_address(){
    local _interface="${1:?# Parameter_Error: ${FUNCNAME[0]} not provided an interface}"
    local _sleep_interval="${2:-1}"
    local _loop_limit="${3:-10}"
    if [ "${_sleep_interval}" -lt '0' ] || [ "${_loop_limit}" -le '0' ]; then
        printf 'Parameter_Error: %s requires positive numbers for second and third parameters\n' "${FUNCNAME[0]}" >&2
        return 1
    fi

    local _loop_count='0'
    local -a _ipv4_addresses
    while true; do
        for _address in $({ ip addr show ${_interface} | awk '/inet /{print $2}'; } 2>/dev/null); do
            _ipv4_addresses+=("${_address}")
        done

        if [ "${#_ipv4_addresses[@]}" -gt '0' ]; then
            printf '%s\n' "${_ipv4_addresses[*]}"
            break
        elif [ "${_loop_count}" -gt "${_loop_limit}" ]; then
            break
        fi

        let _loop_count+=1
        sleep "${_sleep_interval}"
    done

    [[ "${#_ipv4_addresses[@]}" -gt '0' ]]; return "${?}"
}
  

以上来源位于GitHub bash-utilities/await-ipv4-address上,请检查ReadMe文件以获取有关利用Git进行更新和错误修复的说明。

要在当前shell中获取上述功能...

source "await-ipv4-address.sh"

...或在另一个脚本中...

#!/usr/bin/env bash


## Enable sourcing via absolute path
__SOURCE__="${BASH_SOURCE[0]}"
while [[ -h "${__SOURCE__}" ]]; do
    __SOURCE__="$(find "${__SOURCE__}" -type l -ls | sed -n 's@^.* -> \(.*\)@\1@p')"
done
__DIR__="$(cd -P "$(dirname "${__SOURCE__}")" && pwd)"


source "${__DIR__}/modules/await-ipv4-address/await-ipv4-address.sh"


  
    

awk或grep在这种情况下会有用吗?     -Geofferey

  

两者都可以使用;尽管很像 echo ing 我认为 grep ing 最好是在自己的外壳中完成的……我更喜欢{{1} },因为{em> scripting language可以促进 feature蠕动,而awk则是因为{em> slimmed-down 不太可能缺少功能环境。

这里是printf地址的说明,而不管IPv4与IPv6 风味 ....

awk

...在空间上有所不同,以获取更多数据。


  
    

无论接口名称或类型如何,我都可以兼容

  

三个不同的接口名称示例以及如何覆盖一些默认行为

  1. # ... trimmed for brevity for _address in $({ ip addr show ${_interface} | awk '/inet/{print $2}'; } 2>/dev/null); do # ... things that get done with an address done
  2. 上等待十秒钟以上的IP
eth0
  1. _ip_addresses_list=($(await_ipv4_address 'eth0'))
  2. 上等待30秒以上的IP
tun0
  1. 在两次检查之间睡眠3秒钟时,等待 _ip_addresses_list=($(await_ipv4_address 'tun0' '1' '29')) 上IP的尖塔上方
wlan0
  
     

注意,如果_ip_addresses_list=($(await_ipv4_address 'wlan0' '3' '19')) 获得 board ,它将返回非零状态,因此以下内容...

await_ipv4_address
  

...如果您有被此类情况绊倒的错误陷阱,则可以使用。

     

然后使用分配的IP地址进行处理...

_ip_addresses_list=($(await_ipv4_address 'wlan0' '3' '19' || true))

  
    

等待网络接口做什么?     -user207421

         

要起床,但不仅仅是起床,我需要一个有效的连接,我可以确定可以连接到互联网     -Geofferey

  

仅当通过本地网络交换机/ AP或静态设置分配了IP地址时,以上内容才会测试与更大互联网的活动连接;不过,本地IP是先决条件...考虑答案的上述部分是 script友好的,因为它只能很好地执行一件事。

可靠地 ,检测是否允许连接到万维网的其余部分,请检出for _ip_address in "${_ip_addresses_list[@]}"; do printf 'IP -> %s\n' "${_ip_address}" done dig,因为成功的{ {1}}到自己喜欢的DNS并不表示允许其他协议。


  
    

您能解释一下脚本的每个部分,以便在不了解某些脚本工作原理的情况下不要盲目使用它吗? -Geofferey

  

...确定...

curl
  • ping分配局部范围的变量,await_ipv4_address(){ local _interface="${1:?# Parameter_Error: ${FUNCNAME[0]} not provided an interface}" local _sleep_interval="${2:-1}" local _loop_limit="${3:-10}" # ... } local将显示一些更高级用法的有用文档

  • 如果未分配help local
  • help declare将打印"${something:?Error message}"

  • 如果未为Error message分配 null 值,则
  • something将默认为"${another_thing:-1}" >

  

提示,1another_thing部分以及man --pager='less -p ^"PARAMETERS"' bash部分的结尾可能有助于发现更多可以用变量和填充物完成的事情。


Special Parameters
    如果man --pager='less -p "Parameter Expansion"' bash if [ "${_sleep_interval}" -lt '0' ] || [ "${_loop_limit}" -le '0' ]; then printf 'Parameter_Error: %s requires positive numbers for second and third parameters\n' "${FUNCNAME[0]}" >&2 return 1 fi 不是数字,则
  • 会引发错误,原因是小于(_sleep_interval)和小于或等于(_loop_count )检查

  • 如果-lt检查中的任何一个返回 -le ,而if 多次检查,则
  • 引发错误左侧返回 true ,它跳动右侧进行检查,因为||仅在左侧返回 false时触发em>

  

提示&&将显示各种运算符的方向性

  • trueman operator写入标准错误;应该记录所有行为良好的错误,以便可以制作日志或忽略输出

  • 显示有关可能过多的函数输入的偏执程度


printf 'something\n' >&2
  • 应谨慎使用,因为如果未检查状态并正确更新状态,则循环将从不退出。

something
  • while true; do # ... stuff done 技巧是我从这些部分中学到的

    • for _address in $({ ip addr show ${_interface} | awk '/inet /{print $2}'; } 2>/dev/null); do _ipv4_addresses+=("${_address}") done 在子外壳中运行$({ command | parser; } 2>/dev/null)
    • $(something)是复合命令
      

    提示,something应该显示相关文档

    • { one_thing | another_thing; }导致将标准错误写入没有输入返回的地方
  • man --pager='less -p "Compound Commands"' bash通过2>/dev/null

  • _preexisting_list+=("element")附加到element

_preexisting_list
  • +=部分通过 if [ "${#_ipv4_addresses[@]}" -gt '0' ]; then printf '%s\n' "${_ipv4_addresses[*]}" break elif [ "${_loop_count}" -gt "${_loop_limit}" ]; then break fi 符号if

    检查_ipv4_addresses中的元素数是否大于0
  • #部分检查功能是否应该现在为 board

无论哪种情况,当逻辑被触发时,都会从${#_list_name[@]}循环中获取elif


break
  • while let _loop_count+=1 sleep "${_sleep_interval}" 添加到let _counter+=1中的先前值,并将其分配给1

  • _counter导致循环冷静几秒钟,以便设备可以考虑其他事情


_counter
  • 使用测试括号(sleep而不是 [[ "${#_ipv4_addresses[@]}" -gt '0' ]]; return "${?}" [[ is_it_true ]]的Bash分号会导致||返回以下状态:如果找到的IP地址数量大于{ {1}}不论测试是否真实

如果有什么问题可以随时发表评论,以便改善答案。