随笔 - 《我始终是我》

《我始终是我》


上一篇文章里,我讲了一套很冷的东西。重量、杠杆、交易、破圈——听起来像一台精密运转的机器。有人可能会觉得,这个人是不是太理性了,是不是把一切都算得太清楚了,是不是已经把自己活成了一个算法。

不是。

所以这篇文章,我想讲讲框架之下的那个人。


我确实热衷于拆解世界。GPU 集群怎么互联、IPO 招股书里的商业模式怎么运转、社会资源怎么流动、人脉的本质是什么——我看到任何复杂的东西,第一反应都是:它的底层逻辑是什么?它为什么会是这个样子?既然它是人制造出来的,那我就应该能理解它。

这是我的乐趣所在。我不满足于”它很厉害”这种模糊的评价,我要知道它厉害在哪,为什么能成立,以及这个逻辑能不能被我用在自己身上。

但这种拆解世界的冲动,并没有把我变成一个冷血的人。

我会在网络上刷到一个陌生人受苦的视频,沉默很久。我会因为路边一朵桂花被雨打落满地,站在那儿看半天,然后写”百年古树千年朽木,十里繁荣万里荒芜”。我会在看到国际新闻里某些无力改变的事情时,心里堵着,说不出来。

我没有关掉我的感性。我只是给它画了一条边界。


这条边界是:我的情绪和共情能力,只分配给那些我力所能及的事情。

听起来像一种冷漠。但恰恰相反——这是一种保护。如果我每天对世界上的每一件苦难都倾注全部情感,我会被压垮。不是因为我不行,是因为任何人都不行。人类的共情能力是一种有限资源,像体力一样,会耗尽。心理学管这个叫”同情疲劳”——长期沉浸在无法改变的苦难中,人会从共情变为麻木。

我不允许自己麻木。所以我做了选择:我能帮的,我尽全力;我帮不了的,我承认,然后暂时放下。

这不是”不在乎”。这是先让自己足够强,再回来面对那些我现在还扛不动的东西。


很多人以为,像我这样一天到晚想着”重量””杠杆””涟漪”的人,一定活得很紧绷、很累、很焦虑。

不是的。

我是一个会摆烂的人。我会刷一天抖音,打一整天游戏,什么都不想,什么都不做。但我不会因为摆烂而愧疚。因为我心里清楚:我远期的方向没有变,我今天躺平,不代表我迷失了。我只是在休息,不是在放弃。

这个区别很重要。

很多人摆烂之后会陷入自责——“我又浪费了一天””我怎么这么不自律””我是不是根本不够努力”。这种自责本质上是因为你没有一个锚。你不知道自己要去哪,所以每一分钟的偏离都会让你恐慌。但如果你有方向——一个真正想清楚了的、长期的方向——那短暂的偏离就不是迷失,是休整。

方向感比执行力更稳定。执行力会波动,方向不会。

这就是我这几年建立起来的松弛感。松弛不是因为不在乎,是因为我知道自己在哪条路上。走快走慢不是问题,只要方向对。


还有一个我想说的。

这套”重量-杠杆”的思维模型,只是我个人打磨出来的。但我不希望读者把它当成一个”人生公式”去套。因为没有一个模型能解释全部的人生。

纯粹理性的逻辑思维能分析商业,但它分析不了为什么一个母亲会在深夜给孩子掖被角。

纯粹理性的逻辑思维能拆解人脉的本质,但它拆解不了人为什么会在雨天的桂花树下站一整个黄昏。

纯粹理性的逻辑思维能用来优化我自己的成长路径,但当我的理性触达边界——碰到那些怎么想也想不通的东西——我会停下来。托靠于Allah。承认自己的有限。

这听起来矛盾:一个用逻辑拆解一切的人,同时也是一个信Allah的人。但在我看来,这两者恰恰构成一个完整的闭环:

穷尽理性,承认边界,交托信仰。

这不是分裂,这是自知。


这篇文章没有方法论,没有框架图,没有”第一步第二步第三步”。

它只是一份诚实的自述。

我是一个理性的人,但我没有抛弃感性。我是一个拆解系统的人,但我承认系统的边界。我会因为远方的苦难感到无力,但我选择聚焦于眼前能改变的事情。我会摆烂、会偷懒、会刷一天抖音什么都不做,但我清楚地知道我明天要去哪。

我的理想和道路,充满了冷静的解构和计算。但驱动这一切向前走的那个东西——不是理性。

是雨中的桂花。是陌生人的眼泪。是不愿意再做一个无能为力的旁观者的那种决心。

我自始至终都是我。

浮尘落尽后的清醒,没有让我冷漠。破局的物理学,没有让我变成机器。我依然会哭,会笑,会在某些瞬间停下来,认真地看着这个世界,然后对自己说——好的,继续走吧。


无论世界如何复杂,我始终是我。
无论世界如何苦难,我托靠真主。
即使世界终将毁灭,那便回归主。

随笔 - 《破局的物理学:重量、杠杆与涟漪》

《破局的物理学:重量、杠杆与涟漪》


成年人的世界里,一切关系本质上都是交易。

这话不好听。但它让我站起来了。


很长一段时间我活在一种撕裂里。一边是浮尘落尽后的清醒——知道那些百年基业、名门望族,拉长到千年尺度不过朽木一堆;一边是眼睁睁看着别人在往上走,自己却连”破圈”的踏板都摸不到。

我试过焦虑,没用。我试过混圈子,更没用。没有东西能给别人的人,站在谁身边都是空气。

后来我停止向外找答案,开始向内搭模型。我反复问自己一个问题:我能提供什么?不能提供任何东西的人,凭什么让别人把资源给你?

答案在物理里。


重量

重量是你的硬通货。你的技能、你的成果、你用时间验证过的不可替代性。

这玩意骗不了人。你有没有重量,上手一试就知道。你可以吹一万个字,但一个项目砸下来,重量为零的人瞬间透明。

怎么积累重量?四个字:努力、沉淀、勤奋、不急躁。

这四个字单独看像鸡汤,但真正做过事的人知道它的真正含义——把眼前每一件小事做到超出预期。不是为老板,不是为领导,是为自己。因为每一件被做到极致的事,都会变成你的履历上一条无法被抹去的刻度。重量是堆出来的。跳槽堆不出来,混日子堆不出来。

没有重量的人,所有的”向上社交”都是自己骗自己。


杠杆

有重量,你能站在地上。但同等重量的两个人,撬动的世界可以天差地别。差在哪?

杠杆。

杠杆是你的认知、你的思维框架、你的信息差。

大多数人对认知提升的理解还停留在”多读书”。这太浅了。认知提升不是你读了多少本,而是你能不能看到别人看不到的底层结构。

拉长杠杆的方式除了读人物传记外,还可以读 IPO 招股书。

传记不是看故事,是看高手在命运交叉口的决策逻辑。那些瞬间里藏着一个人全部的认知框架,你可以直接拿过来装进自己的系统。

IPO 招股书是商业世界里最没水分的认知提纯。一份材料翻开,这家公司怎么赚钱、行业的底线在哪、市场如何运转,全在纸上。别人真金白银验证过的商业真相,你花几个小时就能看完。绝大多数人一辈子不会翻开一份招股书。你翻了,你的杠杆就比他们长了一截。


破圈

重量有了,杠杆有了,你就可以谈”人脉”了。

但人脉这个词已经被用烂了。太多人把它想象成”关系彩票”——偶遇一位大佬,对方一眼看中你的才华,从此平步青云。这不是人脉,这是幻想。

人脉不在圈子里,在你身边。

家庭资源好的人,家人朋友就是人脉。学历背景强的人,老师同学就是资源。如果你和我一样,什么都没有——你的直属领导、你的老板,就是你天然的人脉。 他们已经用结果证明了自己的成功,你要做的不是满世界找伯乐,而是成为他们手里最锋利的兵。

但这里有一个致命的顺序问题:不是先有人脉,再有能力。是先有能力,才有人脉。你不要去”找”人脉,你要让自己成为别人想资源的那个人。当你的重量足够沉、你的杠杆足够长,人脉会自己来找你。

而当你站到他们面前的时候,记住一件事:你不是去乞讨的。

你是去提供交易的选项。告诉对方”我能给你什么”,而不是”我需要你什么”。这是尊严。这是你多年努力堆出来的重量,赋予你的资格。


方向

重量和杠杆回答了”怎么走”。但它回答不了”往哪走”。

这是我自己花了最长时间才想明白的问题。我建了这个模型,把刀磨得锋利,把认知拉得深远,积累出了足够沉甸甸的重量——但然后呢?我撬动世界以后,往什么方向撬?

我给出的答案是这样的。

2020 年的一个雨天,我下班途中看着桂花被雨打落满地,写下了”百年古树千年朽木,十里繁荣万里荒芜”。那时候我以为自己看透了——繁荣是假的,基业是虚的,一切都是浮尘。但那个视角漏掉了一个关键问题:如果我对这个世界的态度仅仅停留在”看透”,那我就只是一个清醒的旁观者。清醒地看着世界塌陷,什么都不做——这恰恰是另一种形式的麻木。

我不愿意做旁观者。

所以我又写了 2025 年的那篇——《存在的痕迹,不在于石碑,而于涟漪》。石碑再好,终将风化。但你作为一颗石子砸向水面时激起的涟漪——你改变过的人、你传递出去的力量、你在这个世界上砸出来的动静——会一层一层扩散,永远荡漾下去。

这,大概就是方向。

我不是为了革命,不是为了改变全世界。但如果前行路上,我足够强大了,能顺手拉起身边跌倒的一个人——那我活过。如果涟漪够远,能传递到我看不见的地方——那我没白活。


浮尘落尽之后,石碑终成朽木,而涟漪不息……

随笔 - 《存在的痕迹:不在于石碑,而于涟漪》

观此视频有感

人为什么有虚岁 因为妈妈比其他人 单独的拥有了你一年

《存在的痕迹:不在于石碑,而于涟漪》

小时候我就在想——
人生的价值是什么?
是钱吗?是权吗?是骄奢淫逸吗?

那些生不带来、死不带去的东西罢了。

人生没多长,
人生不应该只是一场体验,
人生应该留下些什么,
人生应该有价值。

钱、权,这些终将在你死去的那一刻消散。
或许你为家人带来了财富,让他们享了福,
我不能说这没有价值,
但这还不够,远远不够。
五十年、百年之后,他们也会逝去,
你的存在,也将被慢慢淡忘。

如果这世间没有了你存在的痕迹,
那么,你在这个世界上真的活过吗?

年幼的我,怀揣着科研的梦想,
认为知识是宝贵的财富。
我曾以为,一切都是虚妄,
唯有将知识——这人类的瑰宝——传承下去,
让若干年、数十年之后,
还有人使用这些知识,
那便是人生价值的体现。

后来,时间冲刷着一切。
麻木、迷茫,混杂着泥沙一团糟的日子,
似乎,好像也就这样活一辈子了。

