Php 当通过exec运行命令而不将其发送到后台时,Laravel挂起

Php 当通过exec运行命令而不将其发送到后台时,Laravel挂起,php,laravel,google-chrome,pdf,exec,Php,Laravel,Google Chrome,Pdf,Exec,我有一个奇怪的问题,我已经被困了好几天了。我正在尝试使用chrome headless通过此命令在Laravel应用程序中生成pdf google chrome——无头——禁用gpu——打印到pdf=outputfile.pdfhttp://localurl/pdf-html 该命令基本上以无头模式打开chrome,导航到给定的url,并将其打印为pdf格式,将文件保存在指定位置。这个命令在我的系统外壳(我使用的是Ubuntu18.04)中运行时效果非常好。现在,我的问题出现在尝试从Larave

我有一个奇怪的问题,我已经被困了好几天了。我正在尝试使用chrome headless通过此命令在Laravel应用程序中生成pdf
google chrome——无头——禁用gpu——打印到pdf=outputfile.pdfhttp://localurl/pdf-html

该命令基本上以无头模式打开chrome,导航到给定的url,并将其打印为pdf格式,将文件保存在指定位置。这个命令在我的系统外壳(我使用的是Ubuntu18.04)中运行时效果非常好。现在,我的问题出现在尝试从Laravel控制器运行相同的命令时,我尝试过exec、shell_exec、system和PASSTRU,所有这些都给了我相同的问题。如果通过在命令末尾添加
>tmpfile 2>&1&
来运行命令而不重定向输出并在后台运行进程,则请求将挂起。在后台运行该命令通常不会有问题,除非我需要完成该命令才能将文件作为下载发送回客户端。通过在后台运行它,这基本上是异步执行的,我无法知道进程何时结束(或等待它结束),然后在响应上以加载方式发送文件

我尝试过其他的选择,但都没有用。我试过使用Laravel附带的,但也失败了。我尝试过使用node.js脚本,而不是运行google chrome命令,它包含puppeter文档中的代码(顺便说一句,直接在我的系统shell中运行时也可以工作),但是从Laravel运行时会抛出导航超时错误异常

最后,我用以下代码创建了一个简单的php文件:

<?php

$chromeBinary = 'google-chrome';
$pdfRenderUrl = "http://localhost:8000/pdf-html";
$fileName = 'invoice.pdf';
$outputDirectory = "/path/to/my/file/" . $fileName;

$command = sprintf(
    '%s --headless --disable-gpu --print-to-pdf=%s %s',
    escapeshellarg($chromeBinary),
    escapeshellarg($outputDirectory),
    escapeshellarg($pdfRenderUrl)
);
exec( $command  );
echo ( file_exists("/path/to/my/file/" . $fileName) ? 'TRUE' : 'FALSE');

?>

当从shell运行时,代码运行得很好,比如
php thefile.php
printing TRUE,这意味着exec中的命令被启动,结束后文件就存在了;这正是我在Laravel上使用的代码,除了上面提到的,当我将进程发送到后台时,它才起作用。 有人能在这里给我留言吗?谢谢

编辑:@namoshek感谢您的快速回复,如果我没有说清楚,我很抱歉。问题是等待时间不长,也许我可以接受。问题是exec永远不会完成,我最终不得不强制终止进程(或者exec,或者任何其他替代方案,它们都会永远完全冻结请求,但进程因抛出TimeoutException而失败的情况除外)。我正在使用postman查询端点。前端是一个Angular应用程序,这意味着发票下载请求最终将异步进行。此外,任务本身不是一个长时间运行的任务,事实上它完成得相当快。在我看来,使用轮询策略或通知系统似乎不是一个可行的解决方案。想象一下,一个带有下载按钮的应用程序要下载一个简单的文档,你必须单击该按钮,然后等待应用程序通过电子邮件(或其他方式)通知你文档已准备就绪。如果这是一个更复杂的过程,我可以理解,但下载文档似乎是件小事。但让我感到困惑的是,为什么从php脚本运行任务可以按我希望的方式(同步)工作,而我不能在laravel控制器上复制该行为

编辑:我也试过使用,顺便说一句,也失败了。Browsershot提供了一种使用Process在幕后与傀儡演员交互并生成pdf文件的方法。即使它是一个外部程序,在我看来,我得到的行为仍然不正常,我应该能够获得下载,即使请求需要10秒才能完成,因为它同步执行外部程序。但在我的例子中,由于超时错误,它失败了


编辑:所以过了一会儿,我发现了服务器挂断的明显原因。问题是我使用的是artisan的开发服务器。起初,这对我来说似乎不是一个问题,但似乎artisan无法处理这个负载。在我正在实现的功能中,我正在执行对特定端点的请求,我们称之为端点1,以生成pdf,此端点上的代码触发外部命令,当同步执行时,表示端点1中的代码正在等待外部命令完成。外部命令反过来需要浏览到同一服务器上的端点2,端点2包含一个html视图,其中的内容将放在pdf上,因为服务器仍在等待端点1返回外部命令,因此端点2没有响应,这显然造成了artisan的开发服务器无法处理的循环。问题是我做了一个快速搜索,并没有发现任何迹象表明artisan的开发服务器存在这种缺陷。我将环境迁移到Apache只是为了测试我的理论,它成功了,不过应该注意的是,完成请求需要很长的时间(大约10-20秒)。到目前为止,这似乎是唯一合理的解释,解释为什么会发生这样的问题。如果有人知道我可以如何改进此请求的性能,或者有人可以对原始问题提供更好的解释,我将不胜感激

我没有真正理解您的要求,因为您似乎已经了解,如果同步运行,执行长时间运行的任务(如创建快照)将阻止请求。使用其他软件,如Puppeter,不会改变这一点。如果您的请求需要等待此过程的结果返回,那么让请求更快返回的唯一方法就是加快任务本身。这很可能是不可能的

因此,基本上只剩下两个选项:使用长等待时间(如果您希望同步执行任务)或异步执行请求/任务。后者可以通过以下方式实现: