我正在起草/仍在集思广益/一个bash
shell 脚本。其目的是帮助用户:
- 与各种接口CLI 工具。
- 执行各种行政任务。
最终,它可能会演变成一种个性化的框架。
它有一个特殊要求:
- 它应该能够检测IP地址 的网关/路由器 在当前局域网。
- 我想到
route -n |awk '/UG/{print $2}';
了回声这 对应IP 到标准输出。
我应该用那个吗输入作为function(){ }
输出作为$variable
,或两个都??
以下是我的一些简单想法:
#function# gw() { route -n |awk '/UG/{print $2}'; }
#variable# gw="$( route -n |awk '/UG/{print $2}'; )"
#function# gw() { route -n |awk '/UG/{print $2}'; } #variable# gw="$( route -n |awk '/UG/{print $2}'; )"
#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 等旧命令已被弃用,这是有原因的。