苦难是什么?
是肉体上的饥寒交迫吗?
确实,那也是苦难。
可最痛苦的折磨是什么呢?
是当我遇见像那个视频里一样的事情时,
什么都做不了——
没有能力伸出援手,
没有能力改变任何,
只能眼睁睁地看着一切发生。
那种精神上的撕裂与无力,
不就是最大的苦难吗?

我年幼时满怀希望,
以科研去证明人生价值。
后来才发现,这并不如我想象中那般简单。
那是一个遥远的理想。
不过,无需气馁,也无需放弃。
在前行的路上,
若能拉起身边跌倒的人,
那亦是值得的。

无论如何,
我不喜欢这种苦难。
我不喜欢清醒地看着一切坍塌,
连逃避都成了奢望。

也许,这就是活着的意义吧——
即使努力是一种痛苦,
那就让更大的痛苦逼着自己前进。
比苦难甜,就行了。

勿要,力不能挽流年,唯有目送山河倾——追悔莫及

The Traces of Existence: Not in Stone Monuments, But in Ripples

When I was young, I often wondered—
What is the value of life?
Is it money? Power? Debauchery?
But these are merely things we cannot bring with us at birth, nor take with us in death.

Life is not long.
Life should not be just an experience.
Life ought to leave something behind,
Life ought to have value.

Money, power—these will vanish the moment you die.
Perhaps you have brought wealth to your family, granted them comfort.
I cannot say this holds no value,
But it is not enough, far from enough.
Fifty years, a century later, they too will pass away,
And your existence will slowly fade from memory.

If no trace of you remains in this world,
Then, have you truly lived at all?

As a child, I cherished dreams of scientific research,
Believing knowledge to be a precious treasure.
I once thought that all else was illusion,
That only knowledge—this gem of humanity—passed down through generations,
So that years, decades later,
People would still make use of this knowledge—
That would be the manifestation of life’s value.

But as time washed over everything,
Numbness, confusion, and days muddled with chaos
Made it seem as if living out a lifetime this way was just how things were.

What is suffering?
Is it the pangs of hunger and cold?
Yes, that too is suffering.
But what is the most agonizing torment?
It is when I encounter situations like the one in that video,
And can do nothing—
Unable to reach out and help,
Unable to change anything,
Only able to watch it all unfold before my eyes.
That spiritual tearing and powerlessness—
Is that not the greatest suffering of all?

In my youth, I was full of hope,
Determined to prove life’s value through scientific research.
Only later did I realize it was not as simple as I had imagined.
It was a distant ideal.
Yet, there is no need for despair, no need to give up.
On the path forward,
If we can lift up those who have fallen beside us,
That too is meaningful.

No matter what,
I do not like this kind of suffering.
I do not like watching everything collapse with clear eyes,
Where even escape becomes a luxury.

Perhaps this is the meaning of living—
Even if effort is a form of pain,
Let a greater pain compel you to move forward.
As long as it is sweeter than the suffering, it is enough.

Do not let it be
That you lack the strength to hold back the flowing years, and can only watch the mountains and rivers fall—
Left with nothing but regret.

​اللّٰهُ أَكْبَرُ

IT场景专业术语表

用于各IT场景的专业术语的中英文对照

工单场景

英文 英文全称 中文 释义
TC Ticket Created 新建工单 工单已在系统中被成功创建,并进入待处理队列
PR Pending Report 等待报告 工单处理因等待(用户、第三方或系统提供的)额外信息、日志或报告而暂时挂起
SM Self-Maintenance 自行维护 问题由用户自行解决或无需运维团队介入(如过保服务器),随后工单可被关闭
R Resolved 已解决 问题已被运维团队成功修复,该工单处理完毕
IW In Warranty 在保内 表示设备或服务处于保修期内,维修通常由供应商免费提供
OOW Out of Warranty 已过保 表示设备或服务已超出保修期,维修通常需要付费
TPM Third-Party Maintenance 第三方维保 表示设备由原厂之外的第三方服务商提供维护支持

日常运维场景

英文 英文全称 中文 释义
Ops Task Status Board Ops(Operations ) 运维任务状态看板 一个实时展示运维任务进度和状态的可视化看板

关于服务器硬盘故障但带外没有错误日志的排障与报修笔记

情况说明

收到系统发出IO占用率和IO延迟的告警,登录带外排查无任何错误日志,随后进入操作系统使用脚本批量排查smartctl日志,发现存在错误计数,因smartctl并非厂家带外的告警日志,所以特此向Inspur、H3C、Lenovo、DELL进行了咨询,其中提到了一些日志参数的告警,目前已收到H3C、Inspur的回复

厂商对日志中以下内容的告警表示认可并作为报修依据

硬盘类型 参数 翻译 说明 来源
SSD ID 5 Reallocated_Sector_Ct 重分配扇区计数 因坏块被重新分配的扇区数量,值越高健康状况越差 新华三
SSD ID 197 Current_Pending_Sector 当前待处理扇区计数 有潜在读写错误、待重新映射的扇区数量(>100更换) 浪潮/新华三
SSD ID 187 Reported_Uncorrect 已报告的不可纠正错误 硬盘向主机报告的读/写过程中发生的不可恢复错误次数(>10更换) 浪潮
HDD Total uncorrected errors 总无法纠正错误 所有无法纠正的读/写错误之和 浪潮/新华三
HDD Verify total uncorrected errors 校验无法纠正错误 硬盘控制器自检时无法通过ECC纠正的错误总数,高值表示可靠性下降 新华三
HDD Read total uncorrected errors 读无法纠正错误 读取/写入IO时无法通过ECC纠正的错误总数,高值表示可靠性下降 新华三
HDD Elements in grown defect list 已增长缺陷列表中的元素 硬盘运行中登记的坏块数量,用于追踪坏块增长 @Icenowy于清华TUNA协会技术群组内回复

以下是辅助日志,作为协助排障参考,不作为直接依据

硬盘类型 参数 翻译 说明 来源
SSD Reallocated Sector Count 重分配扇区计数 记录因物理损坏被替换到备用扇区的次数,数值增加说明介质退化(>500为不可靠) 浪潮
SSD CRC Error Count CRC 错误计数 记录主机与硬盘之间传输数据时发生的 CRC 校验错误次数,常见原因包括数据线接触不良、电磁干扰或接口问题,单盘较多则可能为该盘本体故障,多个硬盘则进一步筛查是否位于同一个硬盘背板或同一个SAS端口 浪潮
HDD Non-medium error count 非介质故障 与上方SSD的是一样的意思 浪潮

清华大学TUNA协会技术群组

感谢@Icenowy清华TUNA协会技术群组内回复提出参考Elements in grown defect list参数的值,该值是HDD独有的指标,记录的是在使用过长中新发现的物理坏块数,数值持续增长则意味着该硬盘可靠性正在下降

排查过程

对于JBOD模式的硬盘

1
2
3
4
5
6
7
8
9
10
11
# 使用smartctl直接查询即可
smartctl -a /dev/sdX

# 可以增加grep快速筛选想要查询的参数,在替换双引号中的即可
smartctl -a /dev/sdX | grep -E "Elements in grown defect list"

# 配合for迅速遍历磁盘,{a..z}则是遍历sda到sdz的所有盘
# 如果盘很多那可以直接写为{a..zz},则是遍历sda到sdzz共702个盘
# [ -b "/dev/sd$i" ] test命令的简写,判断该设备是不是一个硬盘
# echo "sd$i"是在输出日志前输出盘号,避免不知道是哪个盘的报错
for i in {a..z}; do [ -b "/dev/sd$i" ] && echo "sd$i:" && sudo smartctl -a "/dev/sd$i" | grep "Elements in grown defect list"; done

对于LSI MegaRAID控制器,RAID模式的硬盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 由于硬盘由阵列卡接管,所以需要调用MegaRAID驱动程序才可访问
# /dev/sdX输入你挂载到系统的阵列,例如通常/dev/sda是RAID1系统盘
# 其中megaraid,后面的数字对应该硬盘是该阵列中的第几个盘,从编号0开始是第一个
smartctl -a -d megaraid,0 /dev/sdX

# 同样的grep筛选
smartctl -a -d megaraid,0 /dev/sdX | grep -E "Non-medium error count"

# 遍历快速排查所有盘
for raid in {a..z};do [ -b "/dev/sd$raid" ] && for disk in {0..20};do echo -e "\033[36;1m阵列 sd$raid 中硬盘 $disk 日志: " && smartctl -a -d megaraid,$disk /dev/sd$raid | grep -E "Non-medium error count";done;done

# 上方命令为单行,方便复制粘贴执行,以下是拆解后可读的版本
for raid in {a..z}; do # 遍历sda到sdz的设备
[ -b "/dev/sd$raid" ] && # 判断是不是硬盘,不是就跳过
for disk in {0..20}; do # 预设是0到20共21个硬盘,可以自行设置
echo -e "\033[36;1m阵列 sd$raid 中硬盘 $disk 日志: " # 打印个开头,不然不知道是哪个设备的日志
smartctl -a -d megaraid,$disk /dev/sd$raid | grep -E "Non-medium error count" # 根据你的需要调整grep筛选的内容
done
done

进阶脚本

该脚本会在当前目录输出smartctl的日志源码到disk_error_$(date +%Y%m%d_%H%M%S).log文件

推荐使用此单行模式,复制粘贴直接用,不需要创建shell文件

1
log_file="disk_error_$(date +%Y%m%d_%H%M%S).log"; for raid in {a..d}; do [ -b "/dev/sd$raid" ] && for disk in {0..23}; do smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1 && output=$(smartctl -a -d megaraid,$disk /dev/sd$raid) && serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}') && if echo "$output" | grep -q "SSD"; then reallocated_sectors=$(echo "$output" | grep "Reallocated_Sector_Ct" | awk '{print $10}'); reallocated_sectors=${reallocated_sectors:-0}; current_pending=$(echo "$output" | grep "Current_Pending_Sector" | awk '{print $10}'); current_pending=${current_pending:-0}; reported_uncorrect=$(echo "$output" | grep "Reported_Uncorrect" | awk '{print $10}'); reported_uncorrect=${reported_uncorrect:-0}; offline_uncorrect=$(echo "$output" | grep "Offline_Uncorrectable" | awk '{print $10}'); offline_uncorrect=${offline_uncorrect:-0}; crc_errors=$(echo "$output" | grep "CRC_Error_Count" | awk '{print $10}'); crc_errors=${crc_errors:-0}; [ "$reallocated_sectors" -gt 0 ] || [ "$current_pending" -gt 0 ] || [ "$reported_uncorrect" -gt 0 ] || [ "$offline_uncorrect" -gt 0 ] || [ "$crc_errors" -gt 0 ] && echo "$output" >> "$log_file" && echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n\033[36;1m05 重分配扇区计数(Reallocated Sector Count):\033[31;1m$reallocated_sectors\033[0m\n\033[36;1m197 当前待处理扇区(Current Pending Sector Count):\033[31;1m$current_pending\033[0m\n\033[36;1m已报告的不可纠正错误(Reported Uncorrectable Errors):\033[31;1m$reported_uncorrect\033[0m\n\033[36;1m离线不可纠正错误(Offline Uncorrectable):\033[31;1m$offline_uncorrect\033[0m\n\033[36;1m接口CRC错误计数(CRC Error Count):\033[31;1m$crc_errors\033[0m\n"; else read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}'); read_uncorrected=${read_uncorrected:-0}; verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}'); verify_uncorrected=${verify_uncorrected:-0}; total_uncorrected=$(echo "$output" | grep "Total uncorrected errors" | awk '{print $NF}'); total_uncorrected=${total_uncorrected:-0}; grown_defect_list=$(echo "$output" | grep "Elements in grown defect list" | awk '{print $NF}'); grown_defect_list=${grown_defect_list:-0}; non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}'); non_medium=${non_medium:-0}; [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$total_uncorrected" -gt 0 ] || [ "$grown_defect_list" -gt 0 ] || [ "$non_medium" -gt 0 ] && echo "$output" >> "$log_file" && echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n\033[36;1m读无法纠正错误(Read total uncorrected errors):\033[31;1m$read_uncorrected\033[0m\n\033[36;1m校验无法纠正错误(Verify total uncorrected errors):\033[31;1m$verify_uncorrected\033[0m\n\033[36;1m总无法纠正错误(Total uncorrected errors):\033[31;1m$total_uncorrected\033[0m\n\033[36;1m已增长缺陷列表元素(Elements in grown defect list):\033[31;1m$grown_defect_list\033[0m\n\033[36;1m非介质错误(Non-medium error count):\033[31;1m$non_medium\033[0m\n"; fi; done; done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/bin/bash

# 日志文件以日期时间命名
log_file="disk_error_$(date +%Y%m%d_%H%M%S).log"

# 遍历可能的RAID设备(sda, sdb, sdc, sdd)
for raid in {a..d}; do
if [ -b "/dev/sd$raid" ]; then
for disk in {0..23}; do
if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then
output=$(smartctl -a -d megaraid,$disk /dev/sd$raid)

serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}')

