写这一篇的起因很简单:做存储的同事丢过来一个LUN的WWN字符串,问你“这盘在机器上到底是sdb还是sdc”,你Linux窗口里敲了一排lsblk,发现压根对不上号;要么就是Windows机器上接了一个存储分配的卷,想确认映射的是不是那一块,却不知道在哪个界面找个16位长的ID。干了几年运维的人,对这些东西多少有点印象,但真要一次讲清楚Linux和Windows分别怎么看块存储的WWN,还真未必能说全。这篇就把我平时排查存储映射、多路径、磁盘故障时真正用过的命令和方法梳理一遍,把WWN这个概念和两个操作系统下的查法一次性讲透。
1. 先把WWN这个概念掰开:它到底是给谁用的编号
1.1 WWN和WWNN、WWPN、WWID的区别
WWN全称World Wide Name,直译就是“全球通用名称”,本质上是存储设备的一种全球唯一标识符,通常是一个8字节的十六进制数,在FC(光纤通道)环境里最常见。很多人会把WWN、WWPN、WWNN、WWID混着叫,实际用的时候确实有细微差别。
在光纤通道体系里,一台主机上的HBA卡(光纤通道适配卡)自身有两个WWN:一个是节点WWN,叫WWNN,对应整个主机节点,相当于一台机器的身份标识;另一个是端口WWN,叫WWPN,对应HBA卡上的某一个物理端口,相当于这个节点下接出去的某条网线的身份标识。所以一块双口FC HBA卡,通常能看到1个WWNN加2个WWPN。存储阵列上的控制器端口也类似,存储侧每个FC端口同样有自己的WWPN。两台FC设备之间互相访问,就是通过WWPN来识别对方的。
而对于块存储设备(比如存储阵列映射给主机的LUN,也就是最终落成磁盘的那块“逻辑盘”),主机侧看到的是SCSI磁盘设备,它的唯一标识在标准里叫WWID(World Wide Identifier),但实际大家习惯也叫它WWN,表现形式一般是一个以0x开头的16位十六进制数,比如0x5000c500abcdef01这样。在Linux系统的/dev/disk/by-id/目录里,这种磁盘的链接名直接就叫wwn-0x5000c500abcdef01,所以日常说“查看块存储的WWN号”,指的就是这个SCSI设备的WWID。
打个比方:如果把存储阵列比作一座仓库,WWNN是仓库的营业执照号,WWPN是仓库的某一扇大门的编号,而映射出来的LUN的WWN就是仓库里每一托货上的唯一条码。主机要从仓库拿货,先得知道哪扇门(WWPN)可以进,货拉回来以后,还得核对每一托货的条码(LUN的WWN),才知道自己车里装的是不是想要的货。
1.2 为什么要查WWN:场景基本集中在三类
第一类也是最常见的场景,存储映射排查。存储工程师在阵列上给某台服务器映射了一个LUN,然后说“已经给你划好了”。主机这边需要确认映射是否成功、新出现的盘是什么。光看盘符大小不够,因为可能映射了多个同样大小的LUN,唯一可靠的办法就是拿存储侧显示的LUN WWN和主机侧设备读取出来的WWN比对。
第二类是FC多路径和故障切换排查。多路径软件把同一个LUN通过两个以上路径暴露给主机,主机显示sdb和sdc其实都指向同一个底层LUN。这个时候如果不看WWN,直接用sdb去配置文件系统或者做分区,很容易因为路径切换导致数据访问异常。多路径工具multipath -l也会把每个dm设备对应的WWN显示出来,查WWN属于基本操作。
第三类是磁盘/盘柜故障更换。直连磁盘柜(JBOD)或存储内部磁盘坏了,系统日志里只会写死一串WWN或者设备路径,要确定物理上是哪一块盘、盘柜里哪个槽位,也需要通过WWN对照硬件标签或者盘柜管理界面去定位。
另外,虚拟化平台的磁盘标识、备份软件对存储设备的识别,也都依赖WWN。总之,只要你想确认“主机上看到的这个盘,就是存储上分配的那个盘”,就必须用到WWN。
2. Linux查看WWN:命令看着多,其实就三个层次
2.1 最省事的入门命令:lsblk和by-id链接
Linux下最简单的查法,一条lsblk就够了。新的util-linux版本默认支持显示WWN字段:
lsblk -o NAME,WWN,SIZE,MODEL,SERIAL输出大致如下:
NAME WWN SIZE MODEL SERIAL sda 0x5000c500abcdef01 600G INTEL SSD xyz123 sdb 0x5000c50012345678 2.0T HITACHI HUS726 zyx987这个命令非常直白,每一块盘后面的WWN列就是它的块存储标识。如果只想要某个盘,可以指定设备名:
lsblk -o NAME,WWN,SIZE /dev/sdb还有一个更接近“底层真相”的地方是/dev/disk/by-id/目录。Linux内核在识别SCSI磁盘时,会按照设备的WWID生成一个持久命名链接,形式如下:
ls -l /dev/disk/by-id/wwn-0x*可以看到类似:
lrwxrwxrwx 1 root root 9 几月几日 10:24 wwn-0x5000c500abcdef01 -> ../../sda lrwxrwxrwx 1 root root 9 几月几日 10:24 wwn-0x5000c50012345678 -> ../../sdb对照一下即可。这里有一个所有运维都应该养成的习惯:在脚本里引用磁盘时,不要写死/dev/sda这类不稳定路径,尽量用by-id下的wwn-0x/.../映射,因为盘符会随着重启或插入顺序变化,WWN是跟着设备走的。
2.2 底层查询:sysfs和scsi_id
如果lsblk输出里WWN列是空的(老版本或某些内核配置下可能出现),可以直接去sysfs里翻。SCSI磁盘设备对应路径是/sys/block/sdX/device/,下面有一个wwid文件:
cat /sys/block/sdb/device/wwid输出类似:
naa.5000c50012345678这里的naa是Network Address Authority的缩写,是FC网络地址分配的一种格式,后面跟的十六进制和WWN完全对应。有些设备上读出来是t10.xxx开头,有的叫eui.xxx,这些都代表不同的标识类型,但用途一样。
scsi_id命令是Linux SCSI设备标识的标准工具,在udev规则里用得很多。手动查看也很简单:
scsi_id -g -u -d /dev/sdb-g表示读取设备的VPD信息,-u表示输出不带厂商前缀的十六进制标识,-d指定设备路径。输出会是一串不带0x前缀的十六进制数,和by-id里的wwn-0x后面的部分完全一致。这个命令的优点是只要SCSI子系统能识别设备,基本都可靠,比lsblk在虚拟机等环境里更稳妥。
2.3 光纤通道HBA的WWN怎么查
如果是查HBA卡本身的口子上的WWN(也就是WWPN/WWNN),不能用上面那些磁盘命令,需要去FC主机目录下看。Linux内核把每个FC主机口表示为/sys/class/fc_host/hostN目录,例如:
cat /sys/class/fc_host/host2/node_name cat /sys/class/fc_host/host2/port_namenode_name对应的是WWNN,port_name对应的是WWPN。输出格式通常是0x开头的一长串十六进制。如果装了lsscsi,还格外好使:
lsscsi -g -H其中-H或--hosts参数可以列出FC主机端口信息。实际上很多运维根本不记目录路径,直接靠systool或lsblk,但sysfs这条路永远是最原生的。
如果还要看存储侧对面端口的WWN(即主机连的存储控制器端口的远程端口WWN),在/sys/class/fc_remote_ports/下能看到:
cat /sys/class/fc_remote_ports/rport-2:0-1/port_name这个值表示主机这个FC口对面连接的存储端口WWPN,在做zone映射排查时有用。
2.4 拿sg_inquiry做终极校验
有些场景下,上面几种方法读出来的值让你不放心,尤其当设备是旧式存储或经过特殊映射时,可以用sg_inquiry直接读SCSI标准VPD页里的设备标识。sg3_utils包提供了这个工具:
sg_inquiry -p 0x83 /dev/sdb输出会包含Device Identification VPD page,下面列出各种设计ator类型。其中NAA开头的6或6h类型的那条,就是块设备的WWN。这段输出比较长,一般只需要看包含“NAA”或“0x5000”的行。这个方式的优点是完全绕开操作系统层面,直接和磁盘设备“对话”,对排障非常有力。
3. 在Windows上查块存储WWN:别只盯着磁盘管理
3.1 PowerShell几步拿全量磁盘WWN
Windows下最便捷的方法是PowerShell配合存储管理模块。打开管理员权限的PowerShell,输入:
Get-Disk | Select-Object Number,FriendlyName,SerialNumber,UniqueId,Size输出里UniqueId字段在不同的磁盘上表现不同:有些盘显示的是WWN(一个以0x开头的16位十六进制数),有些盘显示的是磁盘签名(Disk Signature,一般是8位十六进制),还有一些多路径盘会显示为path形式的标识。要拿WWN,可以加个过滤:
Get-Disk | Where-Object {$_.UniqueId -like "0x*"} | Select-Object Number,FriendlyName,UniqueId从Windows Server 2012开始,微软的存储栈会把SCSI设备的WWN放进UniqueId,所以这条命令在绝大多数FC存储环境下都能直接命中。对于直连SATA/SAS盘,UniqueId里更多是磁盘签名,这时要看SerialNumber字段才准。
需要注意,Windows磁盘管理界面只显示磁盘的“磁盘N”和容量信息,没有WWN列,所以很多人第一反应去磁盘管理里找肯定找不到。
3.2 MPIO多路径下怎么确定LUN对应关系
Windows Server上做FC多路径的常见方案是MPIO(Multipath I/O)。装了MPIO之后,同一个LUN会通过多个路径暴露给系统,但是Get-Disk只显示一个逻辑磁盘,这时看到的UniqueId就是底层LUN的WWN。如果发现同一个LUN太多重复项,可以用mpclaim工具:
mpclaim -s -dmpclaim是Windows MPIO自带的命令行工具,-s -d参数会列出每个MPIO设备的管理信息,包括对应的磁盘和路径数。更好用的方式是用PowerShell查MPIO拓扑:
Get-MPIOSetting Get-MSDSMGlobalDefaultLoadBalancePolicy但这些偏策略配置。实际排查时,我一般直接在PowerShell里把磁盘和它的路径对应起来:
Get-Disk | Get-MPIOPath从返回的PathId和对应磁盘,可以确认这块盘是不是走了双活路径,每个路径对应的存储端口。而最核心的确认WWN还是回到Get-Disk的UniqueId。
3.3 Windows下查HBA端口WWN:两套路子
Windows下查FC HBA卡的WWPN/WWNN,PowerShell没有原生命令。HBA厂商提供的工具各自不同,早期产品大多带GUI界面,直接在“Port Information”或“Adapter Details”里能看到WWPN/WWNN。无GUI服务器上,也可以尝试通过WMI访问HBA驱动私有接口,但基本没有统一标准,很多情况下你是拿不到的。
更通用的做法是从FC交换机侧反查。登录FC交换机,执行:
switchshow可以看到每个端口上登录的主机设备的WWPN,再对应查别名或zone。如果只想看某个端口下登录的设备:
portlogdump或:
fcaliasshow从交换机上看到的WWPN和主机HBA的WWPN是一致的,因此拿交换机输出反推主机哪个端口,是最可靠的办法,不需要依赖Windows侧任何厂商工具。
3.4 Windows磁盘的序列号与WWN的差别
在Windows上还经常遇到一个困扰:SerialNumber字段到底是不是WWN?答案要看情况。FC存储映射出来的磁盘,其SerialNumber字段常常会显示为SCSI标准里的序列号,它和WWN不是一个编号体系,不能直接拿去存储侧比对。真正能跟存储侧对应的是UniqueId字段或者设备的SCSI标识。假如Get-Disk的UniqueId是类似“5000c500abcdef01”或者“0x5000c500abcdef01”这种,这就是WWN;如果是“44 2d 55 4e 49 58...”这种带空格的十六进制,多半是磁盘签名,这时需要靠mpclaim或存储侧管理工具去获取底层WWN。
顺手提一个实用招:Windows上下发了新盘后,在事件查看器的存储诊断日志里,同样记录着LUN的WWN和盘号信息,通过Event ID相关事件可以快速定位新盘对应盘符,用不着一次一次重启。
4. 实战场景:WWN在存储映射与故障排查里到底怎么用
4.1 场景一:存储侧分配了LUN,主机上对不上号
假设某存储阵列的管理界面上给一台FC直连主机映射了一个LUN,存储侧显示的WWN是5000c500abcdef01,容量200GB。主机上执行fdisk -l发现新出现一个201GB的盘sde,但不确定是不是那一个,因为同一台机器还连着好几块类似大小的旧LUN。
这时先在主机上读取sde的WWN:
cat /sys/block/sde/device/wwid如果输出是naa.5000c500abcdef01,跟存储侧完全对应,那就是这盘了。如果输出完全对不上,基本可以断定映射被配置错误——可能zone没做好、LUN masking没生效,或者主机识别到了旧缓存路径。继续排查,先去确认HBA端口能否看到存储端口:
ls /sys/class/fc_remote_ports/ cat /sys/class/fc_remote_ports/rport-3:0-*/port_name再比对存储侧自己报告的控制器端口WWPN,就能判断zone对不对。很多时候LUN在主机上“消失”或不识别,不是存储没映射,而是zone白名单里没加主机HBA的新WWPN。
4.2 场景二:坏盘定位,WWN成了唯一线索
公司一台老的JBOD盘柜报警,指示灯提示有盘故障。盘柜挂在Linux服务器上,盘柜后面十几块硬盘做成了好几个RAID组并用软raid或存储卷管理。系统日志中出现:
sd 3:0:1:0: [sdd] Unhandled error code但消息里没有明确的物理槽位,系统也不一定能感知盘柜哪块Led亮。此时用WWN交叉锁定盘符和盘柜槽位:
sg_inquiry -p 0x83 /dev/sdd拿到WWN后,登录盘柜管理界面去“Disk Information”里检索这个WWN,基本能定位到物理槽位。如果盘柜管理界面没有WWN列,用序列号turn也能查,但很多柜子就是按WWN/ID编号管理的。这让我养成一个习惯:每次新装一台带盘柜的服务器,先把所有盘WWN和盘符槽位的对应关系导出存成表格,等出事时直接翻存档,能省半小时。
4.3 多路径环境里的注意事项:别拿sd设备干正事
Linux下做FC多路径时,最好别直接用/dev/sdX来操作文件系统、分区,因为一个LUN上有两个sd设备(sdb和sdc),操作sdb和操作sdc其实是同一块底层盘的同一个分区。如果跨越设备写数据,极容易产生文件系统错乱。正确姿势是让multipath接管:
multipath -ll输出中每一行都带有WWN:
mpatha (5000c500abcdef01) dm-2 SANBLU, ,LUN注意这里的括号里的WWN就是底层LUN的WWN,和存储侧看到的一致。multipath接管后,系统会生成/dev/mapper/mpatha之类的设备,日常格式化、挂载全部用它。查看这个设备的WWN同样可以用:
multipathd show maps或:
dmsetup ls --tree如果你在已经有多路径的环境里执行fdisk -l,会看到同容量的设备重复出现,别急着格式化任何/dev/sdX,先确认这俩sd设备是不是同一块的轮子。
5. 常见问题速查与避坑技巧
5.1 找不到wwn-0x链接文件,怎么处理
这种情况在SCSI直连盘上很少见,但在虚拟化平台或某些老内核上经常出现。常见原因有三类:第一,磁盘设备本身不支持SCSI VPD页0x83,所以内核无法生成WWID;第二,内核模块参数中关闭了磁盘标识生成;第三,udev规则有问题,规则没匹配到。
排查时先确认sysfs里的wwid文件是否存在:
ls /sys/block/sdb/device/wwid如果存在但by-id里没有链接,说明udev规则有问题,可以手动触发:
udevadm trigger --subsystem-match=block再不行直接看设备ID属性:
udevadm info --query=all --name=/dev/sdb | grep -i wwid至于虚拟机里virtio等半虚拟化磁盘,本来就不是真正的SCSI设备,没有WWN属于正常现象,这种情况用UUID或盘箱序列号去标识更靠谱。
5.2 Windows下UniqueId和WWN对不上的情况
上面提过Get-Disk的UniqueId在不同设备上含义不同。还有一种坑是,在高版本Windows的多路径环境里,Get-Disk输出的是一个带“path”开头的路径标识,而不是WWN。此时建议改用mpclaim -s -d或存储管理工具获取完整WWN。真实踩坑过程:某台Windows Server 2016上Get-Disk显示UniqueId是“path1”,而存储侧只认5000开头的WWN,折腾了半天,最后在MPIO配置界面看到了完整标识。
5.3 别把WWN和NQN、EU-64搞混
NVMe协议下,每个NVMe控制器有自己的NQN(NVMe Qualified Name),格式类似于nqn.2014-08.org.nvmexpress:xxxxxxxx,这是完全不同的体系。另外,FC下还有EU-64(IEEE Extended Unique Identifier)格式。遇到设备是NVMe盘或者NVMe-oF连接时,查WWN的方式要换成nvme命令,查看NQN或序列号,不能再套用SCSI那套。开头如果有人拿WWN让你去“查NVMe盘”,要先把协议层面理清楚,否则找半天都是空的。
另一个容易踩的坑是大小写和0x前缀。存储侧显示的WWN常常是小写不带0x,Linux sysfs里是naa.大写,scsi_id输出是不带0x的小写,三者表面看起来不一样,本质上同一串数字。比对前把格式统一,最稳妥的做法是全部转成小写再去掉“0x”、“naa.”这类前缀再比。
6. 把查WWN这件事做成习惯,效率能提升一大截
对我来说,查WWN最核心的心得就是:所有设备标识工具无非两个字,“稳定”。盘符会漂,路径会变,WWN从设备出厂那一刻起基本不变。所以养成两个习惯长期受益:一是服务器上线时把磁盘WWN和盘符映射固化记录,哪怕当时只是做个表格;二是所有脚本和自动化配置,能用WWN标识设备就绝不用sd盘符,避免设备顺序一乱全盘崩盘。
日常排查中,我常把这些命令浓缩成几个别名或小脚本。比如Linux下做一个bash函数:
wwn() { lsblk -o NAME,WWN,SIZE,MODEL "$@" 2>/dev/null || cat /sys/block/$1/device/wwid; }Windows下存一个PowerShell函数:
function Get-WWN { param($DiskNumber); (Get-Disk -Number $DiskNumber).UniqueId }当存储团队甩过来一条WWN字符串问“这盘在哪个主机上”时,用脚本批量在各服务器跑一遍,几十台机器三分钟就能扫完成个结果。这种时候,你就知道花时间把WWN这些知识彻底理清,比临时翻手册值太多了。