You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 03:53:12