if echo "$output" | grep -q "SSD"; then
# ================= SSD =================
reallocated_sectors=$(echo "$output" | grep "Reallocated_Sector_Ct" | awk '{print $10}')
reallocated_sectors=${reallocated_sectors:-0}

current_pending=$(echo "$output" | grep "Current_Pending_Sector" | awk '{print $10}')
current_pending=${current_pending:-0}

reported_uncorrect=$(echo "$output" | grep "Reported_Uncorrect" | awk '{print $10}')
reported_uncorrect=${reported_uncorrect:-0}

offline_uncorrect=$(echo "$output" | grep "Offline_Uncorrectable" | awk '{print $10}')
offline_uncorrect=${offline_uncorrect:-0}

crc_errors=$(echo "$output" | grep "CRC_Error_Count" | awk '{print $10}')
crc_errors=${crc_errors:-0}

if [ "$reallocated_sectors" -gt 0 ] || [ "$current_pending" -gt 0 ] || \
[ "$reported_uncorrect" -gt 0 ] || [ "$offline_uncorrect" -gt 0 ] || [ "$crc_errors" -gt 0 ]; then
echo "$output" >> "$log_file"
echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n"
echo -e "\033[36;1m05 重分配扇区计数(Reallocated Sector Count):\033[31;1m$reallocated_sectors\033[0m"
echo -e "\033[36;1m197 当前待处理扇区(Current Pending Sector Count):\033[31;1m$current_pending\033[0m"
echo -e "\033[36;1m已报告的不可纠正错误(Reported Uncorrectable Errors):\033[31;1m$reported_uncorrect\033[0m"
echo -e "\033[36;1m离线不可纠正错误(Offline Uncorrectable):\033[31;1m$offline_uncorrect\033[0m"
echo -e "\033[36;1m接口CRC错误计数(CRC Error Count):\033[31;1m$crc_errors\033[0m\n"
fi
else
# ================= HDD =================
read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}')
read_uncorrected=${read_uncorrected:-0}

verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}')
verify_uncorrected=${verify_uncorrected:-0}

total_uncorrected=$(echo "$output" | grep "Total uncorrected errors" | awk '{print $NF}')
total_uncorrected=${total_uncorrected:-0}

grown_defect_list=$(echo "$output" | grep "Elements in grown defect list" | awk '{print $NF}')
grown_defect_list=${grown_defect_list:-0}

non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}')
non_medium=${non_medium:-0}

if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || \
[ "$total_uncorrected" -gt 0 ] || [ "$grown_defect_list" -gt 0 ] || [ "$non_medium" -gt 0 ]; then
echo "$output" >> "$log_file"
echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n"
echo -e "\033[36;1m读无法纠正错误(Read total uncorrected errors):\033[31;1m$read_uncorrected\033[0m"
echo -e "\033[36;1m校验无法纠正错误(Verify total uncorrected errors):\033[31;1m$verify_uncorrected\033[0m"
echo -e "\033[36;1m总无法纠正错误(Total uncorrected errors):\033[31;1m$total_uncorrected\033[0m"
echo -e "\033[36;1m已增长缺陷列表元素(Elements in grown defect list):\033[31;1m$grown_defect_list\033[0m"
echo -e "\033[36;1m非介质错误(Non-medium error count):\033[31;1m$non_medium\033[0m\n"
fi
fi
fi
done
fi
done

输出效果如下

20250918173418

关于DELL TSR日志(iDRAC)没有硬盘故障告警的报修办法

DELL通常只认可其自身硬件的告警日志。
在硬盘出现非致命故障,无法直观的在操作系统看到硬盘离线或RAID降级,同时TSR日志中没有记录到硬盘故障,iDRAC网页也没有显示硬盘故障时。
DELL通常不会认可运维工程师提供的smartctl日志和其他非DELL硬件报告的日志,
且有时smartctl也并不能很好的定位故障。

为此和DELL进行漫长的沟通后,最终定下来以下排障方式:

DELL承认的额外日志

  • 带外由故障日志时:提供TSR日志报修
  • 带外没有故障日志时:提供TSR日志+perccli64 /call show alilog的日志用于报修

此外还可通过分析上文提到的smartctl日志和以下日志用于综合定位问题:

1
2
3
ls -l /sys/class/block > /tmp/lsblock.txt
perccli64 /call show alilog > /tmp/target.txt
perccli64 /call/eall/sall show all > /tmp/slot.txt

以下是本次案例的记录,可以作为排障及报修的参考

情况说明:
本次是日常巡检时运维平台报障IO延迟大于100ms
随后排查了带外,没有告警,继续排查smartctl,定位slot8存在无法纠正的错误记录1次。
随后向DELL提出报修,并上传TSR日志,但因为没有记录告警,所以DELL并不认可,要求进一步调查故障。
排障过程中针对smartctl -a -d megaraid输出的Error counter log,也就是上文解释的smartctl日志;
其中有巨量的Errors Corrected by ECCfast纠正错误计数,达到了1737961798次,
针对该项报错,DELL不参考,并且未对此进行分析,所以只能自行分析。
结合硬盘运行时间约5.8年,且几乎从未停机;而这份报错是由RAID卡报告给smartctl,
所以在计数准确性上无法验证,同时鉴于运行了很长时间,计数的累计也是可能的因素;
此处有个疑点:该天文数字般的ECC纠错计数是否可能是整个RAID5阵列的纠错被记录到了其中?
再加上硬盘存在故障长期未发现,导致了频繁的纠错?
以上两个疑问仅为猜测,不过该ECC纠错确实会导致IO延迟增加。
在进一步的排查中发现slot9才是故障盘,且其中的Errors Corrected by ECCfast纠正为0,
反而是delayed纠正8396次,因此进一步核实这块盘才是真正的故障盘。
因为fast纠正是常规现象,delayed纠正才是有可能存在问题的,delayed纠正是无法快速纠错时进行的深度纠错

见此处说明

接下来讲如何通过分析perccli64 /call show alilog定位到了真正故障的硬盘
首先,perccli64,顾名思义,这是DELL PERC官方的工具,用于操作DELL RAID卡。
因为日志内容较多,所以选择使用perccli64 /call show alilog > /tmp/target.txt查询适配器日志并输出到文件。
随后使用vscode浏览发现,在35200行日志中,光是PD02和PD09的timeout就出现了11938行,
因此该日志足以说明slot2slot9这两个硬盘出现了故障,
并进一步结合smartctl日志交叉验证了这两块盘存在故障,也就是上文说的delayed的错误计数。
随后同时将TSR日志perccli64alilog适配器日志提交给DELL,DELL认可并以此作为依据成功报修。

1
2
3
4
5
6
7
# PD02的timeout
24368: YY-MM-DD HH:MM:SS WARNING:Command timeout on PD 02(e0x20/s2) Path 5000c500cdda6095, CDB: 2a 00 0f 1a ee 00 00 00 80 00
# PD09的timeout
2413: YY-MM-DD HH:MM:SS WARNING:Command timeout on PD 09(e0x20/s9) Path 5000c500cdd04681, CDB: 4d 00 4e 00 00 00 00 00 04 00

# 同时在这份日志顶部部分也输出了RAID控制器和磁盘的详情
# Device Information部分的Slot Number也对应了PD02 PD09

2025-10-16最新消息:DELL高级工程师驳回了维修请求

然后给出了下面两篇文章

PowerEdge:某些企业硬盘驱动器上读取和验证 ECC 错误的 SMART 错误率较高

ScaleIO 硬件感知功能填写 PERC 术语

故障盘PD 02/09

slot2、9: TOSHIBA AL14SXB30ENY

slot3-8、10-13: Seagate ST300MP0026

结合上面两篇文章和硬盘情况来看,确实,iDRAC没有报故障,同时smartctl和perccli64调查出所谓的”故障”,恰好是两块TOSHIBA的硬盘。
TOSHIBA的其他硬盘确实也被记录到了文章中,提到了会在perccli64中误报timeout
结合smartctl记录的ECC纠错数量为天文数字,侧面反映了DELL所说的smartctlECC纠错计数不可靠也是事实。
目前看来,维修诉求被DELL工程师驳回也属于合理范围
且故障仅仅体现在运维监测平台告警IO延迟达到128ms,持续时间不足1分钟,随后恢复
故本次报障取消

补充:

该问题提交给了DELL客户经理

您好,我这边有台XXX PowerEdge XXX,在我们运维监控平台发现告警 IO延迟过高,触发时值: XXXms。
针对该告警我们筛查了TSR日志,并未发现告警记录;
进一步筛查了smartctl日志,发现PD 02/09存在 perccli64告警 Command timeout on PD 02/09;
且smartctl记录到ECC delayed纠正8XXX次。

目前工程师回复提到了smartctl日志错误率,对于某些企业的硬盘仅供参考,实际现象:
其他Seagate硬盘存在1X亿次ECC fast纠错计数,故我们忽略该告警。
故障的PD02/09为TOSHIBA,存在8XXX次 ECC delayed纠错计数,不过尚未出现无法纠错和扇区故障记录,我们暂时忽略。

