博科Fabric OS存储交换机:zone配置、级联与巡检实战
简介:面向数据中心光纤存储网络运维人员与初入SAN领域的工程师,这份博科(Brocade Fabric)交换机培训文档与操作手册以25页PDF形式梳理日常运维所需的核心知识。内容从FC交换机与以太网、FC协议与TCP/IP的差异讲起,延伸到常见接口类型、交换机基础配置、Zone与VSAN等通道业务配置,并配有案例演示和FAQ巡检、日志收集思路,便于按章节查漏补缺。资源包共1个PDF文件,约3.28MB,结构紧凑,适合打印成册或随查随用。已有1898人学习,说明其在存储交换机入门与运维场景中具有一定参考价值。读者可据此掌握登录改密、管理地址与NTP设置、端口启停、switchname修改、Zone创建激活、VSAN与Port Channel配置等操作要点,也能借助巡检命令和排障日志方法提升日常维护与故障定位效率。
1. 一份 25 页的设备交接文档,为什么值得反复翻。
机房搬迁前夜,一台博科存储交换机要新增两个 zone,还要跟另一台做级联。带你的老工程师已经离职,留下的就是一份 25 页的培训文档加操作手册。它把博科交换机 OS 的功能模块、基础管理命令、光纤通道业务配置、级联案例和巡检命令按操作顺序串了起来,从串口登录一直讲到fcping和checkrclink带宽验证。它解决的不是“学会 FC 原理”,而是“明天要动手,今晚知道每条命令敲下去会发生什么”。适合两类人:刚接手存储交换机的运维,和需要给 FC 网络做 zone 变更、级联扩容的老手。第 1 章不讲命令,先把 FC 跟以太网的分工差异讲清楚,因为后面每一个参数都跟这个差异有关。
2. 协议栈分工决定参数:FC 为什么要把 buffer 当成一等公民
2.1 HBA 和交换机 ASIC 承担了底层四层,主机只看到上层数据
FC 协议栈从下往上分五层:FC-0 管物理介质、接口和速率,FC-1 管编码解码,FC-2 管帧、序列和交换,FC-3 是公共服务,FC-4 做上层协议映射(最典型的是 FCP 承载 SCSI,新一点的是 FC-NVMe)。关键在于 FC-0 到 FC-3 这四层的处理不在主机内核里,而是在 HBA 卡和交换机 ASIC 的固件里完成,送到主机内存里的数据已经是干干净净的上层数据。
TCP/IP 走的是另一条路。以太网卡把收到的每一帧都送到主机内核协议栈,IP 层做地址判断,TCP 层做数据段定界、校验、排序、重传和拼接,每一步都要占主机 CPU,还要经历多次内存拷贝。所以在大块顺序读写这种场景下,FC 的 CPU 占用和时延都明显低。
这个差异直接决定了两个配置习惯。第一,FC 链路靠信用机制(BB credit)做流控,发送方必须先拿到接收方的 buffer 额度才发帧,链路不丢包、不重传,所以“buffer 够不够”比“带宽够不够”更容易成为瓶颈。第二,链路距离一长,在途帧数量变大,需要更多 credit 才能把管道填满,这就是级联时要配portcfglongdistance和看portbuffershow的原因,而不是简单调个速率了事。
提示:不要在 FC 环境里套用以太网那套“先扩容带宽”的思路。带宽足够但 credit 不足时,
portperfshow显示的吞吐量会稳定在某个上不去的值,看起来很像链路有问题,实际上参数没给够。
2.2 七类服务模块,各自对应一组命令
文档把 Fabric OS 的服务拆成登录服务、目录服务、光纤控制器服务、时间服务、管理服务、别名服务、广播服务。这套划分不算严格意义上的模块架构,但它是一张很好用的“命令索引表”:遇到问题时先判断是哪类服务在起作用,再去查对应命令,比漫无目的翻手册快得多。
| 服务模块 | 作用 | 常用命令 |
|---|---|---|
| 登录服务 | 与其它交换机节点或服务交换数据 | fabricshow、islshow |
| 目录服务(名称服务器) | 节点注册、查询、发现其它设备 | nsshow、nsallshow、nscamshow |
| 光纤控制器服务 | 节点状态变更通知 | fabricshow、日志检查 |
| 时间服务 | 保持全网时间同步,日志可对齐 | date、tsclockserver |
| 管理服务 | 唯一可直接配置的服务,管基础配置和通道业务 | ipaddrset、switchname、cfgcreate等 |
| 别名服务 | 节点名称注册与分组 | alicreate、alishow、aliadd |
| 广播服务 | 发到广播地址的帧向全域扩散 | 一般只做诊断,不主动配 |
实际排障时的顺序通常是:先看清楚“谁在 fabric 里”(目录服务),再看“链路通不通”(登录服务),最后才动“配置对不对”(管理服务)。反过来做,很容易在错误的层面上折腾半天。
2.3 U_Port 变成 F_Port 还是 E_Port,决定了这条链路能承载什么
光纤交换机上电后端口默认是 U_Port,谁先连上来、对端是什么角色,它自动协商成对应类型。接主机 HBA 或存储阵列端口,协商成 F_Port;接另一台交换机做级联,协商成 E_Port;接交换机但级联没成功,就会停在 G_Port。switchshow输出里每个端口那一列的状态,就是判断当前处于哪种角色最直接的依据。
接口形态上,常见的是 SFP+ 光口(8G/16G/32G FC)、QSFP+ 口(用于更高密度或 128G 链路),以及少量铜缆接口用于管理网或短距互联。选型上我一般按三条原则走:跨机柜或跨楼层一律光纤,同一机柜内 3 米以内可以上铜缆降成本;光模块的速率和距离等级必须成对匹配,短距模块(SR)不要硬拉长距离;两端模块厂商和型号尽量统一,混插是后面porterrshow里出现各种奇怪计数的常见来源。
端口角色不对时,先别怀疑模块。级联场景下如果switchshow一直显示 G_Port,八成是 domain ID 冲突或授权缺失,这两条在避坑章里会展开。
2.4 上线前摸清硬件:三条只读命令
在动任何配置之前,先把这台设备的型号、端口布局、模块在位情况和 Fabric 归属看清楚。这三条命令都是只读的,生产时间跑也安全。
# 1) 整机与端口总览:型号、domain、当前 zone 是否生效、每个端口的状态与角色 switchshow # 2) Fabric 成员:有几台交换机、谁是主、各自的 IP 和 WWN fabricshow # 3) 指定端口的光模块信息:类型、速率、厂商、收发光功率 sfpshow 0 sfpshow 24switchshow输出里有几个字段要盯住:switchName是设备名,switchDomain是域 ID(级联冲突就看它),zoning显示 ON 表示 zone 服务已启用,端口部分的state列给出Online、No_Module、No_Light、In_Sync、Online等状态,comment列会带上F-Port或E-Port以及对端 WWN。fabricshow里主交换机前面会有>标记,级联成功的两台设备必须出现在同一份输出里,否则就是 fabric 没合并。
sfpshow的参数是端口号,不是 area 号,写错了会提示端口不存在。输出里的Media、Connector、Transceiver三行确认模块类型是否和预期一致,后面的Rx Power、Tx Power就是光功率读数,单位是 uW 和 dBm 双显示,下一章讲阈值时再细说。
3. 基础管理配置:九条命令把裸设备变成可运维状态
3.1 三条接入路径与各自的默认参数
新设备拆箱后第一件事是连上去。文档给了三条路径:串口、管理口 SSH、Web。串口是最保底的,波特率 9600、8 位数据位、无校验、1 位停止位、无流控,用 RJ45 转 USB 或 Mini-USB 线接到笔记本,终端软件里选对串口号即可。这条路径不依赖网络,设备 IP 配错了也能救回来,所以我一般建议现场施工时先确认串口能通,再去配管理网。
管理口有出厂默认地址 10.77.77.77,默认账号admin、默认密码password。这个默认值是全网皆知的,设备一上线必须改掉。SSH 登录用ssh admin@10.77.77.77,前提是笔记本网口配一个同网段地址(比如 10.77.77.100/24)。
Web 方式用https://<管理IP>访问,但要注意 Java 依赖:文档里提到某型号需要 Java 7、另一型号需要 Java 8。这条是血泪经验——浏览器升级后 Java 插件被禁,Web 界面直接白屏,很多现场以为是设备故障,其实是本地环境问题。能用 SSH 就别用 Web,脚本化和批量操作都方便得多。
3.2 账号、管理地址:这两条命令改完立即生效
passwd不带参数改当前登录用户的密码,带用户名改指定用户,交互式输入两遍新密码。ipaddrset是交互式命令,逐项询问以太网 IP、子网掩码、网关、带内 IP,注意它是即刻生效的,回车确认后当前 SSH 会话立刻断开,必须用新地址重连。
# 改当前用户密码 passwd # 改指定用户密码(需要 admin 权限) passwd admin # 新增一个只读运维账号,角色为 user userconfig --add ops01 -r user -p 'Init#2024' # 改管理地址:交互式,改完立即生效,SSH 会掉线 ipaddrsetuserconfig的-r参数决定权限:admin可以做全部配置变更,user只能做有限操作和查询,operator权限更低。生产上给巡检脚本单独开一个user角色账号,比共用 admin 账号好排查——clihistory里能看出是谁在什么时候敲了什么。
ipaddrset执行前先确认笔记本已经配好新网段的地址,否则改完就连不上,只能回到串口。这个“后悔药”成本很高,尤其在远程操作时。
3.3 会话超时、NTP 与设备名
会话超时用timeout <分钟数>,值为 0 表示永不超时。生产环境不建议设 0,运维终端开着去开会,回来发现会话还挂着,别人顺手敲一条命令就可能出事。我一般设 10 到 15 分钟。
时间同步是tsclockserver "<NTP服务器IP>",注意 IP 要加引号。时间不同步带来的问题很隐蔽:两台交换机的日志时间差几分钟,级联故障时根本没法按时间线对齐事件,追起来像在黑匣子里找线索。配置完用date确认当前时间,再用tsclockserver不带参数查当前设置的服务器。
设备名用switchname <新名字>。命名规范建议带上机房、楼层、角色和序号,比如DC1-A-SW01,因为fabricshow输出里只显示这个名称,级联后一眼能看出谁是谁。
# 会话超时 15 分钟 timeout 15 # 配置 NTP 服务器(IP 必须加引号) tsclockserver "10.31.255.254" # 查看当前时间与 NTP 配置 date tsclockserver # 修改设备名 switchname DC1-A-SW013.4 禁用、启用与关机:顺序错了多停十分钟
switchdisable让整台交换机退出 fabric,所有端口停止转发,但设备本身还在运行,配置命令依然能敲。switchenable恢复。改 domain ID、改 fabric 参数这类操作必须先在 disable 状态下做,在线改会直接被拒绝。
端口级的portdisable <端口号>和portenable <端口号>影响面小得多,换模块、换线前先 disable 对应端口是基本动作。注意portdisable是临时状态,设备重启后端口可能自动恢复;如果希望重启后仍保持禁用,要配portcfgpersistentdisable,反过来用portcfgpersistentenable。
关机用sysshutdown,执行后会走正常的停机流程。直接拔电源的后果是配置文件可能没落盘,下次启动回到旧配置,这种翻车现场我见过不止一次。正确顺序是:确认业务已切走 →switchdisable→sysshutdown→ 等面板指示灯灭 → 断电源。
注意:
switchdisable会中断整台设备的转发,级联环境下对端交换机会收到 RSCN,主机侧多路径软件可能触发路径切换。做这类操作前先跟存储和主机侧确认窗口。
3.5 建立只读基线:一次跑完的查询组合
接手一台不熟悉的设备,我会先跑一组只读命令,把当前状态存成一份基线文本,后续任何变更都跟这份基线对比。文档里列出的查询命令正好够用。
# 管理层信息 ipaddrshow # 管理口地址 uptime # 运行时长,判断是否发生过意外重启 clihistory --show # 历史命令,看前任做过什么 # 硬件与 Fabric chassisshow # 主板、序列号、固件版本 fabricshow # Fabric 成员 switchshow # 端口总览 # 配置层 configshow # 系统参数 cfgactvshow # 当前生效的配置文件 zoneshow # 已定义和生效的 zone alishow # 别名与 WWN 对应 # 性能与健康 portcfgshow # 端口配置 porterrshow # 端口错误计数 fanshow # 风扇状态 memshow # 内存使用clihistory这条容易被忽略,但它能告诉你前任是不是刚改过什么还没生效的配置。uptime显示的运行时长如果比预期短,说明设备近期重启过,要顺着日志查原因。chassisshow里的固件版本一定要记录,不同版本的命令参数前缀有差异,后面配长距离参数时就可能踩到。
4. alias、zone、cfg 三层对象:把变更做成可回滚的四步链路
4.1 三层对象的关系与生效模型
FC 网络的访问控制不靠 IP,靠 WWN。三层对象从细到粗:alias 是给 WWN 起的名字,zone 是允许互访的成员集合,cfg(配置文件)是一组 zone 的集合,同一时刻只有一份 cfg 生效。主机要能看到存储,两个端口的 WWN 必须落在同一个生效 zone 里。
成员写法有三种:WWN(20:00:00:25:b5:00:00:1a)、别名(ESXi01_HBA1)、域端口对(1,3表示 domain 1 的端口 3)。第三种最脆弱,设备换板卡或端口位置一变就失效,我一般只在临时测试时用,生产一律用 alias 包 WWN。
生效模型要分清两层:cfgsave把内存里的定义写进 flash,这是“保存”;cfgenable让某份 cfg 真正生效,这是“启用”。只保存不启用,配置在zoneshow里能看到但主机不认;只启用不保存,设备重启后配置丢失。这两步都做了,才算变更完成。
4.2 建、加、存、生效:四步一个都不能省
标准流程是:建 alias → 建 zone → 建 cfg 并把 zone 加进去 → 保存并启用。下面这段可以直接照抄改参数。
# 第一步:建别名,把 WWN 换成看得懂的名字 alicreate "ESXi01_HBA1", "20:00:00:25:b5:00:00:1a" alicreate "STOR01_CTL0_P0", "50:00:d3:10:00:5e:00:01" # 第二步:建 zone,成员用分号隔开 zonecreate "zone_esxi01_stor01", "ESXi01_HBA1;STOR01_CTL0_P0" # 第三步:建配置文件并把 zone 加进去 cfgcreate "cfg_dc1_prod", "zone_esxi01_stor01" # 第四步:保存到 flash 并启用 cfgsave cfgenable "cfg_dc1_prod"alicreate和zonecreate的成员用分号分隔,一条命令可以带多个成员。cfgcreate的第二个参数可以给空,之后再cfgadd逐个添加,也可以一次给全。cfgsave提交当前事务,cfgenable的参数是cfg 的名字,不是 zone 的名字——文档里这一行写成了cfgEnable testzonename,容易让人误以为填 zone 名,实际填错会报找不到配置文件。
启用瞬间交换机会向所有登录节点发 RSCN,主机侧多路径软件会看到路径状态变化,可能出现短暂的 IO 抖动。生产变更安排在业务低峰,并且提前跟主机侧打招呼,这是我踩过的最贵的一课。
4.3 改名、替换、删成员:连带影响先想清楚
zoneobjectrename改的是对象名,可以改 zone、alias,也能改 cfg。改名之后必须重新cfgsave和cfgenable才生效。关键一点:改 alias 的名字,引用它的 zone 成员信息会跟着变,用的是 alias 名字而不是 WWN,所以 zone 不会失效——这条如果没想明白,很容易以为要重建所有 zone。
zoneobjectreplace做的是替换成员,典型场景是存储控制器换板卡,WWN 变了但逻辑位置不变。用替换而不是删了重建,可以保持 zone 里的成员顺序不变,少一次全量重建的风险。
# 改 zone 名 zoneobjectrename "zone_esxi01_stor01", "zone_esxi01_stor01_v2" # 把 old 成员整体替换成 new 成员 zoneobjectreplace "STOR01_CTL0_P0", "STOR01_CTL0_P0_NEW" # 增删成员 aliadd "ESXi01_HBA1", "20:00:00:25:b5:00:00:1b" zoneadd "zone_esxi01_stor01", "ESXi01_HBA2" aliremove "ESXi01_HBA1", "20:00:00:25:b5:00:00:1b" zoneremove "zone_esxi01_stor01", "ESXi01_HBA2" # 删除对象 alidelete "ESXi01_HBA1" zonedelete "zone_esxi01_stor01" cfgdelete "cfg_dc1_prod" # 任何变更之后 cfgsave cfgenable "cfg_dc1_prod"删除是全局的:zonedelete会把所有 cfg 里引用的这个 zone 一并删掉,而不只是当前生效的那份。多数时候一个 zone 只存在于一份 cfg 里,所以感觉不到,但如果你维护着“生产 cfg + 灾备 cfg”两套,删一个 zone 会同时从两套里消失。这个行为必须提前知道。
4.4 把表格里的 WWN 批量变成命令
真实场景很少只有一对端口。一张 Excel 表里几十行主机 HBA WWN 和存储端口 WWN,手敲必然出错。我的做法是先用脚本生成命令文本,人工检查一遍,再粘进交换机。
#!/bin/bash # hosts.csv 两列:alias_name,wwn while IFS=, read -r name wwn; do # 跳过表头和空行 [ -z "$name" ] && continue [ "$name" = "alias_name" ] && continue # 去掉 Windows 换行符和首尾空格 wwn=$(echo "$wwn" | tr -d '\r' | xargs) echo "alicreate \"$name\", \"$wwn\"" done < hosts.csv > ali_cmds.txtIFS=,把分隔符改成逗号,read -r防止反斜杠被转义,tr -d '\r'处理从 Windows 导出的 CSV 末尾回车,xargs顺手去掉前后空格。生成的ali_cmds.txt里每行一条alicreate,复制到交换机命令行执行即可。
zone 可以用同样的思路生成,但成员组合必须从业务关系表里来,不能让脚本自己配对——两个不该互通的 zone 一旦合并,主机可能看到不该看到的 LUN,这类事故排查起来极其费时。生成完先cat一遍看有没有异常的 WWN 格式(比如少一位或多一位),再执行。
5. 五个常见问题:现象、成因与处置顺序
5.1 zone 建完主机不认盘:defined 有、effective 没有
现象:zoneshow能看到新建的 zone,cfgactvshow里却没有它;主机侧重新扫描也看不到新 LUN。
原因通常有三个:只执行了cfgsave没执行cfgenable;cfgadd之后忘了保存,配置还在内存事务里;或者启用了另一份 cfg,新 zone 加进了没生效的那份。还有一种隐蔽情况,前一次操作中断留下了未提交事务,后续命令全部被挡住。
解决顺序:先cfgtransshow看有没有挂起的事务,有就cfgtransabort中止;再cfgshow对比 Defined 和 Effective 两段内容,确认目标 zone 在哪一份里;然后cfgsave;最后cfgenable "正确的cfg名";用cfgactvshow复核生效的 cfg 名。全部确认后,主机侧做一次 rescan,必要时重启多路径服务。
5.2 级联端口停在 G_Port:先查 domain ID 和授权
现象:两台交换机光纤接好,switchshow里端口状态是In_Sync或G_Port,fabricshow只显示自己一台,fabric 没合并。
最常见的原因是 domain ID 冲突:两台设备出厂都是 1,接上就打架。处理流程是switchdisable→configure→ 在Fabric parameters处回答y→ 输入唯一域 ID(1 到 239,避开已用值)→ 其余提示直接回车接受 →switchenable。改完switchshow里的switchDomain应该变成新值。
第二个原因是授权。两台交换机互联需要级联授权,超过 10 公里还需要远距离授权。licenseshow查看已安装的授权项,缺了就先补,再谈其它。第三个原因是速率和 FEC 不匹配:一端固定速率、一端自适应,或者一端开了 FEC 一端没开,链路会停在同步阶段。用portcfgfec --disable -FEC <端口>或--enable让两端一致,再观察状态。
成功后的标志很明确:端口状态变成E-Port,fabricshow输出里主交换机前有>,从属设备标注 upstream / downstream,islshow能看到级联链路明细。
5.3 porterrshow 一报错就换线:Enc_Out 和 Crc_Err 要分开看
现象:porterrshow里某端口有错误计数,第一反应是换整条光纤,换完还是涨。
Enc_Out是编码层的外部错误,单独出现、且增长缓慢时,多半是线缆或连接器端面污染、弯折过度。Crc_Err是帧校验错误,反映的是数据完整性。两个一起增长,更可能是光模块本身的光电转换出了问题。只涨Crc_Err而Enc_Out不动,链路误码的可能性更大,要顺着整条链路查,包括配线架上的法兰盘。
处置顺序我一般是:先sfpshow看收发光功率是否在范围内 → 清洁两端端面 → 换一段已知良好的跳线做交叉验证 → 换模块 → 最后才怀疑交换机端口。判断增速比看绝对值有用得多:portstatsclear <端口>清零后观察 10 分钟,涨几百和涨几万是两种性质的问题。
5.4 sfpshow 读数看不懂:uW 和 dBm 的换算与阈值
现象:sfpshow显示Rx Power是 200 uW,看着数字不小,实际链路余量已经不够了。
uW 是线性单位,dBm 是对数单位,两者换算关系是dBm = 10 × log10(uW / 1000)。文档给出的经验阈值是大于 398 uW 为正常,换算过来约等于 -4.0 dBm。几个常用点记住就够:
| 光功率 (uW) | 约合 (dBm) | 判断 |
|---|---|---|
| 1000 | 0 | 强,短距链路常见 |
| 398 | -4.0 | 文档给出的正常下限参考 |
| 100 | -10 | 偏低,长距链路可能正常 |
| 10 | -20 | 接近灵敏度极限,需核查 |
判读要成对看:本端Tx Power和对端Rx Power的差值就是这段光纤的插损,正常情况下几个 dB 以内。如果插损突然变大,先查跳线和法兰,别急着换模块。不同速率的模块灵敏度不同,16G 模块比 8G 模块对损耗更敏感,混插时更容易出问题。
5.5 抄来的命令报 Unknown Command:命令体系不是一套
现象:网上搜到set login user xxx password xxx、set ip interface ...这类写法,粘进博科交换机直接报未知命令。
原因是命令体系不同。set开头那一套属于另一派网络设备的配置风格,博科 Fabric OS 用的是自己的动词体系:改密码是passwd,改管理地址是ipaddrset,改设备名是switchname,改超时是timeout。看到“看起来很像但就是报错”的命令,先怀疑来源不对,而不是设备有问题。
稳妥做法是用设备自带的帮助确认:help列出顶层命令,commandhelp <命令>看具体参数格式。任何在生产设备上没敲过的命令,先在测试设备或者至少--help层面确认一遍,别拿生产当试验田。
6. 日常巡检与带宽验证:把感觉正常换成可对比的数字
巡检的价值在于“有基线可比”。我习惯按频次分三档,把switchshow、fabricshow、cfgactvshow、porterrshow、fanshow放在每日一档,sfpshow、portbuffershow、chassisshow放每周,supportshow这种重命令只在变更前后或排障时跑一次。supportshow输出极大,直接刷屏会卡住会话,用supportshow | more分页,或者配置好上传路径自动落到服务器上。
| 频次 | 命令 | 关注点 |
|---|---|---|
| 每日 | switchshow、fabricshow | 端口状态、Fabric 成员是否变化 |
| 每日 | porterrshow | 错误计数是否新增 |
| 每日 | cfgactvshow、fanshow、memshow | 生效配置、风扇、内存 |
| 每周 | sfpshow <端口>、portbuffershow | 光功率趋势、buffer 余量 |
| 变更前后 | supportshow、chassisshow | 全量快照,用于对比和取证 |
带宽验证别靠“感觉快”。fcping打目标 WWN,加--number参数跑多包,看丢包和往返时延;吞吐量用portperfshow <端口>直接读 MB/s。要做端到端压力测试,用checkrclink:一端起服务端,另一端起客户端跑固定时长。
# 链路连通性与时延 fcping --number 500 20:00:00:25:b5:00:00:1a # 端到端带宽测试:一端 server,一端 client,跑 60 秒 checkrclink --serverstart 2:4:1 checkrclink --startclient 3:4:1 fe80::2341:2:ac02:6523 60 # 实时吞吐 portperfshow 2checkrclink的参数前缀在不同固件版本上不一样,老版本是checkrclink serverstart <端口>,新版本是带--的写法,跑之前用checkrclink --help对一下。端口参数按domain:area:port或简化的端口号填,客户端那串地址是对端端口的标识,照着服务端回显抄就行。
从那以后我每次做 zone 变更,都强制走一遍「cfgtransshow确认无挂起事务 →cfgsave→cfgenable→cfgactvshow复核」这四步,级联前必查 domain ID 和授权,换模块前必看两端sfpshow读数。这几条写在便签上贴显示器边框,比记在脑子里靠谱。这份文档我按操作顺序整理过一遍,配合自己设备的实际回显对照着看,落地会快很多。希望帮到你。
本文还有配套的精品资源,点击获取