如何过滤ping输出提取纯数值延迟,触发traceroute脚本?
问题背景
我和互联网服务提供商(ISP)存在网络问题,虽然已经搭建了Smoke Ping服务器,明确检测到间歇性延迟峰值与丢包,但ISP要求针对Smoke Ping的每个目标提供两组traceroute数据:无延迟/丢包时的,以及出现问题时的——他们要靠这个排查路由问题。
我已经写了能一次性对所有目标执行traceroute并输出到文件的脚本,但还需要一个脚本在延迟超过阈值时自动调用这个traceroute脚本。我自己写了个脚本,但因为cut命令输出的延迟包含数字和"ms"后缀,导致判断逻辑失效,请问怎么过滤输出只保留纯数值?
我写的错误脚本如下:
#/bin/bash while : if [ ping | cut -f5 d" " -gl 400 ] then wait 15 else ./path/script fi done
解决方案
没问题,咱们一步步来修正这个问题:
1. 先搞定纯数值提取
你的核心问题是cut没法精准剥离"ms"后缀,而且不同系统的ping输出格式可能略有差异,推荐用下面几种更可靠的方式提取延迟数值:
方法一:用grep的Perl正则(最简洁)
直接匹配time=后面的数字部分,忽略所有非数字内容:
ping -c 1 你的目标IP或域名 | grep -oP 'time=\K[0-9.]+'
-oP表示启用Perl正则并只输出匹配部分\K会忽略前面的time=,直接提取后面的数字(支持小数,比如350.2ms会提取成350.2)
方法二:用awk分割字段
通过指定分隔符(空格、=、ms)来拆分ping输出,提取对应字段:
ping -c 1 你的目标IP或域名 | awk -F'[=ms ]+' '/time=/ {print $4}'
如果你的ping输出格式不同(比如有些系统是time=400ms没有空格),可以调整分隔符为[=ms]+,字段位置也可能需要微调,执行一次ping看看输出就能确定。
方法三:用sed替换非数字内容
把time=到ms之间的数字以外的内容全部替换掉:
ping -c 1 你的目标IP或域名 | sed -n 's/.*time=\([0-9.]*\).*/\1/p'
2. 修正完整脚本逻辑
你的原始脚本还有语法错误(比如while循环写法、wait应该是sleep、条件判断格式错误),这里给你一个完整可用的版本:
#!/bin/bash # 配置参数 TARGET="你的目标IP或域名" # 替换成你要监控的目标 THRESHOLD=400 # 延迟阈值,单位ms CHECK_INTERVAL=10 # 正常状态下的检查间隔,单位秒 while true; do # 获取当前延迟数值(如果ping失败则为空) LATENCY=$(ping -c 1 "$TARGET" | grep -oP 'time=\K[0-9.]+') # 检查延迟是否超过阈值 if [[ -n "$LATENCY" && $(echo "$LATENCY > $THRESHOLD" | bc -l) -eq 1 ]]; then echo "[$(date)] 检测到延迟超过阈值!当前延迟: ${LATENCY}ms" echo "15秒后执行traceroute脚本..." sleep 15 ./path/your_traceroute_script.sh # 替换成你的traceroute脚本路径 else # 延迟正常或ping失败,输出日志并等待下一次检查 echo "[$(date)] 延迟正常(当前: ${LATENCY:-ping失败}ms),等待${CHECK_INTERVAL}秒后重试..." sleep "$CHECK_INTERVAL" fi done
脚本说明:
- 用
bc -l来处理浮点数比较(比如延迟是400.5ms也能正确判断) - 增加了时间戳日志,方便排查问题
- 处理了ping失败的情况(比如目标不可达时
LATENCY为空) - 可配置的参数放在开头,方便后续修改
内容的提问来源于stack exchange,提问作者jerk
相关产品推荐
相关产品推荐

