Я строю скриншоты сайта SaaS с Laravel.Я пытаюсь выполнить команду из нее, точнее сценарий nodejs;однако я продолжаю получать ошибку ProcessTimedOutException.Вот где происходит волшебство, посмотрите на строку take
method $process-run();
, которая выдает исключение:
<?php
namespace App\Logic;
use App\Logic\TimeHelper;
use App\UrlRequest;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
class Screenshot {
static function take(UrlRequest $urlRequest)
{
$name = self::generateName($urlRequest);
$command = self::buildScreenshotCommand($name, $urlRequest);
$startTime = TimeHelper::milliseconds();
$process = new Process($command);
$process->run();
$endTime = TimeHelper::milliseconds();
if (!$process->isSuccessful())
{
throw new ProcessFailedException($process);
}
$output = $process->getOutput();
if (trim($output) === '')
{
$urlRequest->successful = 1;
$file = self::uploadToS3($name);
$urlRequest->image_url = $file['url'];
$urlRequest->file_name = $name;
$urlRequest->file_size = $file['size'];
$urlRequest->time_it_took_to_take_screenshot_ms = $endTime - $startTime;
}
else
{
$urlRequest->error = $output;
}
if ($urlRequest->save())
{
return $urlRequest;
}
return false;
}
static function uploadToS3($name)
{
$name = 'screenshots/' . $name;
Storage::disk('s3')->put($name, Storage::disk('local')->get($name), ['visibility' => 'public']); // upload to S3
$fileSize = Storage::disk('local')->size($name);
Storage::disk('local')->delete($name);
return [
'url' => Storage::disk('s3')->url($name),
'size' => $fileSize
];
}
static function generateName($urlRequest)
{
$name = time() . rand(10000, 99999);
$extension = '.png';
if (isset($urlRequest->pdf) AND $urlRequest->pdf == 1)
{
$extension = '.pdf';
}
while (UrlRequest::where('file_name', '=', $name . $extension)->first())
{
$name = time() . rand(10000, 99999);
}
return $name . $extension;
}
static function buildScreenshotCommand($name, $urlRequest)
{
$command = 'cd ' . base_path() . ' && node puppeteer-screenshots-init.js ';
$command .= "--url={$urlRequest->url} ";
$fullPath = storage_path('app') . '/screenshots/' . $name;
$command .= "--path={$fullPath} ";
if (isset($urlRequest->pdf))
{
$command .= "--pdf=true ";
}
if (isset($urlRequest->viewport_width))
{
$command .= "--viewportWidth={$urlRequest->viewport_width} ";
}
if (isset($urlRequest->mobile))
{
$command .= '--mobile=true ';
}
if (isset($urlRequest->media_type_print))
{
$command .= '--mediaTypePrint=true ';
}
if (isset($urlRequest->user_agent))
{
$command .= "--userAgent={$urlRequest->user_agent}";
}
return $command;
}
}
Вот скрипт nodejs:
require('puppeteer-screenshots').init();
puppeteer-screenshots
(это скрипт nodejs, который я пытаюсь вызвать) - это пакет, который я написал для простого создания скриншотов с помощью пакета Google Puppeteer.Он с открытым исходным кодом и доступен в BitBucket, здесь есть ссылка на один-единственный файл.Строка в этом пакете, которая, кажется, вешает процесс, является строкой 138 или, если быть точным, такой:
await page.screenshot({path: config.path, fullPage: true});
когда эта строка удалена, процесс завершается, но, очевидно, не сохраняет скриншот.
Кроме того, я попытался переписать код с exec
вместо Process
, но в этом случае скрипт просто зависает и не завершается.
Кроме того, при выполненииточно такая же команда из командной строки все работает как положено.