2024-07-28 05:00:06

PHP执行后台进程

我需要在用户操作时执行目录复制,但目录相当大,因此我希望能够在用户不知道完成复制所需时间的情况下执行这样的操作。

任何建议都将不胜感激。


当前回答

如果你只需要在后台做一些事情,而不需要PHP页面等待它完成,你可以使用另一个(后台)PHP脚本,用wget命令“调用”。当然,与系统上的任何其他PHP脚本一样,这个后台PHP脚本将以特权执行。

下面是一个在Windows上使用gnuwin32包中的wget的例子。

后台代码(文件test-proc-bg.php)为例…

sleep(5);   // some delay
file_put_contents('test.txt', date('Y-m-d/H:i:s.u')); // writes time in a file

前台脚本,调用…

$proc_command = "wget.exe http://localhost/test-proc-bg.php -q -O - -b";
$proc = popen($proc_command, "r");
pclose($proc);

你必须使用popen/pclose才能正常工作。

wget选项:

-q    keeps wget quiet.
-O -  outputs to stdout.
-b    works on background

其他回答

如果使用PHP,使用pcntl_fork有一个更简单的方法:

http://www.php.net/manual/en/function.pcntl-fork.php

来自PHP官方文档(php.net)

<?php
function execInBackground($cmd) {
    if (substr(php_uname(), 0, 7) == "Windows"){
        pclose(popen("start /B ". $cmd, "r")); 
    }
    else {
        exec($cmd . " > /dev/null &");  
    }
}
?>

我知道这是一个有100年历史的帖子,但不管怎样,我觉得它可能对某人有用。你可以在页面的某个地方放一个不可见的图像,指向需要在后台运行的url,就像这样:

<img src="run-in-background.php" border="0" alt="" width="1" height="1" />

如果希望通过PHP执行后台进程,请将命令的输出输送到/dev/null,并在命令末尾添加&。

exec("bg_process > /dev/null &");

注意,不能使用exec()的$output参数,否则PHP将挂起(可能直到进程完成)。

下面是在PHP中启动后台进程的函数。在大量阅读和测试不同的方法和参数之后,终于创建了一个在Windows上也能工作的程序。

function LaunchBackgroundProcess($command){
  // Run command Asynchroniously (in a separate thread)
  if(PHP_OS=='WINNT' || PHP_OS=='WIN32' || PHP_OS=='Windows'){
    // Windows
    $command = 'start "" '. $command;
  } else {
    // Linux/UNIX
    $command = $command .' /dev/null &';
  }
  $handle = popen($command, 'r');
  if($handle!==false){
    pclose($handle);
    return true;
  } else {
    return false;
  }
}

注意1:在windows上,不要像其他地方建议的那样使用/B参数。它强制进程运行与start命令本身相同的控制台窗口,导致进程被同步处理。要在单独的线程中(异步地)运行进程,请不要使用/B。

注2:如果命令是带引号的路径,则必须在start ""后加上空双引号。Start命令将第一个带引号的参数解释为窗口标题。