PHP无法直接读取硬盘类型,需通过lsblk -d -o NAME,ROTA命令间接获取,ROTA值为0表示SSD/NVMe、1表示HDD,该方法不依赖SMART且无需root权限,但需确保PHP进程有exec权限及Web用户具备相应系统命令执行权限。

PHP 读不到硬盘类型,因为根本没权限访问硬件层
PHP 是运行在用户空间的脚本语言,它不直接和 SATA 控制器、NVMe 设备或 SMART 信息打交道。所谓“用 PHP 识别 SSD/HDD”,本质是调用系统命令间接获取结果,不是靠 fopen() 或 scandir() 看出来的。
常见错误现象:exec("lsblk -d -o NAME,ROTA") 返回空、超时、或只列出 loop 和 sr0 —— 很可能因为 PHP 进程被禁用了 exec,或 Web 服务器用户(如 www-data)没权限执行 lsblk、smartctl 等命令。
- 确认
disable_functions没禁掉exec、shell_exec、system - 检查 Web 用户能否在终端里手动运行
lsblk -d -o NAME,ROTA(注意不是 root) - 若用 Docker,容器需加
--cap-add=SYS_RAWIO才能读取部分设备信息
用 lsblk -o NAME,ROTA 判断旋转式硬盘最靠谱
ROTA(Rotational)字段是 Linux 内核暴露的最稳定指标:值为 1 表示传统 HDD(有马达),0 表示 SSD 或 NVMe(无机械部件)。它不依赖 SMART、不需 root 权限,且多数发行版默认可用。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 优先用
lsblk -d -o NAME,ROTA 2>/dev/null(-d只显示磁盘,不列分区;2>/dev/null忽略权限警告) - 解析输出时注意:设备名如
sda、nvme0n1后跟一个数字(0或1),别错当成分区号 - 某些 USB-SATA 转接桥会把 SSD 报成
ROTA=1,属硬件兼容性问题,无法靠 PHP 修复
示例输出:
sda 1 nvme0n1 0
smartctl -i 能补全型号但风险高
想确认具体型号(比如 “Samsung SSD 870 EVO”),得用 smartctl -i /dev/sda。但它需要设备支持 SMART、驱动加载正常,且多数系统要求 root 或 disk 组权限。
常见坑:
- Web 用户不在
disk组时,smartctl直接报错:Smartctl open device: /dev/sda failed: Permission denied - 某些主板 BIOS 关闭了 SATA 的 SMART 支持,
smartctl返回空或 “Read Device Identity failed” - 虚拟机里基本不可用 —— QEMU/KVM 默认不透传 SMART 信息
如果非要试,先确保:sudo usermod -a -G disk www-data,再重启 PHP-FPM 或 Apache。
别信 /sys/block/*/queue/rotational 文件内容
有人推荐读 /sys/block/sda/queue/rotational,文件内容确实是 0 或 1。但 PHP 用 file_get_contents() 读这个路径大概率失败,原因很实在:
- 该路径属于 sysfs,挂载权限常为
0555,仅允许 owner/group 执行open(),普通用户连stat()都被拒 - 即使读到,内容末尾带换行符,
trim()忘了就判断出错 - 某些 NVMe 设备(如老款 Intel 750)该文件不存在,导致
file_get_contents()返回 false
真要比对,不如老实用 lsblk —— 它内部也是读 sysfs,但做了降级兜底,容错强得多。
实际部署时,最易被忽略的是权限链:PHP 进程 → Web 用户组 → 命令可执行性 → 设备节点可访问性。少一环,ROTA 就永远是空的。



















