PHP exec执行date -s返回成功但未更新树莓派系统时间
问题
我在树莓派3的Linux系统上工作,apache2以root身份运行。现有一段PHP代码接收前端JS发送的时间,处理后通过exec执行date -s "YYYY-MM-DD HH:MM:SS"命令,返回的输出显示命令执行成功,但实际查看系统时间却未更新;而手动在终端执行完全相同的命令,系统时间能正常更新。
相关代码
PHP代码
<?php if (strtoupper($_SERVER['REQUEST_METHOD']) === 'POST') { if (isset($_POST['datetime'])) { $datetime = htmlspecialchars($_POST['datetime']); $datetime[10] = ' '; $datetime = substr($datetime, 0, 19); die (json_encode(exec('date -s' . escapeshellarg($datetime)))); } }
JS代码
function syncTime() { let data = new FormData(); data.set("datetime", new Date().toISOString()); fetch("datetime.php", { method: 'POST', body: data }) .then(response => response.json()) .then(json => console.log(json)); .catch(err => console.log('Request Failed', err)); }
执行细节
- 发送的时间格式:
2023-09-08T20:49:28.696Z - PHP处理后格式:
2023-09-08 20:49:28 - 执行的命令:
date -s "2023-09-08 20:49:28" - PHP返回输出:
Fri Sep 8 20:49:28 UTC 2023 - 实际系统时间:
Thu Jan 1 08:34:07 UTC 1970 - 手动执行命令可正常更新时间
原因分析与解决办法
1. exec()返回特性导致的判断误差
exec()仅返回命令执行的最后一行输出,这个输出不代表命令一定执行成功。即使date命令因权限、系统限制等原因未修改时间,依然可能返回格式化后的时间字符串,造成“执行成功”的假象。
修改PHP代码,捕获命令的退出状态码来确认真实执行结果:
<?php if (strtoupper($_SERVER['REQUEST_METHOD']) === 'POST') { if (isset($_POST['datetime'])) { $datetime = htmlspecialchars($_POST['datetime']); $datetime[10] = ' '; $datetime = substr($datetime, 0, 19); $command = 'date -s' . escapeshellarg($datetime); $output = []; $exitCode = 0; exec($command, $output, $exitCode); echo json_encode([ 'output' => implode("\n", $output), 'exit_code' => $exitCode, 'current_system_time' => exec('date') ]); exit; } }
退出码为0表示执行成功,非0则为失败,以此判断命令是否真的生效。
2. 系统自动时间同步服务的干扰
树莓派默认可能开启systemd-timesyncd或ntpd这类时间同步服务,它们会定期将系统时间同步到网络时间服务器。即使你用date -s修改了时间,同步服务很快会把时间拉回原状态。
临时停止同步服务测试:
sudo systemctl stop systemd-timesyncd
修改时间后若能保持,则说明是同步服务的问题。若需长期通过PHP修改时间,要么禁用自动同步,要么调整同步服务配置,允许手动时间调整。
3. 系统安全模块的隐性限制
即使apache2以root身份运行,部分Linux系统的apparmor或selinux安全模块,可能限制进程修改系统时间。
检查安全模块状态:
- 检查apparmor:
sudo aa-status - 检查selinux:
getenforce
若发现相关限制,需调整对应规则,允许apache进程执行修改时间的操作。
4. 硬件时钟未同步(次要可能性)
date -s修改的是系统软件时钟,若硬件时钟(RTC)未同步,重启后时间会回滚,但这不会导致修改后立即查看时间无变化。可执行hwclock -w将系统时钟同步到硬件时钟,避免后续重启时间异常。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

