Symfony - 进程运行抛出异常 - 在命令行上执行有效

Posted

技术标签:

【中文标题】Symfony - 进程运行抛出异常 - 在命令行上执行有效【英文标题】:Symfony - Process run throws exception - Executing on command line works 【发布时间】:2021-02-27 08:47:31 【问题描述】:

我在使用 LaTeX 生成 PDF 文件时遇到问题。该解决方案是使用 Laravel 框架(第 8 版)创建的。 我安装了一个新的“Windows 2019 Datacenter”服务器,以后应该在该服务器上托管该网站。在服务器上,生成 PDF 文件的命令失败。在我的本地开发机器(Windows 10)上,该命令运行良好。我在两台机器上运行 php 7.4 和 symfony/process v5.0。 这是创建命令的代码:

public function createPDFFromLaTexFile(string $fileName, string $outputDirectory, string $laTexFilePath) 
    $executionFile = str_replace('/','\\',env('PDFLATEXENGINE', 'C:/Program Files (x86)/MiKTeX 2.9/miktex/bin/pdflatex.exe'));
    $execute = [$executionFile, '-jobname=' .str_replace('.pdf','',$fileName), '-output-directory=' .str_replace("\\", "/", $outputDirectory), str_replace("\\", "/", str_replace(".tex","",$laTexFilePath))];
    $this->executeProcess($execute);


public function executeProcess($executionProcess) 
    $process = new \Symfony\Component\Process\Process($executionProcess);
    $process->run();
    if (!$process->isSuccessful()) 
        throw new \Symfony\Component\Process\Exception\ProcessFailedException($process);
    

错误日志是这样写的:

[2020-11-16 06:13:55] Live.ERROR:命令 "C:_Tools\texlive\2020\bin\win32\pdflatex.exe -jobname=m7EkMDQFggshi4gGpsDD "-output-directory=C:/_App/Live/public/Berichte/" "C:/_App/Live/app/Classes/Bericht/Tex/Working/m7EkMDQFggshi4gGpsDD"" 失败了。

退出代码:1(一般错误)

工作目录:C:_App\Live\public

输出: == ==============

错误输出:

================ "userId":1770,"exception":"[object] (Symfony\Component\Process\Exception\ProcessFailedException(code: 0):命令“C:\_Tools\texlive\2020\bin\win32\pdflatex.exe -jobname=m7EkMDQFggshi4gGpsDD "-output-directory=C:/_App/Live/public/Berichte/" "C:/_App/Live/app/Classes/Bericht/Tex/Working/m7EkMDQFggshi4gGpsDD"" 失败了。

退出代码:1(一般错误)

工作目录:C:\_App\Live\public

输出: == ==============

错误输出:

================ 在 C:\_App\Live\app\Classes\Documents\PDF.php:21) [stacktrace] #0 C:\_App\Live\app\Classes\Documents\PDF.php(13): App\Classes\Documents\PDF->executeProcess() #1 C:\_App\Live\app\Classes\Bericht\Bericht.php(239): App\Classes\Documents\PDF->createPDFFromLaTexFile() #2 C:\_App\Live\app\Http\Controllers\Bericht\BerichtController.php(51): App\Classes\Bericht\Bericht->pdfErzeugen() #3【内部函数】:App\Http\Controllers\Bericht\BerichtController->erzeugen() ...

奇怪的是,如果我在命令窗口本身运行命令,一切正常,并且 PDF 创建成功。

我不确定,为什么第一个参数没有被" 括起来。也许这可能是命令失败的原因?或者可能是运行命令的授权问题?

"C:\_Tools\texlive\2020\bin\win32\pdflatex.exe -jobname=m7EkMDQFggshi4gGpsDD "-output-directory=C:/_App/Live/public/Berichte/" "C:/_App/Live/app/Classes/Bericht/Tex/Working/m7EkMDQFggshi4gGpsDD""

更新


如果尝试使用 PHP proc_open() 命令创建文件。 这是代码:

$command = '';
$count = 0;
foreach ($executionProcess as $value) 
    if($count != 0) 
        $command .= " ";
    
    $command .= '"' .$value .'"';
    $count++;

$command .= " > nul";
\Log::info('Command: ' .$command);
$descriptorspec = array(
    0 => array("pipe", "r"),  
    1 => array("pipe", "w"), 
    2 => array("file", env('PROCOPENERRORLOG') ."procOpenErrors.log", "a")
);
$cwd = str_replace("\\", "/", base_path()) .'/app/Classes/Bericht/Tex/Working';
$env = null;
$process = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) 
    fwrite($pipes[0], '<?php print_r($_ENV); ?>');
    fclose($pipes[0]);
    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $return_value = proc_close($process);

同样的行为。如果在命令窗口中手动运行$command 变量中的命令,则正在生成 PDF。但是当我只运行代码时,没有生成 PDF 文件。到目前为止,我可以说,命令本身是正确的。也许这真的是服务器系统的权限问题?我有另一个想法,如果它可能是使用 PHP 7.4 32 位或 64 位的问题?目前安装的是x64版本的PHP 7.4。

【问题讨论】:

如果在服务器上激活了http-basic-auth,我的经历类似,你有http基本密码保护吗? 感谢您的提示,但实际上并非如此 - 仅启用了 Anonymous Authentication。但也许我需要在服务器环境中再次检查已安装的 Windows 功能。 【参考方案1】:

不幸的是,我无法找出 Symfony 进程在生成 PDF 文件时出现问题的原因,但我找到了解决方法。 我能够让我的proc_open 命令工作。这是现在可以使用的代码:

$command = '';
$count = 0;
foreach ($executionProcess as $value) 
    if($count != 0) 
        // parameters quoted:
        $command .= " ";
        $command .= '"' .$value .'"';
    
    else 
        // exe
        $command .= $value;
    
    $count++;

$command .= " > nul";
\Log::info('Command: ' .$command);
$descriptorspec = array(
    0 => array("pipe", "r"),  
    1 => array("pipe", "w"), 
    2 => array("file", env('PROCOPENERRORLOG') ."procOpenErrors.log", "a")
);
$cwd = str_replace("\\", "/", base_path()) .'/app/Classes/Bericht/Tex/Working';
$env = null;
$process = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) 
    fwrite($pipes[0], '<?php print_r($_ENV); ?>');
    fclose($pipes[0]);
    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $return_value = proc_close($process);

但我仍然感兴趣,为什么 Symfony 不工作。

【讨论】:

以上是关于Symfony - 进程运行抛出异常 - 在命令行上执行有效的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Symfony2 中抛出 403 异常?

symfony 在渲染模板的过程中抛出了异常

Symfony 3:渲染过程中抛出异常

Symfony/PhpUnit - 如何测试服务中是不是抛出异常

无法使用 Symfony 进程运行带有参数的 Laravel Artisan 命令 [重复]

Symfony Messenger:是不是可以在最后一次重试时不抛出异常?