工程师回复提到了perccli64日志告警timeout,文章解释为:
某个供应商的固态硬盘 (SSD) 不支持其中一个命令 (cdb= 4d 00 51 00 00 00 00 00 00 04 00)
复查后发现,PD 02/09恰好是TOSHIBA的硬盘,且在文章中也有提到TOSHIBA的某个型号SSD不支持该命令,且其他Seagate硬盘均为记录该错误。
故我们根据文章内容,忽略该告警。

鉴于本次排障报修涉及的日志和排障过程较为繁琐,目前理清楚前因后果之后,XXX要求我询问下您,看看这次的报障是驳回继续观察,还是说直接安排更换?

目前尚未收到回复…

DELL服务器硬盘IO告警排障思路

系统报IO告警,在带外无异常的情况下,在操作系统中进行排障

故障现象

监测平台报障IO占用率和延迟过高

初步排障

登录带外观察是否有故障日志,无论是否有故障日志,均需要进一步进行二次核对

JBOD直通无RAID排障

使用smartctl命令观察磁盘健康状态,网络上有大量教程,不再赘述

如果磁盘本身无故障,观察输出结果中的199 UltraDMA CRC Error Count这一行是否有记录,这是硬件通信错误的日志,如果有记录到纠正次数,那就说明发生了硬件连接的问题,如硬盘背板故障,连接线故障,接口松动等

批量排障命令参考

for i in {a..z}; do [ -b "/dev/sd$i" ] && echo "sd$i:" && sudo smartctl -a "/dev/sd$i" | grep "199"; done

RAID阵列模式排障

做了阵列的磁盘无法直接使用smartctl进行排障,需要改为smartctl -a -d megaraid,3 /dev/sdX的方式排障,megaraid,后面跟你的硬盘的编号,/dev/sdX则是对应这个阵列在系统中的编号

范例:

1
2
3
4
5
6
7
8
# raid5阵列,挂载为/dev/sdb
# 阵列中disk2存在故障
smartctl -a -d megaraid,2 /dev/sdb

# 批量查询所有阵列所有盘
# 其中a..d是用于遍历/dev/sda-d,根据你的阵列情况调整
# 其中0..10是用于遍历一个阵列下有多少个硬盘,根据你的阵列情况调整
for raid in {a..d};do for disk in {0..10};do smartctl -a -d megaraid,$disk /dev/sd$raid | grep -i "CRC\|Error";done;done

HDD SSD二合一版

该脚本会在当前目录输出smartctl的日志源码到disk_error_$(date +%Y%m%d_%H%M%S).log文件

推荐使用此单行模式,复制粘贴直接用,不需要创建shell文件

1
log_file="disk_error_$(date +%Y%m%d_%H%M%S).log"; for raid in {a..d}; do [ -b "/dev/sd$raid" ] && for disk in {0..23}; do smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1 && output=$(smartctl -a -d megaraid,$disk /dev/sd$raid) && serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}') && if echo "$output" | grep -q "SSD"; then reallocated_sectors=$(echo "$output" | grep "Reallocated_Sector_Ct" | awk '{print $10}'); reallocated_sectors=${reallocated_sectors:-0}; current_pending=$(echo "$output" | grep "Current_Pending_Sector" | awk '{print $10}'); current_pending=${current_pending:-0}; reported_uncorrect=$(echo "$output" | grep "Reported_Uncorrect" | awk '{print $10}'); reported_uncorrect=${reported_uncorrect:-0}; offline_uncorrect=$(echo "$output" | grep "Offline_Uncorrectable" | awk '{print $10}'); offline_uncorrect=${offline_uncorrect:-0}; crc_errors=$(echo "$output" | grep "CRC_Error_Count" | awk '{print $10}'); crc_errors=${crc_errors:-0}; [ "$reallocated_sectors" -gt 0 ] || [ "$current_pending" -gt 0 ] || [ "$reported_uncorrect" -gt 0 ] || [ "$offline_uncorrect" -gt 0 ] || [ "$crc_errors" -gt 0 ] && echo "$output" >> "$log_file" && echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n\033[36;1m05 重分配扇区计数(Reallocated Sector Count):\033[31;1m$reallocated_sectors\033[0m\n\033[36;1m197 当前待处理扇区(Current Pending Sector Count):\033[31;1m$current_pending\033[0m\n\033[36;1m已报告的不可纠正错误(Reported Uncorrectable Errors):\033[31;1m$reported_uncorrect\033[0m\n\033[36;1m离线不可纠正错误(Offline Uncorrectable):\033[31;1m$offline_uncorrect\033[0m\n\033[36;1m接口CRC错误计数(CRC Error Count):\033[31;1m$crc_errors\033[0m\n"; else read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}'); read_uncorrected=${read_uncorrected:-0}; verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}'); verify_uncorrected=${verify_uncorrected:-0}; total_uncorrected=$(echo "$output" | grep "Total uncorrected errors" | awk '{print $NF}'); total_uncorrected=${total_uncorrected:-0}; grown_defect_list=$(echo "$output" | grep "Elements in grown defect list" | awk '{print $NF}'); grown_defect_list=${grown_defect_list:-0}; non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}'); non_medium=${non_medium:-0}; [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$total_uncorrected" -gt 0 ] || [ "$grown_defect_list" -gt 0 ] || [ "$non_medium" -gt 0 ] && echo "$output" >> "$log_file" && echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n\033[36;1m读无法纠正错误(Read total uncorrected errors):\033[31;1m$read_uncorrected\033[0m\n\033[36;1m校验无法纠正错误(Verify total uncorrected errors):\033[31;1m$verify_uncorrected\033[0m\n\033[36;1m总无法纠正错误(Total uncorrected errors):\033[31;1m$total_uncorrected\033[0m\n\033[36;1m已增长缺陷列表元素(Elements in grown defect list):\033[31;1m$grown_defect_list\033[0m\n\033[36;1m非介质错误(Non-medium error count):\033[31;1m$non_medium\033[0m\n"; fi; done; done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/bin/bash

# 日志文件以日期时间命名
log_file="disk_error_$(date +%Y%m%d_%H%M%S).log"

# 遍历可能的RAID设备(sda, sdb, sdc, sdd)
for raid in {a..d}; do
if [ -b "/dev/sd$raid" ]; then
for disk in {0..23}; do
if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then
output=$(smartctl -a -d megaraid,$disk /dev/sd$raid)

serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}')

if echo "$output" | grep -q "SSD"; then
# ================= SSD =================
reallocated_sectors=$(echo "$output" | grep "Reallocated_Sector_Ct" | awk '{print $10}')
reallocated_sectors=${reallocated_sectors:-0}

current_pending=$(echo "$output" | grep "Current_Pending_Sector" | awk '{print $10}')
current_pending=${current_pending:-0}

reported_uncorrect=$(echo "$output" | grep "Reported_Uncorrect" | awk '{print $10}')
reported_uncorrect=${reported_uncorrect:-0}

offline_uncorrect=$(echo "$output" | grep "Offline_Uncorrectable" | awk '{print $10}')
offline_uncorrect=${offline_uncorrect:-0}

crc_errors=$(echo "$output" | grep "CRC_Error_Count" | awk '{print $10}')
crc_errors=${crc_errors:-0}

if [ "$reallocated_sectors" -gt 0 ] || [ "$current_pending" -gt 0 ] || \
[ "$reported_uncorrect" -gt 0 ] || [ "$offline_uncorrect" -gt 0 ] || [ "$crc_errors" -gt 0 ]; then
echo "$output" >> "$log_file"
echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n"
echo -e "\033[36;1m05 重分配扇区计数(Reallocated Sector Count):\033[31;1m$reallocated_sectors\033[0m"
echo -e "\033[36;1m197 当前待处理扇区(Current Pending Sector Count):\033[31;1m$current_pending\033[0m"
echo -e "\033[36;1m已报告的不可纠正错误(Reported Uncorrectable Errors):\033[31;1m$reported_uncorrect\033[0m"
echo -e "\033[36;1m离线不可纠正错误(Offline Uncorrectable):\033[31;1m$offline_uncorrect\033[0m"
echo -e "\033[36;1m接口CRC错误计数(CRC Error Count):\033[31;1m$crc_errors\033[0m\n"
fi
else
# ================= HDD =================
read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}')
read_uncorrected=${read_uncorrected:-0}

verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}')
verify_uncorrected=${verify_uncorrected:-0}

total_uncorrected=$(echo "$output" | grep "Total uncorrected errors" | awk '{print $NF}')
total_uncorrected=${total_uncorrected:-0}

grown_defect_list=$(echo "$output" | grep "Elements in grown defect list" | awk '{print $NF}')
grown_defect_list=${grown_defect_list:-0}

non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}')
non_medium=${non_medium:-0}

if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || \
[ "$total_uncorrected" -gt 0 ] || [ "$grown_defect_list" -gt 0 ] || [ "$non_medium" -gt 0 ]; then
echo "$output" >> "$log_file"
echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD 磁盘 \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) 检测到异常:\033[0m\n"
echo -e "\033[36;1m读无法纠正错误(Read total uncorrected errors):\033[31;1m$read_uncorrected\033[0m"
echo -e "\033[36;1m校验无法纠正错误(Verify total uncorrected errors):\033[31;1m$verify_uncorrected\033[0m"
echo -e "\033[36;1m总无法纠正错误(Total uncorrected errors):\033[31;1m$total_uncorrected\033[0m"
echo -e "\033[36;1m已增长缺陷列表元素(Elements in grown defect list):\033[31;1m$grown_defect_list\033[0m"
echo -e "\033[36;1m非介质错误(Non-medium error count):\033[31;1m$non_medium\033[0m\n"
fi
fi
fi
done
fi
done

输出效果如下

20250918173451

以下部分的忽略掉即可,老版本的


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 批量巡检脚本 - 适用于HDD

# 遍历可能的RAID设备(sda, sdb, sdc, sdd)
for raid in {a..d}; do
# 检查设备是否存在
if [ -b "/dev/sd$raid" ]; then
# 遍历每个RAID设备上的物理磁盘(0到23号)
for disk in {0..23}; do
# 检查磁盘是否可访问(尝试获取基本信息,输出重定向到/dev/null)
if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then
# 获取完整的SMART数据
output=$(smartctl -a -d megaraid,$disk /dev/sd$raid)

# 从输出中提取序列号
serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}')

# 提取读取无法纠正错误次数(最后一列)
read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}')

# 提取验证无法纠正错误次数(最后一列)
verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}')

# 提取非介质错误次数(最后一列)
non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}')

# 检查是否有任何错误(任一错误计数大于0)
if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then
# 将有错误的磁盘完整SMART数据追加到日志文件
echo "$output" >> disk_error.log

# 输出格式化错误信息
echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"
echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m"
echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m"
echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m"
echo -e "\n"
fi
fi
done
fi
done

# 整合为一行,一条龙服务
for raid in {a..d}; do if [ -b "/dev/sd$raid" ]; then for disk in {0..23}; do if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then output=$(smartctl -a -d megaraid,$disk /dev/sd$raid); serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}'); read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}'); verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}'); non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}'); if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then echo "$output" >> disk_error.log; echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"; echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m"; echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m"; echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m"; echo -e "\n"; fi; fi; done; fi; done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# 批量巡检脚本 - 适用于SSD

# 遍历可能的RAID设备(sda, sdb, sdc, sdd)
for raid in {a..d}; do
# 检查设备是否存在
if [ -b "/dev/sd$raid" ]; then
# 遍历每个RAID设备上的物理磁盘(0到23号)
for disk in {0..23}; do
# 检查磁盘是否可访问(尝试获取基本信息,输出重定向到/dev/null)
if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then
# 获取完整的SMART数据
output=$(smartctl -a -d megaraid,$disk /dev/sd$raid)

# 从输出中提取序列号
serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}')

# 检测磁盘类型(SSD或HDD)
if echo "$output" | grep -q "SSD"; then
# SSD磁盘:使用Media_and_Data_Integrity_Errors等属性
media_errors=$(echo "$output" | grep "Media_and_Data_Integrity_Errors" | awk '{print $10}')
media_errors=${media_errors:-0}

# 对于SSD,我们主要关注媒体错误和ECC错误
uncorrected_errors=$(echo "$output" | grep "Error_Information_Log_Entries" | awk '{print $10}')
uncorrected_errors=${uncorrected_errors:-0}

# 检查SSD错误
if [ "$media_errors" -gt 0 ] || [ "$uncorrected_errors" -gt 0 ]; then
echo "$output" >> disk_error.log
echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"
echo -e "\033[36;1m媒体和数据完整性错误:\033[31;1m$media_errors\033[36;1m"
echo -e "\033[36;1m错误信息日志条目:\033[31;1m$uncorrected_errors\033[36;1m"
echo -e "\n"
fi
else
# HDD磁盘:使用原有的错误计数器
read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}')
read_uncorrected=${read_uncorrected:-0}

verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}')
verify_uncorrected=${verify_uncorrected:-0}

non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}')
non_medium=${non_medium:-0}

# 检查HDD错误
if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then
echo "$output" >> disk_error.log
echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"
echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m"
echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m"
echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m"
echo -e "\n"
fi
fi
fi
done
fi
done

