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
小技巧:如果看到state是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 结合脚本实现自动化巡检

好了,基础用法讲完了。接下来才是重头戏——怎么把这些命令串起来,做成自动化巡检脚本。

我平时写巡检脚本,核心思路就三步:

  1. 收集数据:用ibstatus拿到所有设备状态
  2. 解析数据:从输出里提取关键字段
  3. 判断告警:根据阈值或状态码决定是否报警

下面这个脚本,是我在实际项目中用过的简化版:

#!/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是警告,速率下降是提示
  • 联动处理:发现异常后,自动触发iblinkinfoibdiagnet做深度诊断

说实话,ibstatus虽然简单,但用好它能让你的日常运维效率提升一大截。你想想看,以前要登录每台机器手动敲命令,现在一个脚本全搞定,还能自动告警——这才是自动化运维该有的样子。

下一章,我们会深入ibstat命令,看看它和ibstatus有什么不同,以及如何用它获取更详细的设备信息。