使用 Bash 检测网关/路由器:函数和变量

使用 Bash 检测网关/路由器:函数和变量

我正在起草/仍在集思广益/一个bashshell 脚本。其目的是帮助用户:

  • 与各种接口CLI 工具
  • 执行各种行政任务。

最终,它可能会演变成一种个性化的框架。


它有一个特殊要求:

  • 它应该能够检测IP地址 网关/路由器 当前局域网
  • 我想到route -n |awk '/UG/{print $2}';回声 对应IP 标准输出

我应该用那个吗输入作为function(){ }输出作为$variable,或两个都??


以下是我的一些简单想法:

  1. #function#
    gw() { route -n |awk '/UG/{print $2}'; }

  2. #variable#
    gw="$( route -n |awk '/UG/{print $2}'; )"

  3. #function#
    gw() { route -n |awk '/UG/{print $2}'; }
    
    #variable#
    gw="$( route -n |awk '/UG/{print $2}'; )"

  4. #function#
    gw() { route -n |awk '/UG/{print $2}'; }
    
    #variable#
    gw="$(gw)"

答案1

我完全回答了你的问题,但希望它能有所帮助。我谈到了一些一般性的东西,然后是默认网关的具体内容,最后是一些其他示例。

以下是一些一般性评论:

  • 我建议您将这些调用形成函数,除其他外,这将允许您构建自己的函数,以便更高级别的函数可以简单地包装一个或多个较低级别函数。

  • 为了处理函数的输出,我发现使用 stdout 是最通用的方法,并且它适合于构建函数的模块化/包装器方法。

如果您在函数内部进行变量分配和导出,范围问题将会给您带来麻烦。

如果你有一个函数,它将自己分配给同一个函数内的变量;例如

`testFx() { export routeInfo="$(route)"; }`

如果“testFx”对 routeInfo 的变量赋值与调用者处于同一范围内 - 换句话说,如果该函数在当前 shell 中声明并从当前 shell 调用,则对变量 routeInfo 的结果赋值将可从该 shell 访问。如果在执行的脚本中使用该函数,则调用该脚本的 shell 将无法访问结果,尽管该函数将要可以访问。

这有点过于简单了,但我认为它很好地阐明了范围问题。父级范围内的对象可供子 shell/进程访问,但反之则不然。很难将事物“传回”线路(在 bash 中)。

这种差异体现在获取脚本文件和执行脚本文件时所见的不同行为上。

执行的脚本在子 shell 中运行;源文件被添加到当前上下文中的本地环境中;而不是在子 shell 中。

您可以通过将该简单函数添加到您的 shell 来测试我所说的内容 - 只需将其粘贴进去(或添加到 .bashrc 并重新加载 shell 等)

然后调用该函数并尝试回显保存该值的变量echo $routeInfo。这将按预期工作。

使用以下方法清除该变量unset routeInfo

然后创建一个简单的脚本如下:

vi ~/test.sh

内容:

#!/bin/bash
testFx

保存、关闭并添加执行权限chmod +x ~/test.sh

~/test.sh然后从定义了该函数的 shell运行该脚本。

运行脚本后,回显应保存值的变量:echo $routeInfo,您会看到它是空的 - 假设您进行了上面的取消设置调用;因为导出无法上升到父 shell/进程。

由于这个范围问题以及 Bash 函数缺少传统的“返回”值,我通常看到的 Bash 函数“结果”值要么直接使用;要么将其输出到 stdout,要么将其捕获到变量中。无论哪种情况,函数本身的编写方式都相同,只是调用方式有所改变。

以下是从 Bash 函数中“抓取”输出值的一些示例

rslt=$(testFx)
如果您可以预期多个结果,则可以将结果存储在一个数组中:
rslt=($(testFx)) 包含${#rslt[@]}条目数(N),并且您可以通过直接索引访问元素:
${rslt[$a]}a = 0 到 N-1
或通过循环:
for i in ${rslt[@]}; do echo "$i"; done

希望这能解答您的大部分问题。我提供了本地机器上的几个网络数据收集功能。如果您正在寻找任何其他特定信息,请告诉我,我可能有相关功能。

getExternalIP () {
    lynx -dump -hiddenlinks=ignore -nolist http://checkip.dyndns.org:8245/ | grep "Current IP Address" | cut -d":" -f2 | cut -d" " -f2
}

getLanIP () {
    ip addr show | grep -E -v '127\.0' | grep -Eo '^.*brd' | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
}

getDefGW_IP () { 
    route -n | awk '/UG/ {print $2}'; 
}

getDefGW_Host () { 
    route  | awk '/default/ {print $2}'; 
}    

getDefGW_Host_and_IP () { 
    echo "Def. GW hostname / IP Address: $(getDefGW_Host) / $(getDefGW_IP)";
}

这是处理 IP 地址时有用的正则表达式字符串:

iprgx='(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'

使用该函数的示例 - 输出 LAN 上所有已看到 ARP 数据包的 IP 地址:

getARPTable_IPs() {
    arp -na | grep -Eo "$iprgx";
}

将结果存储在数组中:

arpIPs=($(getARPTable_IPs))

最后,对于现代 Linux 发行版,以下是我经常用来获取网络信息/状态的命令和文件系统位置。netstat 和 ifconfig 等旧命令已被弃用,这是有原因的。

  1. 知识产权
  2. 党卫军
  3. /sys/class/net 下将有一个目录,其中包含系统中每个 NIC 的网络信息文件。a
    . 许多命令行实用程序仅使用此输出并重新格式化。b
    . /proc/net 包含大量信息。c
    . 例如,该arp -na命令可以完全复制为cat /proc/net/arp
  4. iptables

相关内容