在后台执行 Laravel/Symfony/Artisan 命令

Posted

技术标签:

【中文标题】在后台执行 Laravel/Symfony/Artisan 命令【英文标题】:Execute Laravel/Symfony/Artisan Command in Background 【发布时间】:2015-11-19 21:59:39 【问题描述】:

我需要在后台执行一个 Laravel 长时间运行的进程来使用 Twitter 流 API。实际上,我需要运行的 php artisan CLI 命令是

nohup php artisan startStreaming > /dev/null 2>&1 &

如果我自己在命令行中运行它,它会完美运行。

我的想法是我可以单击网站上的一个按钮,该按钮通过执行长时间运行的 artisan 命令开始流式传输(需要在后台运行,因为 Twitter 流式传输连接永远不会结束)。通过命令行运行正常。

但是,以编程方式调用命令不起作用。我尝试通过 callSilent() 从另一个命令静默调用它,并尝试使用 Symfony\Component\Process\Process 运行 artisan 命令或运行运行上述命令的 shell 脚本,但我无法弄清楚.

更新 如果我将打开流连接的命令排队,它会导致队列工作人员的进程超时

我实际上需要一种从 PHP 类/脚本运行上述命令的方法,但 PHP 脚本不等待该命令的完成/输出。

帮助非常感谢

【问题讨论】:

命令进程运行多长时间?是无限期的吗? 使用Artisan::call('startStreaming');在路由上执行不行吗? 否,因为打开流的命令永远不会“完成”,因为流无限期地保持打开状态,所以我永远无法真正向浏览器返回响应 您可以尝试使用pcntl_fork() 之类的东西来创建一个新的子进程,以便在其中运行 artisan 命令。 设置Process的第二个参数已经破解了,你要回答我接受吗? 【参考方案1】:

默认情况下,Symfony 进程组件将在当前工作目录getcwd() 中执行提供的命令。

getcwd() 返回的值不会是 Laravel 安装目录(包含 artisan 的目录),因此该命令很可能会返回 artisan: command not found 消息。

Process Component documentation 中没有提到它,但如果您查看class file,我们可以看到该构造允许我们提供目录作为第二个参数。

public function __construct(
    $commandline, 
    $cwd = null, 
    array $env = null, 
    $input = null, 
    $timeout = 60, array 
    $options = array())

您可以通过在初始化类时提供第二个参数来异步执行您想要的命令:

use Symfony\Component\Process\Process;

$process = new Process('php artisan startStreaming > /dev/null 2>&1 &', 'path/to/artisan'); 
$process->start();

【讨论】:

Running Artisan queue 确实成功运行了该命令,但是它阻止了该队列工作人员。因为 Artisan 命令运行的过程实际上永远不会完成(Twitter 流 API 是一个持久的永无止境的连接)。最终,该过程将超时 可能应该说明该过程无限期运行,而不是在您的原始问题中使用“长期运行”一词。 @Jeemusu 你能告诉我这里的“路径/到/工匠”是什么吗?我已将 laravel 项目安装目录的路径作为第二个参数?我收到此错误消息:无法打开输入文件:工匠 @Jeemusu 你可以使用 base_path() link【参考方案2】:

如何通过 Laravel 内置队列对命令的执行进行排队?

【讨论】:

不需要排队,因为问题在于命令未在后台执行,这会导致队列工作人员在执行作业时超时。使用 Symphony Process 组件使我能够在后台运行命令【参考方案3】:

我遇到了同样的问题,我用纯 php 解决了这个问题并使用了 proc_open 函数。

我的代码:

$descriptionProcOpen = [
    ["pipe", "r"],
    ["pipe", "r"],
    ["pipe", "r"]
];

proc_open("php " . base_path() . "/artisan your:command $argument", $descriptionProcOpen, $pipes);

【讨论】:

以上是关于在后台执行 Laravel/Symfony/Artisan 命令的主要内容,如果未能解决你的问题,请参考以下文章

shell脚本定时后台执行

IOS的后台执行

如何在后台执行限制中生存

应用如何在后台执行

Linux在后台执行命令或脚本

在执行另一个块之前执行所有后台线程