mirror of
https://github.com/getgrav/grav-plugin-admin.git
synced 2025-11-02 11:26:04 +01:00
improvements to logging and command calling
This commit is contained in:
@@ -23,6 +23,8 @@ use Grav\Common\Recovery\RecoveryManager;
|
|||||||
use Grav\Common\Upgrade\SafeUpgradeService;
|
use Grav\Common\Upgrade\SafeUpgradeService;
|
||||||
use Grav\Common\Utils;
|
use Grav\Common\Utils;
|
||||||
use Grav\Installer\Install;
|
use Grav\Installer\Install;
|
||||||
|
use Symfony\Component\Process\PhpExecutableFinder;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use ZipArchive;
|
use ZipArchive;
|
||||||
@@ -65,6 +67,8 @@ class SafeUpgradeManager
|
|||||||
private $progressDir;
|
private $progressDir;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $jobsDir;
|
private $jobsDir;
|
||||||
|
/** @var \Psr\Log\LoggerInterface|null */
|
||||||
|
private $logger;
|
||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
private $jobId;
|
private $jobId;
|
||||||
/** @var string|null */
|
/** @var string|null */
|
||||||
@@ -83,6 +87,7 @@ class SafeUpgradeManager
|
|||||||
{
|
{
|
||||||
$this->grav = $grav ?? Grav::instance();
|
$this->grav = $grav ?? Grav::instance();
|
||||||
$this->recovery = $this->grav['recovery'];
|
$this->recovery = $this->grav['recovery'];
|
||||||
|
$this->logger = $this->grav['log'] ?? null;
|
||||||
|
|
||||||
$locator = $this->grav['locator'];
|
$locator = $this->grav['locator'];
|
||||||
$this->progressDir = $locator->findResource('user://data/upgrades', true, true);
|
$this->progressDir = $locator->findResource('user://data/upgrades', true, true);
|
||||||
@@ -102,9 +107,11 @@ class SafeUpgradeManager
|
|||||||
Folder::create($jobDir);
|
Folder::create($jobDir);
|
||||||
$this->jobManifestPath = $jobDir . '/' . self::JOB_MANIFEST;
|
$this->jobManifestPath = $jobDir . '/' . self::JOB_MANIFEST;
|
||||||
$this->progressPath = $jobDir . '/' . self::JOB_PROGRESS;
|
$this->progressPath = $jobDir . '/' . self::JOB_PROGRESS;
|
||||||
|
$this->log(sprintf('Safe upgrade job %s activated', $this->jobId), 'debug');
|
||||||
} else {
|
} else {
|
||||||
$this->jobManifestPath = null;
|
$this->jobManifestPath = null;
|
||||||
$this->progressPath = $this->progressDir . '/' . self::PROGRESS_FILENAME;
|
$this->progressPath = $this->progressDir . '/' . self::PROGRESS_FILENAME;
|
||||||
|
$this->log('Safe upgrade job context cleared', 'debug');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,22 +125,28 @@ class SafeUpgradeManager
|
|||||||
return $this->jobsDir . '/' . $jobId;
|
return $this->jobsDir . '/' . $jobId;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function escapeArgument(string $arg): string
|
|
||||||
{
|
|
||||||
if (Utils::isWindows()) {
|
|
||||||
$escaped = str_replace('"', '""', $arg);
|
|
||||||
|
|
||||||
return '"' . $escaped . '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
return escapeshellarg($arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function generateJobId(): string
|
protected function generateJobId(): string
|
||||||
{
|
{
|
||||||
return 'job-' . gmdate('YmdHis') . '-' . substr(md5(uniqid('', true)), 0, 8);
|
return 'job-' . gmdate('YmdHis') . '-' . substr(md5(uniqid('', true)), 0, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function log(string $message, string $level = 'info'): void
|
||||||
|
{
|
||||||
|
if (!$this->logger) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (method_exists($this->logger, $level)) {
|
||||||
|
$this->logger->$level('[SafeUpgrade] ' . $message);
|
||||||
|
} else {
|
||||||
|
$this->logger->info('[SafeUpgrade] ' . $message);
|
||||||
|
}
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
// ignore logging errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function writeManifest(array $data): void
|
protected function writeManifest(array $data): void
|
||||||
{
|
{
|
||||||
if (!$this->jobManifestPath) {
|
if (!$this->jobManifestPath) {
|
||||||
@@ -160,6 +173,9 @@ class SafeUpgradeManager
|
|||||||
|
|
||||||
Folder::create(dirname($this->jobManifestPath));
|
Folder::create(dirname($this->jobManifestPath));
|
||||||
file_put_contents($this->jobManifestPath, json_encode($payload, JSON_PRETTY_PRINT));
|
file_put_contents($this->jobManifestPath, json_encode($payload, JSON_PRETTY_PRINT));
|
||||||
|
if (!empty($data['status'])) {
|
||||||
|
$this->log(sprintf('Job %s status -> %s', $payload['id'] ?? $this->jobId ?? 'unknown', $data['status']), 'debug');
|
||||||
|
}
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
// ignore manifest write failures
|
// ignore manifest write failures
|
||||||
}
|
}
|
||||||
@@ -238,6 +254,8 @@ class SafeUpgradeManager
|
|||||||
// ignore log write failures
|
// ignore log write failures
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->log(sprintf('Queued safe upgrade job %s', $jobId));
|
||||||
|
|
||||||
$this->setProgress('queued', 'Waiting for upgrade worker...', 0, ['job_id' => $jobId]);
|
$this->setProgress('queued', 'Waiting for upgrade worker...', 0, ['job_id' => $jobId]);
|
||||||
|
|
||||||
if (!function_exists('proc_open')) {
|
if (!function_exists('proc_open')) {
|
||||||
@@ -256,49 +274,49 @@ class SafeUpgradeManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$phpBinary = $this->escapeArgument(PHP_BINARY);
|
$finder = new PhpExecutableFinder();
|
||||||
$gravBinary = Utils::isWindows()
|
$phpPath = $finder->find(false) ?: PHP_BINARY;
|
||||||
? $this->escapeArgument(GRAV_ROOT . '\\bin\\grav')
|
if (!$phpPath) {
|
||||||
: $this->escapeArgument(GRAV_ROOT . '/bin/grav');
|
throw new RuntimeException('Unable to locate PHP CLI to start safe upgrade worker.');
|
||||||
$jobArgument = $this->escapeArgument($jobId);
|
}
|
||||||
$logArgument = $this->escapeArgument($logPath);
|
|
||||||
|
$gravPath = Utils::isWindows()
|
||||||
|
? GRAV_ROOT . '\\bin\\grav'
|
||||||
|
: GRAV_ROOT . '/bin/grav';
|
||||||
|
|
||||||
|
if (!is_file($gravPath)) {
|
||||||
|
throw new RuntimeException('Unable to locate Grav CLI binary.');
|
||||||
|
}
|
||||||
|
|
||||||
if (Utils::isWindows()) {
|
if (Utils::isWindows()) {
|
||||||
$commandLine = sprintf(
|
$commandLine = sprintf(
|
||||||
'start /B "" %s %s safe-upgrade:run --job=%s >> %s 2>&1',
|
'start /B "" %s %s safe-upgrade:run --job=%s >> %s 2>&1',
|
||||||
$phpBinary,
|
escapeshellarg($phpPath),
|
||||||
$gravBinary,
|
escapeshellarg($gravPath),
|
||||||
$jobArgument,
|
escapeshellarg($jobId),
|
||||||
$logArgument
|
escapeshellarg($logPath)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$commandLine = sprintf(
|
$commandLine = sprintf(
|
||||||
'%s %s safe-upgrade:run --job=%s >> %s 2>&1 &',
|
'nohup %s %s safe-upgrade:run --job=%s >> %s 2>&1 &',
|
||||||
$phpBinary,
|
escapeshellarg($phpPath),
|
||||||
$gravBinary,
|
escapeshellarg($gravPath),
|
||||||
$jobArgument,
|
escapeshellarg($jobId),
|
||||||
$logArgument
|
escapeshellarg($logPath)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$descriptor = [
|
try {
|
||||||
0 => ['pipe', 'r'],
|
file_put_contents($logPath, '[' . gmdate('c') . "] Command: {$commandLine}\n", FILE_APPEND);
|
||||||
1 => ['pipe', 'w'],
|
} catch (Throwable $e) {
|
||||||
2 => ['pipe', 'w'],
|
// ignore log write failures
|
||||||
];
|
|
||||||
|
|
||||||
$process = proc_open($commandLine, $descriptor, $pipes, GRAV_ROOT);
|
|
||||||
if (!is_resource($process)) {
|
|
||||||
throw new RuntimeException('Unable to start safe upgrade worker.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($pipes as $pipe) {
|
$this->log(sprintf('Spawn command for job %s: %s', $jobId, $commandLine), 'debug');
|
||||||
if (is_resource($pipe)) {
|
|
||||||
fclose($pipe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc_close($process);
|
$process = Process::fromShellCommandline($commandLine, GRAV_ROOT, null, null, 3);
|
||||||
|
$process->disableOutput();
|
||||||
|
$process->run();
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
$message = $e->getMessage();
|
$message = $e->getMessage();
|
||||||
$this->writeManifest([
|
$this->writeManifest([
|
||||||
@@ -319,6 +337,8 @@ class SafeUpgradeManager
|
|||||||
'started_at' => time(),
|
'started_at' => time(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$this->log(sprintf('Safe upgrade job %s worker started', $jobId));
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'status' => 'queued',
|
'status' => 'queued',
|
||||||
'job_id' => $jobId,
|
'job_id' => $jobId,
|
||||||
@@ -857,6 +877,9 @@ class SafeUpgradeManager
|
|||||||
try {
|
try {
|
||||||
Folder::create(dirname($this->progressPath));
|
Folder::create(dirname($this->progressPath));
|
||||||
file_put_contents($this->progressPath, json_encode($payload, JSON_PRETTY_PRINT));
|
file_put_contents($this->progressPath, json_encode($payload, JSON_PRETTY_PRINT));
|
||||||
|
if ($this->jobId) {
|
||||||
|
$this->log(sprintf('Job %s stage -> %s (%s)', $this->jobId, $stage, $message), $stage === 'error' ? 'error' : 'debug');
|
||||||
|
}
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
// ignore write failures
|
// ignore write failures
|
||||||
}
|
}
|
||||||
@@ -905,7 +928,10 @@ class SafeUpgradeManager
|
|||||||
'message' => $message,
|
'message' => $message,
|
||||||
'details' => $extra,
|
'details' => $extra,
|
||||||
],
|
],
|
||||||
|
'status' => 'error',
|
||||||
|
'completed_at' => time(),
|
||||||
]);
|
]);
|
||||||
|
$this->log(sprintf('Safe upgrade job %s failed: %s', $this->jobId ?? 'n/a', $message), 'error');
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
Reference in New Issue
Block a user