我有一个PHP脚本,需要调用shell脚本,但根本不关心输出。shell脚本执行了许多SOAP调用,完成起来很慢,因此我不想在PHP请求等待应答时降低它的速度。事实上,PHP请求应该能够在不终止shell进程的情况下退出。
我已经研究了各种exec()、shell_exec()、pcntl_fork()等函数,但它们似乎都不能提供我想要的东西。(或者,即使他们这样做,我也不清楚是如何做到的。)有什么建议吗?
我有一个PHP脚本,需要调用shell脚本,但根本不关心输出。shell脚本执行了许多SOAP调用,完成起来很慢,因此我不想在PHP请求等待应答时降低它的速度。事实上,PHP请求应该能够在不终止shell进程的情况下退出。
我已经研究了各种exec()、shell_exec()、pcntl_fork()等函数,但它们似乎都不能提供我想要的东西。(或者,即使他们这样做,我也不清楚是如何做到的。)有什么建议吗?
当前回答
在linux上,您可以执行以下操作:
$cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);
这将在命令提示符处执行命令,然后只返回PID,您可以检查> 0以确保它工作正常。
这个问题类似:PHP有线程吗?
其他回答
我用at来做这个,因为它真的开始了一个独立的过程。
<?php
`echo "the command"|at now`;
?>
做这件事的正确方法是
叉() 塞西德() execve()
Fork Fork, setsid告诉当前进程成为主进程(没有父进程),execve告诉调用进程被被调用进程取代。这样父母可以在不影响孩子的情况下退出。
$pid=pcntl_fork();
if($pid==0)
{
posix_setsid();
pcntl_exec($cmd,$args,$_ENV);
// child becomes the standalone detached process
}
// parent's stuff
exit();
使用命名fifo。
#!/bin/sh
mkfifo trigger
while true; do
read < trigger
long_running_task
done
然后,每当您想启动长时间运行的任务时,只需向触发器文件写入一个换行符(非阻塞)。
只要您的输入小于PIPE_BUF,并且它是一个单独的write()操作,您就可以将参数写入fifo并在脚本中显示为$REPLY。
我不能使用>/dev/null 2>/dev/null &在Windows上,所以我使用proc_open代替。我在Windows 11上运行PHP 7.4.23。
这是我的代码。
function run_php_async($value, $is_windows)
{
if($is_windows)
{
$command = 'php -q '.$value." ";
echo 'COMMAND '.$command."\r\n";
proc_open($command, [], $pipe);
}
else
{
$command = 'php -q '.$value." > /dev/null 2>/dev/null &";
echo 'COMMAND '.$command."\r\n";
shell_exec($command);
}
}
$tasks = array();
$tasks[] = 'f1.php';
$tasks[] = 'f2.php';
$tasks[] = 'f3.php';
$tasks[] = 'f4.php';
$tasks[] = 'f5.php';
$tasks[] = 'f6.php';
$is_windows = true;
foreach($tasks as $key=>$value)
{
run_php_async($value, $is_windows);
echo 'STARTED AT '.date('H:i:s')."\r\n";
}
在每个要执行的文件中,我放了这个延迟:
<?php
sleep(mt_rand(1, 10));
file_put_contents(__FILE__.".txt", time());
所有文件都是异步执行的。
我还发现Symfony Process Component在这方面很有用。
use Symfony\Component\Process\Process;
$process = new Process('ls -lsa');
// ... run process in background
$process->start();
// ... do other things
// ... if you need to wait
$process->wait();
// ... do things after the process has finished
在GitHub回购中查看它是如何工作的。