2024-07-28 05:00:06

PHP执行后台进程

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

任何建议都将不胜感激。


当前回答

您是否可以安排派生一个单独的进程,然后在后台运行您的副本?我已经有一段时间没有使用PHP了,但是函数pcntl-fork看起来很有前途。

其他回答

PHP脚本不同于其他桌面应用程序开发语言。在桌面应用程序语言中,我们可以设置守护线程来运行后台进程,但在PHP中,当用户请求一个页面时,进程就会发生。但是,可以使用php脚本运行的服务器的cron作业功能来设置后台作业。

您可能想尝试将此附加到您的命令中

>/dev/null 2>/dev/null &

eg.

shell_exec('service named reload >/dev/null 2>/dev/null &');

老问题的新答案。使用这个库,下面的代码将生成一个异步/并行PHPThread来执行后台工作。

必须有pcntl, posix和套接字扩展名 在CLI模式下设计/测试。

EZ代码示例:

 function threadproc($thread, $param) {
 
    echo "\tI'm a PHPThread.  In this example, I was given only one parameter: \"". print_r($param, true) ."\" to work with, but I can accept as many as you'd like!\n";
 
    for ($i = 0; $i < 10; $i++) {
        usleep(1000000);
        echo "\tPHPThread working, very busy...\n";
    }
 
    return "I'm a return value!";
}
 

$thread_id = phpthread_create($thread, array(), "threadproc", null, array("123456"));
 
echo "I'm the main thread doing very important work!\n";
 
for ($n = 0; $n < 5; $n++) {
    usleep(1000000);
    echo "Main thread...working!\n";
}
 
echo "\nMain thread done working.  Waiting on our PHPThread...\n";
 
phpthread_join($thread_id, $retval);
 
echo "\n\nOur PHPThread returned: " . print_r($retval, true) . "!\n";

用任何方便的语言(php/bash/perl/etc)将进程作为服务器端脚本编写,然后从php脚本中的进程控制函数调用它。

该函数可能会检测是否使用标准io作为输出流,如果是,则设置返回值,如果不是,则结束

proc_close( proc_open( "./command --foo=1 &", array(), $foo ) );

我在命令行中使用“sleep 25s”作为命令快速测试了这个功能,效果非常好。

(答案在这里)

一个适用于Windows和Linux的解决方案。在我的github页面上找到更多信息。

function run_process($cmd,$outputFile = '/dev/null', $append = false){
                    $pid=0;
                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
                        $cmd = 'wmic process call create "'.$cmd.'" | find "ProcessId"';
                        $handle = popen("start /B ". $cmd, "r");
                        $read = fread($handle, 200); //Read the output 
                        $pid=substr($read,strpos($read,'=')+1);
                        $pid=substr($pid,0,strpos($pid,';') );
                        $pid = (int)$pid;
                        pclose($handle); //Close
                }else{
                    $pid = (int)shell_exec(sprintf('%s %s %s 2>&1 & echo $!', $cmd, ($append) ? '>>' : '>', $outputFile));
                }
                    return $pid;
            }
            function is_process_running($pid){
                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
                        //tasklist /FI "PID eq 6480"
                    $result = shell_exec('tasklist /FI "PID eq '.$pid.'"' );
                    if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
                        return true;
                    }
                }else{
                    $result = shell_exec(sprintf('ps %d 2>&1', $pid));
                    if (count(preg_split("/\n/", $result)) > 2 && !preg_match('/ERROR: Process ID out of range/', $result)) {
                        return true;
                    }
                }
                return false;
            }
            function stop_process($pid){
                    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
                            $result = shell_exec('taskkill /PID '.$pid );
                        if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
                            return true;
                        }
                    }else{
                            $result = shell_exec(sprintf('kill %d 2>&1', $pid));
                        if (!preg_match('/No such process/', $result)) {
                            return true;
                        }
                    }
            }