干这行的人应该都有过这种经历:业务那边火急火燎地过来说“存储上已经加了盘,怎么机器上看不到”,你跑到Linux主机上一敲fdisk -l,新磁盘连个影子都没有。大部分情况下,不是存储没加好,而是主机这边的SCSI层压根没去“重新认识”存储,甚至存储端可能连你这台主机的HBA卡WWN都没映射对。
这篇文章就是来彻底解决这个问题的。我会从HBA卡和WWN的基本概念说起,再到具体怎么查看WWN,以及如何正确地扫描存储空间让系统识别新磁盘,最后把我这些年踩过的坑和排查思路一并整理出来。适合刚接触存储管理的Linux运维,也适合那些平时只操作虚拟机、第一次接触FC SAN物理服务器的人。
1. 先把概念理清:HBA卡和WWN到底是什么
1.1 HBA卡在存储链路中的角色
HBA(Host Bus Adapter,主机总线适配器)说白了就是服务器和存储阵列之间的“桥”。普通的SATA/SAS硬盘直连时,主板上的控制器直接就能识别;但在FC(Fibre Channel,光纤通道)存储网络中,服务器不能直接看到存储设备,必须通过光纤线缆连到FC交换机,再连到存储阵列的前端端口。而HBA卡就是服务器这一侧负责把PCIe总线上的数据转换成FC协议帧的硬件设备。
你可以把HBA卡理解成网卡,只不过网卡转的是以太网帧,HBA转的是FC帧。常见的HBA卡厂商有QLogic、Emulex(现在归Broadcom)、Brocade等,服务器上几万块钱一块的卡,干的活说穿了就是这么回事。还有一部分是CNA(Converged Network Adapter)融合网卡,既能走FC(FCoE)也能走以太网,但在存储层面观察到的方式本质是一样的。
1.2 WWN、WWPN、WWNN,到底在说谁
WWN(World Wide Name)是光纤通道网络中每个设备或端口的全球唯一标识符,类似以太网网卡的MAC地址,但长度更长,通常是8字节(64位)或16字节(128位),在FC网络中实际使用的大多是8字节的形式。命名上通常带0x前缀,比如0x10000090fa123456,看起来是16个十六进制字符,其实前面0x后面对应的就是8字节。
WWN又分两种:
- WWPN(World Wide Port Name):端口级标识。每块HBA卡上有多少个物理端口,就有多少个WWPN。
- WWNN(World Wide Node Name):节点级标识。它标识的是整个HBA卡设备本身,同一块卡上的所有端口通常共享同一个WWNN。
为什么这两个要分开?因为在FC存储环境里,存储阵列做LUN映射时基本上只认WWPN。你把一块双口HBA卡的端口1和端口2分别接到两台FC交换机上,存储端做主机组配置时,就要让这个“主机”包含这两个WWPN,这样两个端口都能看到存储,才能做多路径。
我在刚开始接触这块时也迷糊过,老是混用两个概念,直到有一次在存储端把WWNN填进去做映射,结果怎么都扫不到盘,才彻底记住:存储认的是端口级WWPN,而不是WWNN。当然,也有一些老设备、老存储管理界面会让你填WWNN,但绝大多数情况下你要找的是WWPN。
1.3 Linux内核里和FC相关的内容
Linux系统对FC HBA卡的支持主要靠两个内核模块:qla2xxx(对应QLogic的卡)和lpfc(对应Emulex的卡)。系统启动时驱动会加载,把每个HBA物理端口注册成一个SCSI主机适配器(host),在/sys/class/scsi_host/目录下面就能看到host0、host1这样的目录,每个host对应一个物理端口,也对应一个独立的WWPN。
在你查看WWN之前,先确认驱动加载正常、端口链路起来了,否则后面所有操作都是在跟空气较劲。
2. 查看HBA卡WWN的实操方法
先说结论,查看HBA卡WWN最干净、最可靠的方式不是装第三方工具,而是直接读内核导出的sysfs接口。以下方法在RHEL、CentOS、Rocky、Ubuntu、SUSE等主流发行版上都通用。
2.1 先确认HBA卡被系统识别
首先查看系统里有多少个FC HBA端口:
ls /sys/class/fc_host/正常输出是host0、host1这样的目录。如果这个目录不存在,说明系统里没有FC HBA卡,或者驱动没加载成功。可以用lspci看硬件本身有没有被识别到:
lspci | grep -i fibre lspci | grep -i "storage controller"QLogic的卡在lspci里一般会显示类似“QLogic Corp. ISP2722-based 16G Fibre Channel to PCIe Adapter”的字段,Emulex会显示“Emulex Corporation OneConnect 10Gbps/16Gbps ...”,如果是系统里的其他RAID卡,也会出现在storage controller下面,注意区分。
这块卡如果连lspci都看到不,那就是硬件层面的事,先检查PCIe插槽接触、服务器BIOS里PCI设备是否被禁用等,而本文后续所说的查看和扫描就无从谈起。
2.2 从sysfs读取WWN
确认fc_host目录存在后,逐个host读port_name和node_name:
cat /sys/class/fc_host/host0/port_name cat /sys/class/fc_host/host0/node_name输出是类似这样的:
0x10000090fa123456 0x20000090fa123456第一个是WWPN,第二个是WWNN。如果机器上有多个host,就逐个读取。也可以一条命令看全部:
for host in /sys/class/fc_host/*; do echo "$(basename $host) -> WWPN: $(cat $host/port_name) WWNN: $(cat $host/node_name)"; done这里我特别说明一下:市面上很多人的习惯是用systool -fc_host host0 -v或者cat /sys/class/fc_host/host0/port_name,两者结果一样。但systool需要额外安装sysfsutils工具包,有些最小化安装的服务器没有这个命令,而/sys目录是内核虚拟文件系统,每个Linux都必然存在,所以直接用cat是最不会出错的做法。
注意:port_name文件里读出的是带0x前缀的WWN。在存储阵列上填写主机WWPN时,有的存储界面需要带0x,有的不需要,还有的要求中间加冒号分隔。建议你先确认存储端界面是什么格式要求,再对着填,免得因为格式问题导致映射不生效。
2.3 用systool看更详细的HBA信息
如果你需要更多诊断信息,比如HBA卡的型号、固件版本、端口状态、协商速率,systool确实更方便:
yum install -y sysfsutils # RHEL系 apt install -f sysfsutils # Debian/Ubuntu systool -fc_host host0 -v输出看到的信息会包括port_name、node_name、port_state、speed等。其中port_state如果是Online,说明光纤链路已经和FC交换机成功通信;如果是Offline,那光纤没通或者交换机端口的zone没放通,后面扫描存储也必然失败。
说实话,生产环境里我用得最多的其实是另外两个文件:
cat /sys/class/fc_host/host0/port_state cat /sys/class/fc_host/host0/fabric_nameport_state表示链路状态,fabric_name表示登录到的FC交换机(Fabric)的WWN。如果fabric_name为空或者显示0x0000000000000000,说明这个HBA端口根本没登录进交换机,那查WWN之后再怎么弄也是白搭。
2.4 多端口HBA卡如何对应物理位置
一块双口HBA卡在系统里通常是两个host,比如host0和host1。怎么知道哪个host对应物理上的哪个SFP光模块?
一个简单思路是看PCI地址再对应到服务器槽位:
ls -l /sys/class/scsi_host/host0输出中会带一个指向PCI设备的软链接,里面能看到类似0000:04:00.0的地址,这个代表PCI总线地址。再到服务器BMC/BIOS里看PCI槽位布局图,就能对应上物理位置。不过大多数情况下你不用分这么细,因为无论哪个物理端口,只要链路都是通的,存储扫描都能正常工作,你要的只是每个端口自己的WWN而已。
但如果只有其中一个端口配置了接入交换机、另一个空着,那你需要能区分:看port_state是Online的那个host对应插线了的端口,这样记录WWN时就不会把没接线的端口WWN也交给存储管理员。
2.5 再往前一步:确认驱动与固件信息
想看驱动的模块名、版本,可以:
lsmod | grep -E "qla2xxx|lpfc" modinfo qla2xxx | grep version这条信息在排查“HBA卡温度过高导致端口随机掉线”之类问题时很有用。但在查看WWN这一步,确认驱动加载即可,不必深究。
3. 扫描存储空间,让新LUN现身
WWN查到了,存储端也告诉你映射已经做好了,那下一步就是在Linux主机上扫描存储空间,让内核重新去存储那里“串门”,把新的LUN拉出来。
3.1 扫描前必须做的准备动作
先别急着敲扫描命令,我遇到过太多因为跳过了这一步而误操作的情况。准备动作不多,但每一条都在关键时刻救过我:
- 在存储端确认主机WWPN已经加入主机组,LUN映射已下发,有些存储还需要手动“应用”配置,千万别只保存就关界面。
- 在FC交换机侧确认zone已配置,主机端口和目标存储前端端口在同一zone内,zone配置是实时生效的,但有些老交换机需要active保存。
- 在主机上先记录当前磁盘状态,最简单是lsblk和fdisk -l各执行一次,把输出留存。为什么要留?扫描完成后你看到新增了sdd、sde,但万一之前就有这些名字呢?先留存一份现状快照能避免把老磁盘当新磁盘来折腾。
- 确认多路径软件的状态,如果生产环境都在用多路径,执行systemctl status multipathd确认进程活着。
3.2 核心扫描命令解析
扫描FC存储最核心的命令是往sysfs里写“重新扫描”指令:
echo "- - -" > /sys/class/scsi_host/host0/scan这个命令的意思是,让host0这个SCSI主机适配器去总线上的所有target、所有LUN重新扫描一遍。三个“-”依次代表通道(channel)、目标(target)、LUN(lun),写成通配符就表示全部扫描。
如果你想精准一点,比如存储端告诉你在某个target下新增的LUN ID是5,也可以这样:
echo "0 0 5" > /sys/class/scsi_host/host0/scan第一个0是channel,第二个0是target(这个值一般是存储前端口映射出来的target id),第三個5是LUN ID。我自己很少用这种精准模式,因为多路径环境下target id不好判断,直接用“- - -”扫就行,代价只是多占用一点点总线的带宽,内核层面不会有其他副作用。
如果host0、host1对应两个光纤端口,而两个端口都连到了同一个存储,那就两个host都扫一遍:
for host in /sys/class/scsi_host/host*/scan; do echo "- - -" > $host; done注意不要扫/sys/class/scsi_host下面的非FC hosts,比如服务器本身的SAS控制器也会注册成host,盲目对整个系统所有SCSI主机都扫一遍其实也没问题,但生产环境还是精准一点好,只扫你自己确认过是FC的那几个host。
3.3 扫描后怎么确认是否识别成功
扫描命令执行后,先等一两秒让内核完成设备注册,然后查看新出现的磁盘:
lsblk fdisk -l lsscsilsscsi这个命令非常直观,它把SCSI设备和对应的host、channel、target、lun都列出来。例如输出中出现:
[2:0:0:5] disk IBM 2107 0000就说明是host2下发现的LUN 5,对应一台IBM存储卷。如果输出的sd设备里有新面孔,再看lsblk确认大小是不是你刚才在存储上创建的那个LUN容量。
我习惯用multipath -ll来看多路径盘:
multipath -ll输出里如果出现类似:
mpatha (360050768028103c0b8000000000000) dm-2 IBM,2107说明新盘已经被多路径接管了,路径数、设备大小、优先生效路径都显示得很清楚。
3.4 关于多路径的一点点补充
如果这台机器装了multipath,扫描到的新LUN通常不会以裸盘的sdX直接提供服务,而是被device-mapper多路径设备名接管,比如/dev/mapper/mpatha。真正给数据库、给文件系统用的那块盘,是/dev/mapper/下面的设备,不是sdX。
以下情况可以说明为什么多路径重要:线上机器的HBA卡几乎都是至少两个端口接两台交换机,存储那边也至少映射给两个前端端口。结果就是你在Linux里会同时看到sdd和sde,它们大小一样,其实是同一个LUN的两条路径。如果没有多路径软件,直接对sdd格式化、挂载是极其危险的做法,一旦某根光纤链路中断,数据就可能损坏。有了multipath,这两条路径被抽象成一个dm设备,系统只认那个dm设备,某一条路径断了会自动切换,不影响业务。
这里有个坑需要单独提醒:如果你在扫描之前multipathd没起来,或者multipath.conf里没有匹配这个盘的配置规则,新扫出的盘就会以裸盘形式暴露,这样最直接的后果是设备号混乱。也就是说,你原本应该用/dev/mapper/mpatha做LVM的,现在系统控制不住它了。正确做法是确认multipathd正常、检查multipath -ll之后再做后续动作,任何情况下都不要直接对一条路径的sdX做格式化。
3.5 通过WWN名找到新磁盘
Linux下其实提供了更方便的对应关系,扫描成功后,/dev/disk/by-id/目录里会生成以wwn开头的符号链接:
ls -l /dev/disk/by-id/ | grep wwn输出类似:
wwn-0x60050768028103c0b8000000000000 -> ../../sdd这个wwn就是存储LUN的WWN,和HBA卡的WWN不是一个概念,别搞混。它帮助你确认:这个磁盘确实就是存储上那个LUN。在给磁盘分区、建LVM之前,建议先看这个链接对应哪个设备,确认设备号没有变化。
注意:每次重启服务器,sdX这种设备名都可能因为探测顺序变化而变化,但by-id这种方式是稳定的。写fstab、做multipath配置、配LVM时,能不用/dev/sdX就不用,尽量用/dev/disk/by-id/或/dev/mapper/下的稳定名称。
3.6 完整示例:从扫描到让LVM识别新空间
假设这台机器装了multipath,存储上已经把一块新LUN映射给主机,LUN大小为500GB,现在要在主机上完成扫描并扩展给数据库使用。
第一步,查看当前SCSI主机和链路状态:
ls /sys/class/fc_host/ cat /sys/class/fc_host/host0/port_state cat /sys/class/fc_host/host0/fabric_name确认host0、host1都是Online且能连上fabric。
第二步,扫描所有FC host:
for host in /sys/class/scsi_host/host{0,1}/scan; do echo "- - -" > $host; done第三步,等两秒,查看新磁盘:
lsblk lsscsi multipath -ll正常情况下能看到新多路径设备,比如mpathb,大小500G。
第四步,把它加入LVM并扩展逻辑卷。如果之前这个卷组里已经有很多物理卷,用如下命令:
pvcreate /dev/mapper/mpathb vgextend vgdata /dev/mapper/mpathb lvextend -l +100%FREE /dev/vgdata/lvdata如果这块盘之前已经做过pv且有数据,那就用pvresize扩展:
pvresize /dev/mapper/mpathb第五步,文件系统扩容。XFS用xfs_growfs,ext4用resize2fs:
xfs_growfs /data # 如果是XFS,挂载点直接扩 resize2fs /dev/vgdata/lvdata # 如果是ext4到这里,存储上新加的空间就算真正被系统用上了。
3.7 扫描命令以外的另一种方式:rescan-scsi-bus.sh
部分发行版上有sg3_utils提供的一个脚本叫rescan-scsi-bus.sh,在RHEL/CentOS上路径通常是/usr/bin/rescan-scsi-bus.sh,Debian系在/usr/bin/rescan-scsi-bus.sh也常见。它的本质还是对系统里所有SCSI主机执行扫描,但多了对已存在设备大小变化的重扫描逻辑。
yum install -y sg3_utils rescan-scsi-bus.sh --all这条命令会遍历所有SCSI主机执行scan。好处是省得自己写循环,坏处是它可能把非FC的SCSI主机也扫一遍。如果你明确知道只需要扫FC的host,那自己写for循环更精确。我一般把这两种方式结合在一起用:先for循环扫FC host,然后rescan-scsi-bus.sh --all兜底,确保任何设备变更都能被发现。
4. 扫不到新盘?一套完整的排查思路
扫描命令执行完了,lsblk还是没看到新盘,这是最常见的问题。我从问题表象出发,按排查顺序说,能省下不少瞎折腾的时间。
4.1 先看链路,再看映射,最后才看主机
我见过太多人一上来就在主机端反复扫描、重启服务器,折腾两小时还是看不到盘,结果一查FC交换机发现zone根本没配。所以请按下面的顺序排查:
第一步,主机端看链路状态和登录状态:
cat /sys/class/fc_host/host0/port_state cat /sys/class/fc_host/host0/fabric_nameport_state要是Online,fabric_name要是一串非全0的WWN。如果port_state是Offline,说明光纤链路都没通,后面就可以不看了,先解决物理链路和交换机端口注册的问题。
第二步,看dmesg里有没有FC登录或SCSI错误信息:
dmesg | grep -i -E "qla2xxx|lpfc|scsi"如果看到类似“qla2xxx 0000:04:00.0: entered - aborting the command directly”之类的内容,说明链路是好的,但可能有命令超时或端口被禁用,需要进一步看交换机和存储端的配置。
第三步,到FC交换机上看主机端口是否登录成功,以及zone是否包含目标存储端口。不同厂商交换机命令不同,但都会有对应的“show flogi database”和“show zone”之类的功能。这一步需要交换机管理权限,如果你是主机运维,可以跟网络/存储管理员配合。
第四步,到存储端确认LUN映射确实包含主机的WWPN,很多存储界面需要点“应用”或“确定”才真正生成映射关系,而且可能有一定的配置下发延迟,等一两分钟再刷新看看。
4.2 我扫描了多个host,但只有其中一个看到盘
这种情况很典型。比如host0扫到了新LUN,host1没扫到。原因很可能是存储端给主机映射时,只把WWPN之一加到了主机组里,或者FC交换机上zone只包含了主机的一个端口。
这时回到第2部分再核对一遍:把每个host的WWPN都记下来,交给存储管理员确认是否都在主机组里。我碰到的另一个原因是HBA端口速率协商不一致,比如交换机端口强制8G、HBA端口协商成了4G,也会导致连接不上或掉线,但这通常会在FC交换机上有告警日志,排查时需要留意。
4.3 扫描之后smdev出现了,但multipath -ll看不到它
先看multipathd是否在运行:
systemctl status multipathd再确认配置是否有匹配规则。有时候系统自动识别了sdX,但没有匹配到multipath.conf里的配置,它就会作为普通磁盘暴露。可以把wwid找到,手动添加规则,然后reload multipathd:
/sbin/multipath -l /usr/lib/udev/scsi_id -g -u /dev/sdd拿到wwid之后,在/etc/multipath.conf里加一条multipaths配置,指定alias和wwid,然后:
systemctl reload multipathd这个坑在混合厂商存储环境里特别常见,因为Linux默认的配置模板只识别一部分常见的设备类型,小众存储需要手动加规则才行。
4.4 扩容时发现磁盘容量没变
如果原本已经有一个LUN映射给主机,后来在存储端把LUN扩容了,但主机上看到的大小还是旧值,这时要做的不是重新scan整个host,而是对这个具体的SCSI设备做rescan:
echo 1 > /sys/block/sdd/device/rescan如果是多路径设备下的路径,要分别对每一条路径的sdX执行rescan,然后multipathd会自动感知容量变化。之后再:
multipathd reconfigure pvresize /dev/mapper/mpatha就能看到卷组可用空间变大了。记住一点:不要在LVM已经挂载使用的状态下直接做host扫描,某些场景下面可能会造成系统I/O路径上的短暂阻塞,影响业务。在线扩盘的正确姿势是精准rescan目标设备。
4.5 虚拟机上关于HBA和存储扫描的区别
如果你是在虚拟机里做测试,比如VMware虚机、KVM虚机里试图用本文的方式扫描FC存储,需要分辨两种情况:
- 虚拟机使用的是虚拟SCSI控制器(通常的默认方式),这种环境下/sys/class/fc_host/目录不存在,也谈不上HBA卡WWN,你看到的SCSI设备是虚拟出来的,一般不用扫描也能识别新添加的虚拟磁盘。
- 虚拟机直通了物理HBA卡(PCI Passthrough),这种情况下虚机才能看到真实的FC HBA和WWN,扫描方式才和物理机一致。
换句话说,如果你在VMware ESXi上的虚拟机里找不到fc_host目录,不用怀疑操作问题,先确认是不是没有做PCI直通。对于直接使用虚拟磁盘的虚机,新加虚拟磁盘后只需要在系统里执行echo "- - -" > /sys/class/scsi_host/hostX/scan即可,这个操作路径一样,但概念上跟FC存储完全是两回事。
4.6 扫描FC存储的常见误解
有些同事总以为扫描存储就是把服务器重启一下,或者重新插拔一下光纤线。这些动作在生产环境里代价非常大,而且没必要。理解内核的扫描机制之后你就会明白,所谓扫描就是向内核的SCSI子系统发出“重新枚举总线”的请求,根本不用动硬件,更不用重启。
再一个误解是,认为WWN只有存储工程师才需要。其实作为Linux运维,你必须能随时把本机HBA的WWPN准确报给存储工程师,否则存储那边没法做映射,两边扯皮半天才发现原来是你没有正确把WWN发给对方。学会自己查WWN,很多问题就不再需要拉一堆人开会了。
5. 顺手总结几个可靠的小技巧
说点实操中值得记住的细节。查看WWN和扫描存储这件事,本身命令不多,但执行顺序和记录习惯才是真正拉开运维水平的地方。
我在处理几百台服务器的存储映射时,养成了一套自己的固定流程:先把所有主机的WWPN统一记录下来,按机器名、机房位置、机房机柜编号整理成表格,再发给存储管理员做映射。这个习惯帮我避免过无数次设备搞混、端口搞错的问题。具体记录时,推荐用heredoc脚本一次采集所有信息:
for host in /sys/class/fc_host/*; do echo "Host: $(basename $host)" echo "WWPN: $(cat $host/port_name)" echo "WWNN: $(cat $host/node_name)" echo "State: $(cat $host/port_state)" echo "Speed: $(cat $host/speed)" echo "---" done执行完之后把输出整理到文档里,这就是这台服务器的HBA信息清单。服务器维保更换HBA卡之前,也建议先采集这样一份清单,换完卡之后对比,能快速发现WWN是否变化,从而判断需要让存储端运维更新哪些映射关系。
扫描存储空间时,我的另一个心得是“先并行扫所有FC host,不要一个一个试”。有些人不确定哪条链路承载了存储路径,就host0扫一下没看到,host1扫一下没看到,反反复复浪费很多时间。一次性把两个端口都扫了,再看结果,效率高得多。
还有一个我踩过坑的细节:扫描之后如果发现新盘,但fdisk -l里看不到它的容量,大概率是这条路径只是部分LUN映射成功了,或者多路径路径数不对。这时用multipath -ll看清楚路径数量,理想条件下应该看到两条active路径,如果只看到一条,说明另一个HBA端口、交换机或者存储前端端口根本没真正连通,别急着继续往下做格式化,先解决路径问题。
最后一个建议,也是我反复跟团队强调的:在生产环境做任何存储扫描、分区、格式化操作之前,保留现场信息是一个好习惯。最简单的做法是执行扫描前把lsblk、multipath -ll、pvs、vgs、df -h这几条命令的输出都重定向到文件留存,一旦操作过程中发现不对劲,还能回到之前的现场数据对照。扫描命令本身是无害的,后续的分区、格式化、挂载才是真正影响数据安全的地方,谨慎一点,总没有坏处。