4. ibstatus命令实战:批量查看所有IB设备状态,结合脚本实现自动化巡检
说实话,刚接触InfiniBand网络那会儿,我最常用的命令就是ibstatus。为什么呢?因为它简单、直接,一眼就能看出所有IB设备的状态。你想想看,一个集群里几十台机器,每台可能插着好几块HCA卡,要是挨个登录上去看,那不得累死?
ibstatus这个命令,说白了就是帮你一次性把当前节点上所有IB设备的状态都列出来。我习惯在巡检脚本里第一个就调用它,先摸清整体情况再说。
4.1 ibstatus命令基础用法
先看看最基本的用法。直接在终端敲ibstatus,系统会返回所有IB设备的状态信息。我个人习惯先跑一遍这个命令,确认设备是否在线、链路是否正常。
# 查看所有IB设备状态
ibstatus
输出大概长这样:
Infiniband device 'mlx5_0' port 1 status:
default gid: fe80:0000:0000:0000:ec0d:9a03:0023:4567
base lid: 0x2
sm lid: 0x1
state: 4: ACTIVE
phys state: 5: LinkUp
rate: 100 Gb/sec (4X EDR)
link_layer: InfiniBand
Infiniband device 'mlx5_1' port 1 status:
default gid: fe80:0000:0000:0000:ec0d:9a03:0023:4568
base lid: 0x3
sm lid: 0x1
state: 4: ACTIVE
phys state: 5: LinkUp
rate: 100 Gb/sec (4X EDR)
link_layer: InfiniBand
嗯,这里要注意几个关键字段:
- state:端口状态,
4: ACTIVE表示正常,1: DOWN就麻烦了 - phys state:物理链路状态,
5: LinkUp说明线缆没问题 - rate:当前速率,比如
100 Gb/sec (4X EDR) - link_layer:链路层类型,InfiniBand还是Ethernet
3: INIT,别慌。这通常意味着端口正在初始化,等几秒再查一次就好。我在项目中遇到过,重启SM服务后,所有端口都会短暂进入INIT状态。
4.2 只看关键信息
有时候你不想看那么多细节,就想知道设备是不是活的。可以用-s参数,只显示摘要信息:
# 只看摘要
ibstatus -s
输出会精简很多:
mlx5_0: 1 ACTIVE (4) 100 Gb/sec (4X EDR)
mlx5_1: 1 ACTIVE (4) 100 Gb/sec (4X EDR)
这样一眼就能扫完。我写巡检脚本时,经常先用-s做快速检查,发现异常了再用完整输出定位问题。
4.3 指定设备查看
如果机器上有多块HCA卡,只想看某一块的状态,可以指定设备名:
# 查看指定设备
ibstatus mlx5_0
这在排查问题时特别有用。我记得有一次,集群里某台机器网络时断时续,我挨个查每块卡的状态,最后发现是第二块卡的物理链路有问题——光模块松了。
4.4 结合脚本实现自动化巡检
好了,基础用法讲完了。接下来才是重头戏——怎么把这些命令串起来,做成自动化巡检脚本。
我平时写巡检脚本,核心思路就三步:
- 收集数据:用
ibstatus拿到所有设备状态 - 解析数据:从输出里提取关键字段
- 判断告警:根据阈值或状态码决定是否报警
下面这个脚本,是我在实际项目中用过的简化版:
#!/bin/bash
# IB设备自动化巡检脚本
# 作者:资深网络工程师
# 用途:批量检查所有IB设备状态,异常时输出告警
# 定义颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
echo "=========================================="
echo " InfiniBand 设备巡检报告"
echo " 巡检时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "=========================================="
# 获取所有IB设备列表
DEVICES=$(ibstat -l 2>/dev/null)
if [ -z "$DEVICES" ]; then
echo -e "${RED}[ERROR]${NC} 未检测到任何IB设备"
exit 1
fi
# 逐个检查设备
for dev in $DEVICES; do
echo ""
echo "--- 检查设备: $dev ---"
# 获取设备状态
STATE=$(ibstatus $dev | grep "state:" | awk '{print $2}')
PHYS_STATE=$(ibstatus $dev | grep "phys state:" | awk '{print $2}')
RATE=$(ibstatus $dev | grep "rate:" | awk '{print $2}')
# 判断状态
if [ "$STATE" == "4" ] && [ "$PHYS_STATE" == "5" ]; then
echo -e " 状态: ${GREEN}正常${NC}"
echo " 速率: $RATE"
else
echo -e " 状态: ${RED}异常${NC}"
echo " 当前state: $STATE (期望: 4)"
echo " 当前phys state: $PHYS_STATE (期望: 5)"
# 这里可以加入告警逻辑,比如发邮件、写日志
# echo "告警: $dev 状态异常" >> /var/log/ib_monitor.log
fi
done
echo ""
echo "=========================================="
echo " 巡检完成"
echo "=========================================="
ibstat -l可以列出所有IB设备名称,比手动写死设备名更灵活- state=4且phys state=5才是正常状态,其他组合都要警惕
- 巡检脚本建议加入crontab,每5分钟跑一次
4.5 进阶:解析ibstatus输出到结构化数据
如果你想把数据存到数据库或者对接监控系统,纯文本输出就不够用了。我习惯用Python来解析ibstatus的输出:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 解析ibstatus输出,转为JSON格式
import subprocess
import json
import re
def parse_ibstatus():
"""解析ibstatus命令输出"""
result = subprocess.run(['ibstatus'], capture_output=True, text=True)
output = result.stdout
devices = []
current_device = {}
for line in output.split('\n'):
# 匹配设备名和端口
dev_match = re.match(r"Infiniband device '(\w+)' port (\d+) status:", line)
if dev_match:
if current_device:
devices.append(current_device)
current_device = {
'device': dev_match.group(1),
'port': int(dev_match.group(2))
}
continue
# 匹配各个字段
if 'state:' in line:
current_device['state'] = line.split(':')[1].strip()
elif 'phys state:' in line:
current_device['phys_state'] = line.split(':')[1].strip()
elif 'rate:' in line:
current_device['rate'] = line.split(':')[1].strip()
elif 'base lid:' in line:
current_device['lid'] = line.split(':')[1].strip()
# 添加最后一个设备
if current_device:
devices.append(current_device)
return devices
if __name__ == '__main__':
data = parse_ibstatus()
print(json.dumps(data, indent=2, ensure_ascii=False))
输出效果:
[
{
"device": "mlx5_0",
"port": 1,
"state": "4: ACTIVE",
"phys_state": "5: LinkUp",
"rate": "100 Gb/sec (4X EDR)",
"lid": "0x2"
},
{
"device": "mlx5_1",
"port": 1,
"state": "4: ACTIVE",
"phys_state": "5: LinkUp",
"rate": "100 Gb/sec (4X EDR)",
"lid": "0x3"
}
]
ibstatus输出格式略有差异。比如有些版本在state后面没有空格,有些版本会多一行空行。建议在解析时用正则表达式,而不是固定字符串截取。
4.6 实战:巡检结果可视化
光有脚本还不够,你得能直观地看到结果。我一般会把巡检结果输出成表格,方便快速定位问题:
#!/bin/bash
# 生成巡检报告表格
echo "+-----------------+------+--------+-----------+----------------+"
echo "| 设备名 | 端口 | 状态 | 物理状态 | 速率 |"
echo "+-----------------+------+--------+-----------+----------------+"
for dev in $(ibstat -l); do
PORT=1
STATE=$(ibstatus $dev | grep "state:" | awk '{print $2}')
PHYS=$(ibstatus $dev | grep "phys state:" | awk '{print $2}')
RATE=$(ibstatus $dev | grep "rate:" | awk '{print $2}')
printf "| %-15s | %-4s | %-6s | %-9s | %-14s |\n" \
"$dev" "$PORT" "$STATE" "$PHYS" "$RATE"
done
echo "+-----------------+------+--------+-----------+----------------+"
输出效果:
+-----------------+------+--------+-----------+----------------+
| 设备名 | 端口 | 状态 | 物理状态 | 速率 |
+-----------------+------+--------+-----------+----------------+
| mlx5_0 | 1 | 4 | 5 | 100 |
| mlx5_1 | 1 | 4 | 5 | 100 |
+-----------------+------+--------+-----------+----------------+
4.7 总结与最佳实践
最后,分享几个我多年积累的经验:
- 巡检频率:建议每5分钟一次,太频繁会增加系统负载,太稀疏可能错过故障
- 日志保留:至少保留30天的巡检日志,方便回溯问题
- 告警分级:state不等于4是严重告警,phys state不等于5是警告,速率下降是提示
- 联动处理:发现异常后,自动触发
iblinkinfo或ibdiagnet做深度诊断
说实话,ibstatus虽然简单,但用好它能让你的日常运维效率提升一大截。你想想看,以前要登录每台机器手动敲命令,现在一个脚本全搞定,还能自动告警——这才是自动化运维该有的样子。
下一章,我们会深入ibstat命令,看看它和ibstatus有什么不同,以及如何用它获取更详细的设备信息。