工作中的shell数据提取与操作

本文介绍了一套实用的Linux网络故障排查方法,包括快速定位网口对应关系、获取网口详细信息、查找网口异常时间点及统计特定端口的UDP报文数量。通过shell命令与脚本实现自动化故障诊断。

问题一:有台正常运行的服务器,共有48个网口,并且网口号处于没有经过调整的混乱状态,怎样快速的找出eth0~eth47对应的物理网口位置?

shell命令# for i in `seq 0 47`; do ethtool -p eth$i 2; done

说明:遍历i=0~47,对每个 eth$i , 执行 ethtool -p 命令,意思是点亮该网口2秒钟。

问题二:查看linux系统所有网口的驱动版本、链接状态等信息

shell命令#ifconfig -a | grep eth | awk '{print $1}' | sed 's/eth//g' | sort -n | while read i; do echo eth$i; ethtool -i eth$i; ethtool eth$i | egrep "Link|Supported"; echo " ";done

说明:包含一些基本工具的应用,没什么技术含量。

问题三:服务器/var/log/blackbox 目录下有很多日期目录,目录名称是01,02,...28,29,30. 分别表示系统运行的当天号数(本月和下月记录会循环覆盖);每个时间号目录下,都有一个 net 文件,net文件记录了系统每分钟所有网口的状态信息(net内容格式是date;ethtool ethN,的每分钟执行打印的结果,其中N=0~47)。现在突然某天发现某一网口有异常,其ethtool ethN的Speed是Speed:Unknown!,而Link detected: yes ,问如何通过/var/log/blackbox的黑盒记录,找到网口异常发生的起始时间?

shell命令#find ./ -name net | while read file; do cat $file >> netAll; done

shell命令#awk '{b="";errorLineNum+=1}; /Speed:/{a=$2}; /Link detected:/{b=$3}; {if(a=="Unknown!" && b=="yes")print errorLineNum}' netAll > rlt

说明:首先找到所有日期下的net文件,合并为netAll,便于统一处理(这不会丢失时间信息,因为系统每分钟执行ethtool的时候,都已经附带执行了date命令,记录了时间信息)。然后,通过awk语言特性,遍历每行文件,只要匹配Speed:,则记录speed的结果到a变量;只要匹配到 Link detected:,则记录结果到b变量;因为a,b在处理每行的数据时,它的值在没匹配时都会保持上一个值,所以这里需要每次对b进行初始化为空(手动调试一下就可理解)。一旦a,b的值同时满足要求时,打印该行的行号。然后通过 vim netAll 打开,输入记录的errorLineNum行号,回车,即可直接定位到问题发生时的第一时间点。为什么这里这么费事的用awk语言?因为netAll文件有3718990行,手动寻找符合特征要求的时间点不现实。实际工作中,本人定位的问题发生的起始点是netAll的第60518行,对应的时间点是Wed Jun 27 03:53:34 CST 2018,也就是在6月27号凌晨3点多发生该网口异常。

//20181207备注:其实可以用二分法对netALL文件查找问题发生时间点的。netALL文件380 0000行,二分查找 2^20 = 100 0000;所以最多只需要找22次就可以定位时间点。

问题四:在一台接收大量UDP报文的服务器上,如何快速的根据UDP报文的目的端口做报文数量的统计 (实际是服务器监听了多个UDP端口,需要查看发往该服务器的UDP报文是在端口上散列均匀)

shell命令# timeout 5 tcpdump -iany udp -n > hei

shell命令# cat hei | awk -F. '{print $10}' | awk -F: '{print $1}' | awk '{++times[$1]}END{for(i in times)print "port: "i" ="times[i]}' | sort -n -k 2

效果如下:

Shell 脚本中,从字符串参数中提取数据是一项常见任务,可以通过多种方法实现,具体决于数据格式和提取需求。以下是一些常用的技术: ### 提取固定格式字符串中的数据 如果字符串参数具有固定格式,例如 `key=value`,可以使用 Bash 的字符串操作提取数据。例如: ```bash param="username=john_doe" username=${param#*=} # 提取等号后面的部分 echo "Username: $username" ``` 这种方法利用了 Bash 的参数扩展功能,`#*= ` 表示删除最短匹配的前缀,直到等号为止。 ### 使用正则表达式提取数据 对于更复杂的模式匹配,可以使用正则表达式。Bash 支持通过 `=~` 运算符进行正则匹配。例如,从 URL 中提取域名: ```bash url="http://www.example.com/path/to/resource" if [[ $url =~ ^https?://([^/]+) ]]; then domain=${BASH_REMATCH[1]} echo "Domain: $domain" fi ``` 这里使用了正则表达式 `^https?://([^/]+)` 来匹配 URL 的开头部分,并捕获域名。 ### 使用 `cut` 命令提取字段 `cut` 命令可以从文件或管道输入的每一行中提取特定字段。例如,从逗号分隔的字符串中提取第二个字段: ```bash data="apple,banana,orange" echo $data | cut -d',' -f2 ``` 此命令使用 `-d` 参数指定分隔符,并使用 `-f` 参数指定要提取的字段编号。 ### 使用 `awk` 提取数据 `awk` 是一种强大的文本处理工具,非常适合从结构化文本中提取数据。例如,从空格分隔的字符串中提取第一个字段: ```bash line="one two three" echo $line | awk '{print $1}' ``` `awk` 默认以空格作为字段分隔符,但可以通过 `-F` 参数指定其他分隔符。 ### 使用 `sed` 进行替换提取 `sed` 是一种流编辑器,可以用来进行复杂的文本转换。例如,从字符串中删除不需要的部分,仅保留特定模式: ```bash str="The price is $123.45" price=$(echo $str | sed 's/[^0-9.]*\([0-9.]*\).*/\1/') echo "Price: $price" ``` 此命令使用正则表达式匹配数字和小数点,并替换整个字符串为捕获的组。 ### 结合 `read` 和 IFS 提取数据 如果字符串参数包含多个值,可以使用 `read` 命令结合 `IFS`(内部字段分隔符)提取数据。例如: ```bash data="apple,banana,orange" IFS=',' read -r -a fruits <<< "$data" for fruit in "${fruits[@]}"; do echo "Fruit: $fruit" done ``` 此方法将字符串按逗号分割,并存储到数组中。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值