我有一个PHP脚本,该脚本需要调用shell脚本,但根本不关心输出。Shell脚本会进行许多SOAP调用,并且完成起来很慢,因此我不想在等待回复时放慢PHP请求。实际上,PHP请求应该能够退出而不终止shell进程。
我已经研究过的各种exec()
,shell_exec()
,pcntl_fork()
,等功能,但他们都不似乎提供正是我想要的。(或者,如果这样做,我不清楚如何做到。)有什么建议吗?
我有一个PHP脚本,该脚本需要调用shell脚本,但根本不关心输出。Shell脚本会进行许多SOAP调用,并且完成起来很慢,因此我不想在等待回复时放慢PHP请求。实际上,PHP请求应该能够退出而不终止shell进程。
我已经研究过的各种exec()
,shell_exec()
,pcntl_fork()
,等功能,但他们都不似乎提供正是我想要的。(或者,如果这样做,我不清楚如何做到。)有什么建议吗?
Answers:
如果它“不关心输出”,则脚本的exec是否不能使用&
后台进程来调用?
编辑 -结合@AdamTheHut对这篇文章发表的评论,您可以将其添加到对以下内容的调用中exec
:
" > /dev/null 2>/dev/null &"
这样会将stdio
(first >
)和stderr
(2>
)都重定向到/dev/null
后台并在后台运行。
还有其他方法可以执行相同的操作,但这是最简单的方法。
上述双重重定向的替代方法:
" &> /dev/null &"
&> /dev/null &
,如果使用xdebug,则不会生成日志。检查stackoverflow.com/questions/4883171/...
/dev/null
还是最好的做法,因为写入封闭的FD会导致错误,而尝试进行读取或写入/dev/null
只是简单地无声无息。
我曾经在这一点,因为它是真正开始独立的进程。
<?php
`echo "the command"|at now`;
?>
www-data
)没有使用权限,at
并且您无法对其进行配置,则可以尝试使用<?php exec('sudo sh -c "echo \"command\" | at now" ');
如果command
包含引号,请参阅escapeshellarg来避免让您头疼
echo "sudo command" | at now
和评论www-data
在了/etc/at.deny
对于所有Windows用户:我发现了一种运行异步PHP脚本的好方法(实际上,它几乎适用于所有内容)。
它基于popen()和pclose()命令。并且在Windows和Unix上都可以很好地工作。
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
myscript.js
而是写了node myscript.js
。也就是说:node是可执行文件,myscript.js是要执行的脚本。可执行文件和脚本之间存在巨大差异。
php artisan
只需在此处添加注释,这样就无需跟踪其为何无法与命令一起使用
在Linux上,您可以执行以下操作:
$cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);
这将在命令提示符处执行该命令,然后仅返回PID,您可以检查PID> 0以确保其正常工作。
这个问题类似:PHP是否具有线程?
action=generate var1_id=23 var2_id=35 gen_id=535
部分),则此答案将更易于阅读。另外,由于OP询问有关运行Shell脚本的问题,因此您不需要特定于PHP的部分。最终代码为:$cmd = 'nohup nice -n 10 /path/to/script.sh > /path/to/log/file.log & printf "%u" $!';
nice
也ionice
。
&
在后台运行前面的代码,然后printf
用于$!
包含PID 的变量的格式化输出
php-execute-a-background-process有一些很好的建议。我认为我的表现很好,但我有偏见:)
在Linux中,您可以通过在命令末尾附加与号来在新的独立线程中启动进程。
mycommand -someparam somevalue &
在Windows中,您可以使用“开始” DOS命令
start mycommand -someparam somevalue
start
在Windows上经过测试的命令,它不会异步运行...您能包括从中获取信息的源吗?
/B
参数。我在这里已经解释过:stackoverflow.com/a/34612967/1709903
正确的方法(!)
fork forks,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();
我用这个...
/**
* Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.
* Relies on the PHP_PATH config constant.
*
* @param string $filename file to execute
* @param string $options (optional) arguments to pass to file via the command line
*/
function asyncInclude($filename, $options = '') {
exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &");
}
(其中PHP_PATH
const定义为相似define('PHP_PATH', '/opt/bin/php5')
还是相似)
它通过命令行传递参数。要使用PHP读取它们,请参见argv。
我发现真正对我有用的唯一方法是:
shell_exec('./myscript.php | at now & disown')
shell_exec("/usr/local/sbin/command.sh 2>&1 >/dev/null | at now & disown")
,但得到的是:sh: 1: disown: not found
我还发现Symfony流程组件对此很有用。
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存储库中查看其工作方式。
proc_*
内部功能。
在不使用队列的情况下,可以这样使用proc_open()
:
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w") //here curaengine log all the info into stderror
);
$command = 'ping stackoverflow.com';
$process = proc_open($command, $descriptorspec, $pipes);
nice
并且ionice
防止shell脚本淹没您的系统(例如/usr/bin/ionice -c3 /usr/bin/nice -n19
)