# 一条龙服务
for raid in {a..d}; do if [ -b "/dev/sd$raid" ]; then for disk in {0..23}; do if smartctl -d megaraid,$disk /dev/sd$raid -i >/dev/null 2>&1; then output=$(smartctl -a -d megaraid,$disk /dev/sd$raid); serial=$(echo "$output" | grep "Serial number:" | awk '{print $3}'); if echo "$output" | grep -q "SSD"; then media_errors=$(echo "$output" | grep "Media_and_Data_Integrity_Errors" | awk '{print $10}'); media_errors=${media_errors:-0}; uncorrected_errors=$(echo "$output" | grep "Error_Information_Log_Entries" | awk '{print $10}'); uncorrected_errors=${uncorrected_errors:-0}; if [ "$media_errors" -gt 0 ] || [ "$uncorrected_errors" -gt 0 ]; then echo "$output" >> disk_error.log; echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 SSD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"; echo -e "\033[36;1m媒体和数据完整性错误:\033[31;1m$media_errors\033[36;1m"; echo -e "\033[36;1m错误信息日志条目:\033[31;1m$uncorrected_errors\033[36;1m"; echo -e "\n"; fi; else read_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^read:" | awk '{print $NF}'); read_uncorrected=${read_uncorrected:-0}; verify_uncorrected=$(echo "$output" | grep -A 10 "Error counter log:" | grep "^verify:" | awk '{print $NF}'); verify_uncorrected=${verify_uncorrected:-0}; non_medium=$(echo "$output" | grep "Non-medium error count:" | awk '{print $NF}'); non_medium=${non_medium:-0}; if [ "$read_uncorrected" -gt 0 ] || [ "$verify_uncorrected" -gt 0 ] || [ "$non_medium" -gt 0 ]; then echo "$output" >> disk_error.log; echo -e "\033[36;1mRAID \033[32;1msd$raid \033[36;1m中的 HDD Disk \033[32;1m#$disk \033[36;1m(SN:\033[33;1m $serial) \033[36;1m存在以下错误:\n"; echo -e "\033[36;1m读取错误无法纠正次数:\033[31;1m$read_uncorrected\033[36;1m"; echo -e "\033[36;1m磁盘自检无法纠错次数:\033[31;1m$verify_uncorrected\033[36;1m"; echo -e "\033[36;1m非介质错误次数:\033[31;1m$non_medium\033[36;1m"; echo -e "\n"; fi; fi; fi; done; fi; done

以上部分的忽略掉即可,老版本的

原始错误日志解读

HDD范例

范例:

20250917112407

报错内容 翻译 说明
Error Corrected by ECC ECC纠错 当某个扇区存在错误时,硬盘通过内置的错误校正码(ECC)机制自动完成的纠错次数。
Total errors corrected 已纠错总次数 记录累计成功纠正的错误总数(包含所有纠错方式)。
Correction algorithm invocations 纠错算法调用次数 硬盘调用纠错算法的次数,部分可能无需实际改写即可修复;一般无需重点关注。
Gigabytes processed 已处理数据量(GB) 表示在统计期间,通过 ECC 机制处理过的数据总量(以 GB 计)。
Total uncorrected errors 未能纠错总数 ECC 无法修复的错误次数,表示确实发生了数据损坏;若大于 0,需立即关注。
Non-medium error count 非介质错误计数 非存储介质本身的故障,例如接口、背板、线缆、电源等导致的通信或传输错误。
fast rereads 快速重读 通过快速重读实现的自动纠错,对性能影响较小。
delayed rereads 延迟重读 通过延迟重读实现的纠错,通常会增加 I/O 响应时间。
rewrites 重写 当重读成功后,将正确的数据重新写回故障扇区,以防止未来再次出错。

范例中ECC纠错2555次,且存在4次无法纠错,且非介质故障高达13次,该硬盘急需维护。

SSD范例
报错内容 翻译 说明
Reallocated Sector Count 重分配扇区计数 表示硬盘将坏掉或不可靠的扇区重映射到备用扇区的次数。数值大于 0 意味着盘体已经出现物理坏块。若持续增加,说明硬盘劣化严重,应尽快备份并考虑更换。
Reported Uncorrectable Errors 报告无法纠正错误 硬盘在正常读写中发生的、ECC 无法修复的错误次数。这类错误会导致数据直接损坏,是严重的健康警告指标。
Current Pending Sector Count 当前待处理扇区 等待进一步确认或重新分配的扇区数量。通常表示这些扇区在读写中出现问题,待后续重写确认是否稳定。若数值不降反升,说明盘体状态持续恶化。
Offline Uncorrectable 离线不可校正错误 硬盘在离线检测或自检时发现的无法修复错误。表示硬盘在后台扫描时检测到了坏块,可靠性降低。
CRC Error Count 接口 CRC 错误次数 表示主机与硬盘之间数据传输时出现的循环冗余校验错误,通常由线缆、接口、背板、电磁干扰或电源问题引起,而非硬盘介质损坏。

服务器稳定性及基准测试方法

重要更新: 2025-11-4 硬盘测试开发了全自动测试工具,见下方硬盘测试部分

测试项

测试前准备

CPU调优

BIOS关闭超线程

方法:
BIOS里找CPU或者Socket Configuration,进入其中,找Processor Configuration,
进入其中关闭超线程即可
超线程在BIOS的写法通常有:

  • SMT
  • Logical Processor(LP)
  • Hyper-Threading

理由:
超线程的作用是让 CPU 能在一个线程等待(例如等待内存I/O)时,利用空闲执行单元去执行另一个线程。
所以对于CPU性能测试的浮点运算、以及CPU满载的业务场景,超线程导致的线程切换,反而会:

  • 增加上下文切换与调度开销(Scheduler Overhead)

    • 操作系统调度器看到两个逻辑核心,调度两个重量级任务上去,但实际上底层的物理核根本没法承担
  • 导致缓存污染(Cache Pollution)

    • 不同线程使用的数据不同,缓存反而会互相驱逐对方数据
    • 这个问题与下文中根据L3缓存设计NB大小尤其相关
BIOS关闭C-State

方法:
BIOS里找CPU或者Socket Configuration,进入其中,找Advanced Power Management Configuration,
进入其中CPU C State Control,参数如下:

参数 解释 建议设置
Enable Monitor MWAIT 是否允许使用 MWAIT 指令进入 C-state Disabled
CPU C6 report 是否让操作系统知道 C6 可用 Disabled
Enhanced Halt State (C1E) 启用增强型省电停机(降压降频) Disabled
OS ACPI Cx 操作系统可用的最深 C 状态(如 ACPI C2) 设置为能选的最小值

补充:
上面是比较通用的写法,但我看到Lenovo写的是SST-PP……自行判断或者问下厂商吧
原理就是C-State设置0最好,就像Lenovo的SST-PP,BIOS里也写了,Level 0 TDP 185W,最高性能

20251113154536

理由:
C-State是省电休眠状态控制,除非你要省电,否则把它关了。
让性能最高,减少CPU状态切换导致的延迟,关不了就保持在C0使CPU始终活跃。

存储调优

RAID调优

Stripe Size(带宽): 1m
写入策略: Write Back(回写)
驱动器缓存: Drive Cache disabled(关闭磁盘缓存)
初始化方式: Fast Initialize(快速初始化)

文件系统调优

采用parted分区,gpt
分区从2048s扇区起,保持4k对齐
文件系统采用xfs即可

CPU基准测试

测试项 测试工具 参考业务场景 测试方式
双精度浮点运算 float64 HPL 该项测试为HPC行业标准,TOP500超级计算机排行榜均采用该方式评估 测试3次取均值

内存基准测试

测试项 测试工具 选择理由 测试方式
内存带宽 STREAM Benchmark HPC内存带宽的行业标准测试,TOP500超级计算机排行榜均采用该方式评估 Copy/Scale/Add/Triad测试3次取均值

硬盘测试

重要更新: 2025-11-5 发布了v1.1版本,修复了读测试无IO导致测试结果失真的BUG
新增了实时显示FIO进度的功能


重要更新: 2025-11-4 发布了fio硬盘测试的全自动工具
工具涵盖了自动运行fio,通过预置的benchmark.fio文件自动运行60项基础测试
运行前检查其中的directory=/mnt/test/ ; 测试目录路径,请根据实际情况修改
补充:注意directory=后面一定是带/的,因为是目录
可以选择将需要测试的硬盘挂载到这个目录,或者修改为你想要的目录
runtime=30s ; 每个测试运行 30 秒,则是每项测试运行多久
ramp_time=5s ; 5秒预热,使设备进入稳定状态,这一条无需修改,作用是按照所设定的参数运行5秒确保硬盘跑起来,避免冷启动的性能过低或者波动
size=10G,这是测试文件的大小,注意根据你的容量并计算numjobs的数量,例如8个numjobs则是10G*8=80G硬盘空间
full_auto设置执行权限,并确保benchmark.fio和该程序在一个目录即可
运行完成后会在当前目录生成原始数据的json文件和导出可读的xlsxExcel表格

仓库地址:https://github.com/1949hacker/fio_benchmark

可执行程序下载

运行效果图1

运行效果图2

v1.1效果图


测试项 测试工具 参考业务场景 测试方式
4k单队列 fio bs=4k iodepth=1 MySQL场景 测试3次取均值
4k 32队列 fio bs=4k iodepth=32 MongoDB场景 测试3次取均值
32k 32队列 fio bs=32k iodepth=32 高并发Web服务,Kafka日志刷盘,多线程缓存写入 测试3次取均值
1m 单队列 fio bs=1m iodepth=1 顺序读写,备份、视频流、镜像分发 测试3次取均值
1m 32队列 fio bs=1m iodepth=32 并发大文件读写,大规模备份,分布式存储,对象存储 测试3次取均值
硬盘压测 fio -numjobs=32 -bs=4k -iodepth=64 -directory 具体代码见下方及下文中有关于fio参数的解释

补充说明:除系统盘不能直接测试裸盘外,其他盘均应使用裸盘测试,如fio -filename=/dev/sdbfio -filename=/dev/nvme0n1,直接指向硬盘块设备,而不是分区或路径


1
fio -name=disk_benchmark -size=5G -runtime=5d -time_base -direct=1 -ioengine=libaio -randrepeat=0 -numjobs=32 -group_reporting -bs=4k -rw=randrw -rwmixwrite=30 -directory=/home/test/ -iodepth=64

其中针对业务场景,根据单台服务器部署的业务数量适当设置numjobs以模拟操作系统/应用层并发。

例如单台服务器4个数据库,则fio bs=4k iodepth=32 numjobs=4

iodepth对应单个线程的队列深度,用于存储设备并发能力测试

numjobs对应多个线程并发,用于测试操作系统/应用层并发能力

综合基准测试

测试项 测试工具 参考业务场景 测试方式
综合性能指数 GeekBench 横向比较整机性能,仅供参考 普通测试

CentOS 7.9.2009跑不了GeekBench 6

GeekBench历史版本

测试过程

AMD 9F14平台测试

补充:

可以先准备好fio程序的目录/root/fio
编译好hpl文件并确保目录是/root/hpl
编译好内存测试的stream并放在/root/memtest
当然,目录自由发挥也可以,改下方代码即可

1
2
3
# 一行代码搞定内存基准、CPU基准、存储基准的全自动测试
# 注意其中的目录和-np 24的参数根据下文内容,改为你自己的
cd /root/memtest/ && for i in {0..2};do ./stream 2>&1 | tee -a mem_$i.log;done && cd /root/hpl/bin/Linux_Intel64/ && for i in {0..2};do mpirun --allow-run-as-root -np 24 --map-by core --bind-to core ./xhpl 2>&1 | tee -a HPL_$i.out;done && cd /root/fio && ./full_auto.v2.2.0

安装CentOS 7.9.2009

替换源为清华大学CentOS-Vault源

清华CentOS-Vault仓库输入小版本,获取命令

例如CentOS 7.9.2009如下

1
2
3
4
5
sed -e "s|^mirrorlist=|#mirrorlist=|g" \
-e "s|^#baseurl=http://mirror.centos.org/centos/\$releasever|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009|g" \
-e "s|^#baseurl=http://mirror.centos.org/\$contentdir/\$releasever|baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009|g" \
-i.bak \
/etc/yum.repos.d/CentOS-*.repo

该命令执行后会将原本的所有源配置文件备份为带.bak后缀名的备份

可以通过下方的命令快速还原

1
2
3
4
5
6
7
8
# 启用bash扩展通配符
shopt -s extglob

# 使用通配符快速删除不带.bak的文件
rm !(*.bak) -f

# 使用for循环快速去掉.bak后缀
for f in *.bak;do mv -- "$f" "${f%.bak}";done

yum makecache更新源

yum install vim安装vim编辑器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 更新源
yum makecache
# 安装vim
yum install vim
# 编辑ssh配置文件
vim /etc/ssh/sshd_config
# 设置心跳
# 取消注释,设置为每60秒发送一次心跳重复9999999次
ClientAliveInterval 60
ClientAliveCountMax 99999
# 设置允许root用户登录
# 取消注释并配置为yes
PermitRootLogin yes
# 重启ssh服务
systemctl restart sshd

准备CPU的Linpack测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# 基础环境
# 安装OpenBLAS
# 安装OpenMPI
yum install -y epel-release && yum install gcc gcc-c++ gcc-gfortran cmake python3 zlib* -y && yum install -y openblas openblas-devel && yum install -y openmpi openmpi-devel

# 找到MPI的位置
find /usr -name "mpicc" 2>/dev/null
# 我的输出如下
/usr/lib64/openmpi/bin/mpicc
# 添加MPI到环境变量
echo 'export PATH=/usr/lib64/openmpi/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/lib64/openmpi/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
# 临时生效
export PATH=/usr/lib64/openmpi/bin:$PATH
export LD_LIBRARY_PATH=/usr/lib64/openmpi/lib:$LD_LIBRARY_PATH

# 复查一下系统中有没有openblas
ldconfig -p | grep openblas
# 输出通常如下所示
libopenblas64_.so.0 (libc6,x86-64) => /lib64/libopenblas64_.so.0
libopenblas64.so.0 (libc6,x86-64) => /lib64/libopenblas64.so.0
libopenblasp64_.so.0 (libc6,x86-64) => /lib64/libopenblasp64_.so.0
libopenblasp64.so.0 (libc6,x86-64) => /lib64/libopenblasp64.so.0
libopenblasp.so.0 (libc6,x86-64) => /lib64/libopenblasp.so.0
libopenblaso64_.so.0 (libc6,x86-64) => /lib64/libopenblaso64_.so.0
libopenblaso64.so.0 (libc6,x86-64) => /lib64/libopenblaso64.so.0
libopenblaso.so.0 (libc6,x86-64) => /lib64/libopenblaso.so.0
libopenblas.so.0 (libc6,x86-64) => /lib64/libopenblas.so.0

# 下载High Performance Linpack
# 去官网检查最新版https://www.netlib.org/benchmark/hpl/
wget https://www.netlib.org/benchmark/hpl/hpl-2.3.tar.gz
tar xvf hpl-2.3.tar.gz
mv hpl-2.3 hpl
mv hpl ~/
cd ~/hpl

# 从模板创建副本并改动编译器参数
# INTEL使用Make.Linux_Intel64
# AMD使用Make.Linux_ATHLON_FBLAS
cp setup/Make.Linux_ATHLON_FBLAS ./Make.Linux_ATHLON_FBLAS
vim Make.Linux_ATHLON_FBLAS

# 64行的ARCH的名称可以自定义,但没必要,需要和文件名后缀一致,如Make.Linux_ATHLON_FBLAS
# 后续make编译时会用到,如make arch=AMD_OpenBLAS
ARCH = Linux_ATHLON_FBLAS

# 配置openblas通用开源方案,保持测试结果的中立
# 避免MKL和AOCL BLIS/LibFLAME对于INTEL AMD的专项优化
# 修改配置使HPL走CBLAS接口,而不是老的Fortran BLAS
# 在配置文件中找到
HPL_DEFS = $(F2CDEFS) $(HPL_OPTS) $(HPL_INCLUDES)

# 在末尾加上 -DHPL_CALL_CBLAS
HPL_DEFS = $(F2CDEFS) $(HPL_OPTS) $(HPL_INCLUDES) -DHPL_CALL_CBLAS

# 找到CCFLAGS,添加-march=native
CCFLAGS = $(HPL_DEFS) -fomit-frame-pointer -O3 -funroll-loops -W -Wall -march=native

# 默认的配置如下
LAdir = $(HOME)/netlib/ARCHIVES/Linux_ATHLON
LAinc =
LAlib = $(LAdir)/libf77blas.a $(LAdir)/libatlas.a
# 修改为
LAdir = /usr/lib64/openblas # 你的 OpenBLAS库路径,find / -name libopenblas*
LAinc =
LAlib = -lopenblas

# 改为直接使用mpicc编译
# 修改CC
CC = mpicc

# 注释掉84-86行左右的三行MP配置
# 在前面加#注释了就行
MPdir = /usr/local/mpi
MPinc = -I$(MPdir)/include
MPlib = $(MPdir)/lib/libmpich.a


# 这部分是针对Intel的编译参数设置,AMD忽略
# --------- start ---------
OMP_DEFS = -openmp
# 改为
OMP_DEFS = -fopenmp

CCFLAGS = CCFLAGS = $(HPL_DEFS) -O3 -w -ansi-alias -i-static -z noexecstack -z relro -z now -nocompchk -Wall
# 修改为
CCFLAGS = $(HPL_DEFS) -O3 -w -Wall -fopenmp -fno-strict-aliasing -march=native -z noexecstack -z relro -z now

LINKFLAGS = $(CCFLAGS) $(OMP_DEFS) -mt_mpi
#修改为
LINKFLAGS = $(CCFLAGS) $(OMP_DEFS)
# --------- end ---------

# 编译HPL
make -f Make.top build_src arch=Linux_ATHLON_FBLAS
make -f Make.top build_tst arch=Linux_ATHLON_FBLAS


# 编辑HPL.dat
cd bin/Linux_ATHLON_FBLAS
# Intel是Linux_Intel64
cd bin/Linux_Intel64

mv HPL.dat HPL.dat.bak
vim HPL.dat

# HPL.dat范例,参数及其解析详见下方表格
HPLinpack benchmark input file
Innovative Computing Laboratory, University of Tennessee
HPL.out output file name (if any)
6 device out (6=stdout,7=stderr,file)
1 # of problems sizes (N)
165120 Ns
1 # of NBs
384 NBs
0 PMAP process mapping (0=Row-,1=Column-major)
1 # of process grids (P x Q)
8 Ps
12 Qs
16.0 threshold
1 # of panel fact
2 PFACTs (0=left, 1=Crout, 2=Right)
1 # of recursive stopping criterium
4 NBMINs (>= 1)
1 # of panels in recursion
2 NDIVs
1 # of recursive panel fact.
1 RFACTs (0=left, 1=Crout, 2=Right)
1 # of broadcast
1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1 # of lookahead depth
1 DEPTHs (>=0)
2 SWAP (0=bin-exch,1=long,2=mix)
64 swapping threshold
0 L1 in (0=transposed,1=no-transposed) form
0 U in (0=transposed,1=no-transposed) form
1 Equilibration (0=no,1=yes)
8 memory alignment in double (> 0)
##### This line (no. 32) is ignored (it serves as a separator). ######
0 Number of additional problem sizes for PTRANS
1200 10000 30000 values of N
0 number of additional blocking sizes for PTRANS
40 9 8 13 13 20 16 32 64 values of NB

# 禁用防火墙
systemctl stop firewalld
setenforce 0
# 开始运行
mpirun --allow-run-as-root -np 96 --map-by core --bind-to core ./xhpl

# 使用htop查看硬件负载
yum install -y htop
htop

# 测试结果范例,其中183行和190行分别是测试结果和误差,附带了注释
================================================================================
HPLinpack 2.3 -- High-Performance Linpack benchmark -- December 2, 2018
Written by A. Petitet and R. Clint Whaley, Innovative Computing Laboratory, UTK
Modified by Piotr Luszczek, Innovative Computing Laboratory, UTK
Modified by Julien Langou, University of Colorado Denver
================================================================================

An explanation of the input/output parameters follows:
T/V : Wall time / encoded variant.
N : The order of the coefficient matrix A.
NB : The partitioning blocking factor.
P : The number of process rows.
Q : The number of process columns.
Time : Time in seconds to solve the linear system.
Gflops : Rate of execution for solving the linear system.

The following parameter values will be used:

N : 165120
NB : 384
PMAP : Row-major process mapping
P : 8
Q : 12
PFACT : Right
NBMIN : 4
NDIV : 2
RFACT : Crout
BCAST : 1ringM
DEPTH : 1
SWAP : Mix (threshold = 64)
L1 : transposed form
U : transposed form
EQUIL : yes
ALIGN : 8 double precision words

--------------------------------------------------------------------------------

- The matrix A is randomly generated for each test.
- The following scaled residual check will be computed:
||Ax-b||_oo / ( eps * ( || x ||_oo * || A ||_oo + || b ||_oo ) * N )
- The relative machine precision (eps) is taken to be 1.110223e-16
- Computational tests pass if scaled residuals are less than 16.0

================================================================================
T/V N NB P Q Time Gflops
--------------------------------------------------------------------------------
WR11C2R4 165120 384 8 12 1755.82 1.7094e+03
# 这里的1.7094e+03也就是1.7094*10^3 Gflops=1709.4GFlops=1.7094TFlops
HPL_pdgesv() start time Mon Sep 15 12:53:01 2025

HPL_pdgesv() end time Mon Sep 15 13:22:17 2025

--------------------------------------------------------------------------------
||Ax-b||_oo/(eps*(||A||_oo*||x||_oo+||b||_oo)*N)= 4.65407372e-04 ...... PASSED
# 这里的PASSED说明误差合格,测试有效
# 误差为4.65407372*10^-4=0.00046540737
================================================================================

Finished 1 tests with the following results:
1 tests completed and passed residual checks,
0 tests completed and failed residual checks,
0 tests skipped because of illegal input values.
--------------------------------------------------------------------------------

End of Tests.
================================================================================
HPL.dat的参数及其说明

在线生成HPL.dat文件的网站 HPL.dat

参数 说明
Nodes 对应CPU数量
Cores per Node 每个CPU多少核
Memory per Node(MB) 每个CPU有多少MB内存
Block Size(NB) HPL运算的块大小

NB 块大小计算方式:

设置适当的块大小,使数据块能够很好的放入CPU的高速缓存(L2/L3 Cache),如果数据块不能放入高速缓存,则不得不从慢得多的主内存RAM中进行读取,从而导致性能瓶颈。

NB最好是PQ的整数倍,以我的AMD 9A14为例,L3为384MB,96核心

HPL将矩阵N分块成NB*NB的小块,然后分布在一个二维进程网格P行Q列上

所以如果任何一方过长,就会造成通信路径变长,从而导致性能开销大

为了使性能达到最优,需要使这个二维网格接近正方形,也就是PQ值相近,且同时P*Q需要等于核心数,以确保每个核心都有数据块在计算

PQ计算公式

使用在线生成则直接跳过此处即可,仅用作学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 根据内核数量取近似的能开方的整数
# 例如96核取100开方
# 然后用核数除平方根递归直到整除
96/10=9.6
96/9=10.66
96/8=12
# PQ则为8*12
# 该网格便由8行12列组成,接近正方形,避免了过长的通信路径
# 每个进程需要将分解结果广播给其他进程,所以过长的通信路径就意味着过长的通信开销
# 如图
- - - - - - -
- - - · - - -
- - - - - - -
# 对比过长的通信路径
- - - - - - - - ·- - - - - - -
NB块大小计算公式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 首先查询CPU的L3缓存
# 然后用L3缓存除以核心数,算出每个核心能使用的缓存均值
# 根据float类型占4字节,double类型占8字节计算
# 该性能测试为双精度浮点运算,取8字节
# 先计算每个核心能使用多少字节的缓存
# AMD 9A14 L3 384MB/96核心
384/96=4MB/core
4*1024*1024=4,194,304Byte/core
# 然后除以双精度的8字节,计算出每个核心处理多少个双精度浮点数,也就是NB²
4194304/8=524288NB²
# 然后开方得出NB
524288开方约为724NB
# 为了避免撑爆L3缓存,只取一半值
724/2=362/core
# 现代x86 CPU的Cache Line是固定的64字节
# 为了保证AVX/AVX-512指令能每次搬运时都尽量填满
# 所以寻找64的倍数,且尽量接近L3 Cache的极限
# 这样计算出每个核心计算大概362个NB,每次指令搬运64字节,总共搬运约6次
362/64=5.65625 取整 6
# 计算每次64字节总共6次的整数
64*6=384
# 最终得出NB最优值为384

最终计算出NB为384

注意其中Nodes填的是有多少个CPU
Cores per Node则是每个CPU有多少物理内核
Memory per Node(MB)是每个CPU有多少内存可用,所以内存条也需要均匀安装
Block Size(NB)则是填入上方计算的值

20250915145114

在线生成后的HPL.dat如下,HPL只会读取第一列,数字后方的是注释,带#的也是注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
HPLinpack benchmark input file
Innovative Computing Laboratory, University of Tennessee
HPL.out output file name (if any)
6 device out (6=stdout,7=stderr,file)
1 # of problems sizes (N)
165120 Ns
1 # of NBs
384 NBs
0 PMAP process mapping (0=Row-,1=Column-major)
1 # of process grids (P x Q)
8 Ps
12 Qs
16.0 threshold
1 # of panel fact
2 PFACTs (0=left, 1=Crout, 2=Right)
1 # of recursive stopping criterium
4 NBMINs (>= 1)
1 # of panels in recursion
2 NDIVs
1 # of recursive panel fact.
1 RFACTs (0=left, 1=Crout, 2=Right)
1 # of broadcast
1 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1 # of lookahead depth
1 DEPTHs (>=0)
2 SWAP (0=bin-exch,1=long,2=mix)
64 swapping threshold
0 L1 in (0=transposed,1=no-transposed) form
0 U in (0=transposed,1=no-transposed) form
1 Equilibration (0=no,1=yes)
8 memory alignment in double (> 0)
##### This line (no. 32) is ignored (it serves as a separator). ######
0 Number of additional problem sizes for PTRANS
1200 10000 30000 values of N
0 number of additional blocking sizes for PTRANS
40 9 8 13 13 20 16 32 64 values of NB

根据这份文件,运行命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
mpirun --allow-run-as-root -np 96 --map-by core --bind-to core ./xhpl
# --allow-run-as-root 允许root用户运行
# -np 96 启动96个MPI进程,与物理内核总数相同,不是线程数
# 如果你是4路每路20核那你就要填80,是所有CPU物理内核总数
# --map-by core MPI进程核CPU逻辑核心进行绑定
# --bind-to core 将每个进程锁定到core上运行,避免cache miss

# 显示的同时输出到文件,方便做为测试记录
mpirun --allow-run-as-root -np 96 --map-by core --bind-to core ./xhpl 2>&1 | tee -a HPL_0.out
# 一条命令实现运行完CPU基准后自动开始执行存储基准测试
# 在xhpl目录运行的
for i in {0..2};do mpirun --allow-run-as-root -np 96 --map-by core --bind-to core ./xhpl 2>&1 | tee -a HPL_$i.out;done && cd /root/fio/ && /root/fio/full_auto.v2.2.0

关于参数的解释在官网有详细说明HPL Tuning

进行内存的基准测试

使用STREAM Benchmark进行测试

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 安装编译工具
yum install gcc -y

# 下载源码,或者复制,都行
wget https://www.cs.virginia.edu/stream/FTP/Code/stream.c

# 编译stream
# 其中-DSTREAM_ARRAY_SIZE是设置每个数组的元素数量
# 测试的内存大小 = 物理内存上限 ÷ (数组个数 × 元素字节数)
# 物理内存上限取一半值,避免打到swap,256GB × 1/2 = 128GB = 137438953472 Bytes
# 数组个数 = 4 默认测试 Triad 核心项,需 a/b/c/d 4 个数组
# 元素字节数 = 8 推荐用 double 类型,兼顾精度和硬件带宽适配
# -DSTREAM_ARRAY_SIZE = 137438953472 ÷ (4 × 8) = 137438953472 ÷ 32 = 4294967296
gcc -O3 -fopenmp -DSTREAM_ARRAY_SIZE=4294967296 stream.c -o stream
# 实际编译中这个值太大了,超过程序的限制了,取一半就行了
# -O3编译器优化 -m64强制生成64位可执行文件
# -mcmodel=medium采用64位系统的内存模型,以支持超大全局数组 -fopenmp启用多线程并行框架
# -DTYPE=double定义元素类型为double高精度 -DSTREAM_TYPE=double同步内部的流类型与DTYPE一致
# -DN=2147483648冗余安全参数,用于兼容以N作为数组大小别名的源码
gcc -O3 -fopenmp -m64 -mcmodel=medium -DSTREAM_ARRAY_SIZE=2147483648 -DTYPE=double -DSTREAM_TYPE=double -DN=2147483648 stream.c -o stream


# 运行
./stream

# 直接输出到文件
./stream >> mem_test_0.log

输出结果如下,只需要第30行中Triad的带宽212674.9MB/s和延迟的平均值Avg time

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 100000000 (elements), Offset = 0 (elements)
Memory per array = 762.9 MiB (= 0.7 GiB).
Total memory required = 2288.8 MiB (= 2.2 GiB).
Each kernel will be executed 10 times.
The *best* time for each kernel (excluding the first iteration)
will be used to compute the reported bandwidth.
-------------------------------------------------------------
Number of Threads requested = 192
Number of Threads counted = 192
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 16443 microseconds.
(= 16443 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function Best Rate MB/s Avg time Min time Max time
Copy: 254046.3 0.006921 0.006298 0.011713
Scale: 189664.1 0.008491 0.008436 0.008531
Add: 204691.7 0.011839 0.011725 0.011884
Triad: 212674.9 0.011320 0.011285 0.011350
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------

只取其中的典型值Triad即可,代表典型科学计算/数值模拟中的内存访问性能

硬盘性能fio测试

使用fio进行硬盘的性能测试,测试结果包含IOPS、带宽、延迟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# 安装fio
yum install fio

# 准备好测试路径或硬盘
# 这里采用指向目录的方式测试
# 如需直接测试硬盘,则指向硬盘即可
# -name=本次测试的名称,自定义即可
# -size=本次测试的文件大小,建议大于内存的2倍,避免某些文件系统使用内存缓存
# 鉴于CentOS 7.9.2009的xfs和参数设置了direct=1,所以size不用大于内存
# -runtime=运行时间,单位支持秒s、分m、时h、天d
# -time_base 即使写入了指定大小的文件,依旧继续重复写入,直到runtime时间结束
# -direct=1设置不使用系统缓存,直写
# -ioengine=libaio直接使用Linux的异步IO引擎
# -randrepeat=0设置每次IO的随机性都不同,模拟真实业务场景
# -numjobs=8设置8个进程,模拟真实业务场景
# -group_reporting多进程的运行结果汇总汇报
# -bs=4k 块大小4k
# -rw=randrw随机读写
# -rwmixwrite=30设置30%写70%读,模拟真实业务场景
# -filename=/root/fio 在/root目录下创建一个名为fio的文件进行测试
# -directory=/dir/上方的filename也可替换为该命令指向目录,会在目录下根据numjobs的数量生成多个文件测试
# 注意下你的目录容量,别装不下size*numjobs的文件
# -iodepth= IO队列深度

# 运行5分钟,采用路径模式8进程写入,模拟最真实的业务场景
fio -name=disk_benchmark -size=10G -runtime=5m -time_base -direct=1 -ioengine=libaio -randrepeat=0 -numjobs=8 -group_reporting -bs=4k -rw=randrw -rwmixwrite=30 -filename=/home/fio -iodepth=1

# 1m顺序混合30%写70%读范例
fio -name=disk_benchmark -size=5G -runtime=15s -time_base -direct=1 -ioengine=libaio -numjobs=8 -group_reporting -bs=1m -rw=rw -rwmixwrite=30 -filename=/home/fio/a -iodepth=1

# 运行结果如下
# 其中第38行则是读取性能的测试结果,55行是写入的性能测试结果,附带了注释说明
disk_benchmark: (g=0): rw=randrw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=32
...
fio-3.7
Starting 8 processes
disk_benchmark: Laying out IO file (1 file / 5120MiB)
Jobs: 8 (f=8): [m(8)][100.0%][r=339MiB/s,w=144MiB/s][r=86.8k,w=36.0k IOPS][eta 00m:00s]
disk_benchmark: (groupid=0, jobs=8): err= 0: pid=64509: Tue Sep 16 15:11:50 2025
# 读取性能的测试结果在此,记录IOPS,和MB单位的353MB/s即可
read: IOPS=86.2k, BW=337MiB/s (353MB/s)(5053MiB/15002msec)
slat (nsec): min=1110, max=34081k, avg=51710.15, stdev=245614.51
clat (usec): min=229, max=36569, avg=2081.87, stdev=914.48
# 读取延迟取lat(total latency)总延迟的值即可,统一用微秒单位
# Windows按住Alt然后直接按小数字键盘0181即可输出µ
# Linux则是Ctrl+Shift+U输入00b5
# MACOS则是Option+m输出µ
lat (usec): min=237, max=37825, avg=2133.63, stdev=947.08
clat percentiles (usec):
| 1.00th=[ 545], 5.00th=[ 816], 10.00th=[ 1106], 20.00th=[ 1401],
| 30.00th=[ 1614], 40.00th=[ 1795], 50.00th=[ 1958], 60.00th=[ 2147],
| 70.00th=[ 2376], 80.00th=[ 2737], 90.00th=[ 3261], 95.00th=[ 3621],
| 99.00th=[ 4490], 99.50th=[ 4817], 99.90th=[ 5538], 99.95th=[ 5866],
| 99.99th=[21103]
bw ( KiB/s): min=39944, max=45384, per=12.50%, avg=43106.80, stdev=948.51, samples=240
iops : min= 9986, max=11346, avg=10776.67, stdev=237.13, samples=240
# 写入性能的测试结果在此,记录IOPS,和MB单位的353MB/s即可
write: IOPS=37.0k, BW=145MiB/s (152MB/s)(2171MiB/15002msec)
slat (nsec): min=1470, max=17704k, avg=54444.01, stdev=241994.82
clat (usec): min=150, max=37077, avg=1887.95, stdev=964.94
# 写入延迟取lat(total latency)总延迟的值即可,统一用微秒单位
# Windows按住Alt然后直接按小数字键盘0181即可输出µ
# Linux则是Ctrl+Shift+U输入00b5
# MACOS则是Option+m输出µ
lat (usec): min=153, max=37080, avg=1942.46, stdev=994.98
clat percentiles (usec):
| 1.00th=[ 400], 5.00th=[ 537], 10.00th=[ 676], 20.00th=[ 1156],
| 30.00th=[ 1418], 40.00th=[ 1614], 50.00th=[ 1795], 60.00th=[ 1991],
| 70.00th=[ 2212], 80.00th=[ 2540], 90.00th=[ 3130], 95.00th=[ 3556],
| 99.00th=[ 4490], 99.50th=[ 4817], 99.90th=[ 5604], 99.95th=[ 5997],
| 99.99th=[18744]
bw ( KiB/s): min=16736, max=19920, per=12.50%, avg=18519.40, stdev=504.91, samples=240
iops : min= 4184, max= 4980, avg=4629.82, stdev=126.23, samples=240
lat (usec) : 250=0.01%, 500=1.54%, 750=4.81%, 1000=4.07%
lat (msec) : 2=44.46%, 4=42.71%, 10=2.39%, 20=0.01%, 50=0.01%
cpu : usr=1.15%, sys=8.65%, ctx=508859, majf=0, minf=268
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=100.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.1%, 64=0.0%, >=64=0.0%
issued rwts: total=1293511,555725,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=32

Run status group 0 (all jobs):
READ: bw=337MiB/s (353MB/s), 337MiB/s-337MiB/s (353MB/s-353MB/s), io=5053MiB (5298MB), run=15002-15002msec
WRITE: bw=145MiB/s (152MB/s), 145MiB/s-145MiB/s (152MB/s-152MB/s), io=2171MiB (2276MB), run=15002-15002msec

Disk stats (read/write):
dm-2: ios=1288781/553752, merge=0/0, ticks=1713741/644122, in_queue=2391609, util=100.00%, aggrios=1293378/555710, aggrmerge=132/23, aggrticks=1658421/619009, aggrin_queue=2289296, aggrutil=99.74%
sda: ios=1293378/555710, merge=132/23, ticks=1658421/619009, in_queue=2289296, util=99.74% # 这里的util是硬盘负载,100%负载才说明榨干了硬盘性能

综合性能测试

使用CentOS 7.9.2009和GeekBench进行综合性能评估

下载地址 geekbench

1
2
3
4
5
6
7
8
9
10
11
# 解压下载的压缩包
tar -zxvf Geekbench-6.5.0-Linux.tar.gz

# 直接运行即可
./geekbench6

# 如果提示
/root/Geekbench-6.5.0-Linux/geekbench_avx2: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by /root/Geekbench-6.5.0-Linux/geekbench_avx2)

# 系统glibc版本过低,使用旧版本GeekBench
https://cdn.geekbench.com/Geekbench-5.5.1-Linux.tar.gz

稳定性测试

鉴于HPL测试本身就会使服务器CPU内存满载,所以直接在上文CPU测试的基础上直接变成重复执行即可做到稳定性测试,配合带外观察CPU温度内存等是否故障即可

1
2
3
4
# 循环运行100次
for i in {1..100};do "hpl代码";done
# 以我的AMD 9A14为例
for i in {1..100};do mpirun --allow-run-as-root -np 96 --map-by core --bind-to core ./xhpl && echo -e "\033[36;1m第 $i 次运行完成!";done

使用该脚本运行并将运行结果也进行统计,方便同时观察性能是否有波动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
for i in {1..1000}; do
echo -e "\033[34;1m=== 第 $i 次运行开始 ===\033[0m"

# 运行测试并保存输出到临时文件
# 记得将其替换为你自己的对应命令
mpirun --allow-run-as-root -np 96 --map-by core --bind-to core ./xhpl > hpl_run_$i.log 2>&1

# 提取关键指标
gflops=$(grep -A1 "T/V.*N.*NB.*P.*Q" hpl_run_$i.log | grep -v "T/V\|--" | awk '{print $NF}')
error=$(grep "||Ax-b||_oo" hpl_run_$i.log | awk -F'= ' '{print $2}' | awk '{print $1}')
status=$(grep "PASSED\|FAILED" hpl_run_$i.log | awk '{print $NF}')

# 输出结果
echo -e "Gflops: \033[32;1m$gflops\033[0m"
echo -e "Error: \033[33;1m$error\033[0m"
echo -e "Status: \033[36;1m$status\033[0m"
echo -e "\033[36;1m第 $i 次运行完成!\033[0m"
echo ""

# 可选:保存汇总结果到文件
echo "运行$i, $gflops, $error, $status" >> hpl_summary.csv

# 可选:删除临时日志文件以节省空间
# rm hpl_run_$i.log
done

# 最终汇总统计
echo -e "\033[35;1m=== 所有运行完成 ===\033[0m"
echo "总运行次数: 1000"
echo "PASSED 次数: $(grep -c "PASSED" hpl_summary.csv)"
echo "FAILED 次数: $(grep -c "FAILED" hpl_summary.csv)"

异常宕机BMC日志无参考价值时的排障思路

巡检发现异常宕机,带外日志仅有一条热复位的记录

BMC日志如下:

SYS_Restart 系统启动/重新启动 开始热复位 - 触发

仅有一条热复位记录,无物理按键记录,无操作系统发起重启记录

排障思路 命令
排查启动日志 `journalctl -b
排查内核缓冲区 dmesg --level=err,warn
排查是否有内核崩溃转储文件 ls -la /var/crash/
排查是否有硬件错误 `journalctl -k
排查watchdog是否触发 `journalctl -k
排查过热日志 `journalctl -k
检查内存不足事件 `journalctl -k
检查 CPU 或 I/O 阻塞 sar -q -f /var/log/sa/sa10
检查内存错误计数 `dmidecode -t memory
检查电源日志 `journalctl -k

记录一次分析[服务器SSD报故障随后自行恢复正常现象]

日常巡检时发现带外出现INTEL SSD故障告警,随后又自行恢复,间隔约30分钟,无人工介入。

smartctl -a /dev/sda

故障原因推测 排障思路
硬盘背板接触问题 检查smartctl中ID 199 UltraDMA CRC Error Count的值,是否存在CRC校验错误
NAND闪存寿命是否不足 检查smartctl中ID 233 Media Wearout Indicator的值
是否存在坏扇区 检查smartctl中ID 5 Reallocated sector ct的值
硬盘备用空间是否不足 检查smartctl中ID 232 Available Reservd space的值

实例:

1
2
3
Media Wearout Indicator: 当前值0 临界值100 - 健康
Reallocated Sector Count: 当前值0 临界值75 - 健康
Available Reservd Spare: 当前值0 临界值100 - 健康

关于DELL PowerEdge报错Correctable memory error logging disabled for a memory device的说明

关于DELL PowerEdge R740XD iDRAC报内存设备的可纠正内存错误日志记录已禁用问题的说明及解答

巡检发现:iDRAC报错Correctable memory error logging disabled for a memory

致电800-858-0613核实BIOS固件版本低于2.10,固件过旧,属于遗留问题

关于该报错的解释为:BIOS关闭了对于ECC纠错记录的保存,仅仅是没有记录进行了ECC纠错,实际上并不影响使用,可能存在的风险为:无法知晓ECC进行了多少次纠错。

2025-9-4已致电DELL800-858-0613核实,该信息可信