【问题标题】:PHP Process ID and uniquePHP 进程 ID 和唯一性
【发布时间】:2013-07-26 06:17:57
【问题描述】:

我想在后台运行一个 php 脚本并将其 PID 存储在数据库中。这样我就可以检查特定脚本是否正在运行(稍后)。

我们可以使用getmypid来获取当前的PID。

但根据 PHP 手册

进程 ID 不是唯一的,因此它们是弱熵源。我们 建议不要在依赖安全的上下文中依赖 pid。

...我不能依赖 PID。

我的第二个想法是将进程创建时间存储到数据库中。

如何获取当前脚本的创建时间?以后如何与任务列表进行比较以检查特定脚本是否正在运行?

我在一个共享主机上运行,​​windows/linux 环境。

【问题讨论】:

  • 在安全相关上下文中关于 PID 的评论是指“熵源”和srand(getmypid()); 等情况。您似乎需要某种进程监控机制,如 daemontools、perp、minit 等:这些机制中的大多数会分叉出一个子进程并监视文件描述符和信号以查看子进程是否还活着。根据您的想法,您必须解决时间问题、权限等问题(以确定当前具有您存储在数据库中的 PID 的进程是否实际上是同一个进程)。
  • kr.github.io/beanstalkd(这是一个作业队列)顺便说一句,它使用了一些简洁的东西:接受给定作业的进程必须向队列报告它仍然处于活动状态并且正在处理该任务。你也可以在php中实现类似的东西:如果进程本身没有及时报告给定的标识符,你可以认为该任务被中断/失败等。观察产生/分叉子进程的信号/文件描述符仍然更容易恕我直言。
  • 可能有用:github.com/CHH/kue - A minimalistic, generic and framework independent interface to job queues
  • @akira 非常感谢 .. 让我检查一下 ..

标签: php


【解决方案1】:

来自php.net/getmypid

稍作修改即可禁用非 cli 访问。

可以使用/usr/bin/php script.php 执行脚本。

另外使用nohup /usr/bin/php script.php > nohup.out & 在后台启动nohup 进程。

#!/usr/bin/php 
<?php 

if ( PHP_SAPI !== 'cli' ) {
    die( "Cmd line access only!\n" );
}

define( 'LOCK_FILE', "/var/run/".basename( $argv[0], ".php" ).".lock" );  // can also use /tmp
if( isLocked() ) die( "Already running.\n" ); 

# The rest of your script goes here.... 
echo "Hello world!\n"; 
sleep(30); 

unlink( LOCK_FILE ); 
exit(0); 

function isLocked() 
{ 
    # If lock file exists, check if stale.  If exists and is not stale, return TRUE 
    # Else, create lock file and return FALSE. 

    if( file_exists( LOCK_FILE ) ) 
    { 
        # check if it's stale 
        $lockingPID = trim( file_get_contents( LOCK_FILE ) ); 

       # Get all active PIDs. 
        $pids = explode( "\n", trim( `ps -e | awk '{print $1}'` ) ); 

        # If PID is still active, return true 
        if( in_array( $lockingPID, $pids ) )  return true; 

        # Lock-file is stale, so kill it.  Then move on to re-creating it. 
        echo "Removing stale lock file.\n"; 
        unlink( LOCK_FILE ); 
    } 

    file_put_contents( LOCK_FILE, getmypid() . "\n" ); 
    return false; 

} 
?>

【讨论】:

    【解决方案2】:

    这完全取决于您对目标机器的访问级别。您可以使用 PHP CLI,存储 PID(它们在特定时间点是唯一的,因此您不会有 2 个具有相同 PID 的进程在运行)并在 ps -ax 的输出中使用 grep 来检查它们是否正在运行。如果没有 - 从数据库中删除它们,这样就不会出现相同 PID 的问题。

    【讨论】:

    • 不是立即的。您将能够在 DB 中将其标记为已完成。也包括日期/时间以进行区分。
    【解决方案3】:

    您可以尝试将 PID 与另一个 id 一起使用,例如:

    如果您有一个使用文件 id = 327 的压缩作业,请尝试存储 {PID}327,并检查此特定作业是否仍在运行。

    即使 PID 被重用,您也不会存储 id 为 327 的 PID,或者如果您使用这个特定的 id 327 重新启动压缩过程,PID 可能会改变。

    但是,为避免获得与此 id 327 相同的 PID,您必须先检查您的数据库,然后在组合 id 的末尾添加一个计数器,例如 {PID}327_1。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-13
      • 1970-01-01
      • 2011-07-29
      • 2011-08-27
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      相关资源
      最近更新 更多