【问题标题】:Is it possible within a long running PHP process to capture/handle/detect when the system time has changed?是否可以在长时间运行的 PHP 进程中捕获/处理/检测系统时间何时更改?
【发布时间】:2019-01-10 23:44:57
【问题描述】:

老读者,第一次发帖……

我在 Ubuntu 16.04 机器上托管了一个长期运行的 PHP 7 进程。它以不同的间隔执行多种功能;每 2m 一次,一些曾经 15m 等。我根据当前纪元时间触发这些函数,比较为每个函数维护的“next_time_to_run”。每次执行函数时都会重新计算 next_time_to_run。例如,如果一个函数每 2 分钟执行一次,那么当它被触发时,它只需将当前 epoch 时间加 120 即可找到下一个触发时间。

我最近遇到了一个问题,即 NTP 进程在我的进程运行时显着改变了系统时间。正如你可能想象的那样,这让我的日程安排变得一头雾水。 (哦,是的,我说'tizzy'

我的问题是——是否可以注册回调/事件处理程序/等。当系统时间(纪元)改变时会被触发吗?顺便说一句,系统时钟保持在 UTC。

感谢 oh-great-and-glorious-StackOverflow-hive-mind!

$dothing1time = time() + 120;
$dothing2time = time() + 3600;

while(1) {
    $now = time();
    if( $now >= $dothing1time ) { dothing1(); $dothing1time = $now + 120; }

    if( $now >= $dothing2time ) { dothing2(); $dothing2time = $now + 3600; }

    sleep( 30 );
}

【问题讨论】:

  • 最丑陋和快速的解决方案:1) 禁用 ntp 守护进程,2) 每天(每周/每月)检查一次长脚本中的时间 2) 直接从脚本启动 ntp 更新 3) 检查时间再找差异
  • 没有内置的时间变化通知机制。我只是将函数拆分为单独的命令,并使用自己的 cron 运行每个命令——完全消除了代码中的所有时间管理。
  • 取决于您是否只想probe for adjustements 或需要real notifications(即使使用 FFI 在 PHP 中也不可能)。真正的问题是为什么这个长时间运行的脚本会实现延迟。多个 cron 作业不是更简单吗?
  • 这些功能确实需要与“现实世界”保持同步,因此禁用 NTP 是不可行的。也许偶尔运行它。
  • 还有更多的定时函数在运行,它会监控其他“东西”,因此以 cron 方式运行并不实用(某些函数需要与其他函数协调,等等)

标签: php linux ubuntu ntp


【解决方案1】:
<?php

ignore_user_abort ( TRUE );

set_time_limit ( 0 );

$dothing1time = 120;

$dothing2time = 3600;

$now = 0;

$tic = 0;

$toc = 0;

while ( 1 )
{

    if ( $now >= $dothing1time )
    {
        dothing1 ( ++$tic );

        $dothing1time = $now + 120;
    }

    if( $now >= $dothing2time )
    {
        dothing2 ( ++$toc );

        $dothing2time = $now + 3600;
    }

    sleep( 30 );

    $now += 30;
}


function dothing1 ( $tic )
{
    file_put_contents ( './dothing1.txt', $tic );
}

function dothing2 ( $toc )
{
    file_put_contents ( './dothing2.txt', $toc );
}

?>

【讨论】:

  • 是的,我喜欢这个。我可以将此方法用于不需要同步到特定壁时间的位。非常感谢!
【解决方案2】:

要回答您的具体问题,“否”。据我所知,没有 timechanged 事件可以附加监听器。

不幸的是,鉴于您当前的程序架构,我怀疑一个强大的解决方案将需要一个单调且均匀增加的时钟——这是我们软件和用户空间人员认为理所当然的事情。更不幸的是,没有一个 PHP 函数可以保证您“滥用”time() 函数的单调且均匀增加的属性。

但是,有几种可能性。

  • PHP 原生解决方案可能会使用一个简单地循环、休眠和递增计数器的线程。我将线程实例化和其他样板作为“读者练习”,但示例线程内核可能是:

    while ( $threadAlive ) {
      if ( 0 == sleep( 1 ) )
        $programMonotonicClock++;
    }
    

    您必须进行测试,因为这也可能成为 NTP 时间更改事件的受害者,具体取决于 PHP 中如何实现 sleep()

  • 另一个可能更强大的选项是 exploit Linux's jiffy count 为您的程序“时钟”。 Jiffies 是自计算机首次启动以来的 CPU 时钟周期数。同样,将进程包装和进一步解析作为“读者练习”,考虑使用这个 shell 命令来获取当前的 jiffy 计数:

    $ grep ^jiff /proc/timer_list | head -1
    

现在,您可以自己检测时间是否发生了变化(通过与您的程序计数器/jiffy 计数的已知值和最近值进行比较),或者只是将程序计数器/jiffy 计数视为您的新程序时钟源。

【讨论】:

  • 这与上面的方法类似;使用我自己的“时钟”来确定间隔,而不是与系统时间进行比较。 Jiffies 是一个新颖的理想,我忘记了它们的存在,但我想我会为基于间隔的“dothings”选择更简单的解决方案。谢谢!
  • 虽然,我现在关心的是 sleep() 的 PHP 实现。我将避免任何递归导致对 sleep() 失去睡眠的引用。 ;-)
猜你喜欢
  • 1970-01-01
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多