shell 执行命令前等待网络接口

q9rjltbz  于 2023-08-07  发布在  Shell
关注(0)|答案(4)|浏览(132)

我有几个想法,我将如何实现这一点。我不确定我会如何写它。
方法1:(可能是更好的选择)
创建一个循环,ping服务器直到收到回复,然后如果在X时间内没有收到回复,则执行命令/运行continue脚本。
方法二:
检查网络接口是否具有有效的IP,然后继续脚本
如何在脚本中添加此功能。awk或grep在这种情况下有用吗?提前感谢您的任何输入。

bbmckpt7

bbmckpt71#

这个命令应该等到它可以联系谷歌或者它已经尝试了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成功完成时结束。

c6ubokkw

c6ubokkw2#

我已经在通过DHCP配置的电路板上测试过了。
假设在特定接口上存在默认网关(在本例中为eth0),则这是由于DHCP服务器为该板分配了IP(因此是默认网关),这意味着网络已启动并正在运行。
我的问题是,对我来说,一旦局域网/内联网中的机器可以访问,即使不存在互联网连接(即8.8.8.8或www.google.com不可访问),网络也被认为是启动的。我也不想ping内部网中的特定IP或域名,因为我不想对子网或哪些设备肯定会启动以及它们的IP或域名是什么做出假设。

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

字符串

lmvvr0a8

lmvvr0a83#

如何在脚本中添加此功能-- 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在这种情况下有用吗?--杰弗里
两者均可使用;虽然很像 * echo ing*,但我认为 * grep ing* 最好在自己的shell中进行。我更喜欢在公共场合使用awk,因为有一个完整的scripting language来促进 * 功能蠕变 *,而printf则是因为它不太可能在 * 精简 * 的环境中缺少功能。
以下是如何awk一个地址,而不考虑IPv4与IPv6 flavor....

# ... 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


...只是空间上的差异以获得更多数据。
无论接口名称或类型如何,我都可以拥有兼容的东西
三个不同的接口名称示例以及如何覆盖一些默认行为
1.等待10秒以上,以获得**eth0**上的IP

_ip_addresses_list=($(await_ipv4_address 'eth0'))


1.等待30秒以上,以获得**tun0**上的IP

_ip_addresses_list=($(await_ipv4_address 'tun0' '1' '29'))


1.在**wlan0**上等待超过一小步舞曲的IP,同时在两次检查之间休眠3秒

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


注意,如果await_ipv4_address得到 board,它将返回一个非零状态,所以下面的...

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


...如果你有被这些东西绊倒的错误陷阱,可以使用。
然后做的东西与IP地址一旦分配.

for _ip_address in "${_ip_addresses_list[@]}"; do
    printf 'IP -> %s\n' "${_ip_address}"
done

等待网络接口做什么?--用户207421
我需要一个活跃的连接,在那里我确信我可以连接到互联网--杰弗里
以上将测试到更大的互联网的活动连接,只有当IP地址已通过本地网络交换机/AP或静态设置分配;但是,本地IP是先决条件…考虑上面的回答部分是 * 脚本友好的 *,因为它只被设计为很好地执行一件事。
为了 * 可靠地 * 检测是否允许连接到万维网的其他部分,请检查digcurl,因为成功的ping到一个人最喜欢的DNS并不意味着允许其他协议。
你能解释一下你的剧本的每一部分吗?这样我就不会在没有理解它是如何工作的情况下盲目地使用它了。--杰弗里
……当然……

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 localhelp declare将展示一些关于更高级用法的有用文档
  • 如果未分配something,则"${something:?Error message}"将打印Error message
  • 如果another_thing未被分配被分配 null 值,则"${another_thing:-1}"将默认为1

提示,man --pager='less -p ^"PARAMETERS"' bashSpecial 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 *,则触发右侧进行检查,其中&&仅在左侧返回 * true * 时才会触发

提示man operator将显示各种运算符 * 方向性

  • printf 'something\n' >&2something写入标准错误;其中应写入所有行为良好的错误,以便可以生成日志或忽略输出
  • 显示了对可能过度的函数输入的偏执程度
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)在子shell中运行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部分通过#符号${#_list_name[@]}检查_ipv4_addresses中的元素数是否大于0
  • elif部件检查功能现在是否应为 board

在任何一种情况下,从while循环break是当逻辑跳闸。

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

  • let _counter+=1将把1添加到_counter中的任何先前值,并将其分配给_counter
  • sleep会使循环冷却几秒钟,以便设备可以考虑其他事情
[[ "${#_ipv4_addresses[@]}" -gt '0' ]]; return "${?}"

  • 使用测试方括号([[ is_it_true ]])而不是||&&对分号进行破折号,会导致return返回“如果找到的IP地址数大于0,则无论测试的真实性如何”的状态

如果有什么问题,毕竟,随时发表评论,使答案可以得到改善。

pcrecxhr

pcrecxhr4#

您可以执行以下操作

until ifconfig -l | grep ppp0 >/dev/null 2>&1; do :; done

字符串
适用于MacOS

相关问题