php无法直接识别电池供电状态,只能通过exec()调用系统命令或file_get_contents()读取/sys文件间接获取,但受限于运行环境、权限和硬件路径,实际部署中常因环境假设错误导致失败。

PHP 本身无法直接识别电池供电状态。它运行在 Web 服务器进程里,与笔记本电源管理硬件(如 ACPI、EC、SMI)完全隔离,没有系统级权限,也无对应扩展支持。
为什么 exec() 调用系统命令是唯一可行路径
PHP 只能通过外壳调用操作系统工具间接获取电源信息。这依赖于运行环境是否为真实 Linux/macOS 笔记本(非 Docker 容器、非 WSL2 默认配置、非共享主机),且 Web 服务器用户(如 www-data 或 _www)需有读取电源接口的权限。
- Linux 下主要靠
/sys/class/power_supply/目录下的文件,例如online(交流电是否接入)、status(Charging/Discharging/Full) - macOS 需用
pmset -g batt,输出含; discharging;或; charging;等标识 - Windows 不支持(
powercfg无法可靠返回实时电池状态,且 PHP 在 IIS/Apache on Windows 下通常无权调用)
file_get_contents() 直读 /sys 比 exec() 更快但限制更多
在 Linux 上,若 Web 进程用户能读取 /sys/class/power_supply/AC/online 和 /sys/class/power_supply/BAT0/status,可跳过 shell 启动开销,直接读取:
if (is_readable('/sys/class/power_supply/AC/online')) {
$ac = (int)file_get_contents('/sys/class/power_supply/AC/online'); // 1=插电, 0=电池
}
if (is_readable('/sys/class/power_supply/BAT0/status')) {
$status = trim(file_get_contents('/sys/class/power_supply/BAT0/status')); // Charging/Discharging/Full
}
- 路径不固定:部分设备用
BAT1、axp288_fuel_gauge或需遍历/sys/class/power_supply/下所有子目录找online - 权限问题常见:Apache/Nginx 默认以受限用户运行,
sysfs权限常为root:root 444,需sudo setfacl -m u:www-data:r /sys/class/power_supply/AC/online(不推荐生产环境开放) - 容器内基本失效:Docker 默认不挂载
/sys/class/power_supply,即使挂载也受限于 cgroup 权限
实际部署时最易踩的三个坑
不是代码写错,而是环境假设错了:
- 误以为
$_SERVER['HTTP_USER_AGENT']或客户端 JS 能传电源状态——浏览器明确禁止暴露该信息(安全策略) - 在 systemd 服务中运行 PHP CLI 脚本时能读
/sys,但换到 Apache mod_php 就失败——用户上下文不同,权限模型完全不同 - 测试时用
php -f script.php成功,上线后 Web 请求 500——SELinux 或 AppArmor 拦截了对/sys的访问,错误日志里只有Permission denied,没提示具体被哪个策略拦住
真要依赖电源状态做逻辑(比如省电模式降频渲染),得接受它是个「尽力而为」的信号:可能读不到、可能延迟几秒、可能在虚拟机里永远返回“插电”。别把它当开关用,更适合作为辅助提示或统计维度。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











