Supervisor Manager

PHP

Plesk extension for managing Supervisor processes and workers with monitoring, process control, service management, and deployment automation.

Stars
16
Forks
1
Downloads
N/A
Open Issues
0
Files main

Repository Files

Loading file structure...
plib/scripts/cleanup.php
<?php

function supervisorManagerCleanup()
{
    $configs = array();
    $logs = array();

    foreach (supervisorManagerStoredPrograms() as $program) {
        if (!empty($program['config_path'])) {
            $configs[] = $program['config_path'];
        }
        if (!empty($program['log_path'])) {
            $logs[] = $program['log_path'];
        }
    }

    foreach (supervisorManagerGeneratedConfigs() as $config) {
        $configs[] = $config;
        $log = supervisorManagerLogFromConfig($config);
        if ($log !== null) {
            $logs[] = $log;
        }
    }

    foreach (array_unique($configs) as $config) {
        supervisorManagerRemoveConfig($config);
    }
    foreach (array_unique($logs) as $log) {
        supervisorManagerRemoveLog($log);
    }

    supervisorManagerRemoveDataFile();
    supervisorManagerRefreshSupervisor();
}

function supervisorManagerStoredPrograms()
{
    $file = pm_Context::getVarDir() . '/data/programs.json';
    if (!is_readable($file)) {
        return array();
    }

    $data = json_decode((string) file_get_contents($file), true);
    return is_array($data) ? $data : array();
}

function supervisorManagerGeneratedConfigs()
{
    $configs = array();
    foreach (array('/etc/supervisor/conf.d', '/etc/supervisord.d') as $dir) {
        foreach (glob($dir . '/plesk-*.conf') ?: array() as $config) {
            if (supervisorManagerIsGeneratedConfig($config)) {
                $configs[] = $config;
            }
        }
    }

    return $configs;
}

function supervisorManagerIsGeneratedConfig($path)
{
    if (!supervisorManagerIsSafeConfigPath($path) || !is_readable($path)) {
        return false;
    }

    $handle = fopen($path, 'r');
    if ($handle === false) {
        return false;
    }
    $firstLine = fgets($handle);
    fclose($handle);

    return trim((string) $firstLine) === '; Generated by Plesk Supervisor Manager. Edit from Plesk when possible.';
}

function supervisorManagerLogFromConfig($path)
{
    if (!is_readable($path)) {
        return null;
    }

    foreach (file($path) as $line) {
        if (strpos($line, 'stdout_logfile=') === 0) {
            $log = trim(substr($line, strlen('stdout_logfile=')));
            return supervisorManagerIsSafeLogPath($log) ? $log : null;
        }
    }

    return null;
}

function supervisorManagerRemoveConfig($path)
{
    if (!supervisorManagerIsSafeConfigPath($path)) {
        return;
    }
    if (file_exists($path) && supervisorManagerIsGeneratedConfig($path)) {
        @unlink($path);
    }
}

function supervisorManagerRemoveLog($path)
{
    if (!supervisorManagerIsSafeLogPath($path)) {
        return;
    }
    if (file_exists($path) && is_file($path) && !is_link($path)) {
        @unlink($path);
    }
}

function supervisorManagerRemoveDataFile()
{
    $dataDir = pm_Context::getVarDir() . '/data';
    $programsFile = $dataDir . '/programs.json';
    if (file_exists($programsFile) && is_file($programsFile) && !is_link($programsFile)) {
        @unlink($programsFile);
    }
    if (is_dir($dataDir) && count(scandir($dataDir)) === 2) {
        @rmdir($dataDir);
    }
}

function supervisorManagerIsSafeConfigPath($path)
{
    $path = trim((string) $path);
    $directory = rtrim(dirname($path), '/');
    $file = basename($path);

    return in_array($directory, array('/etc/supervisor/conf.d', '/etc/supervisord.d'), true)
        && preg_match('/^plesk-[A-Za-z0-9_.-]+\.conf$/', $file);
}

function supervisorManagerIsSafeLogPath($path)
{
    $path = trim((string) $path);
    $directory = rtrim(dirname($path), '/');
    $file = basename($path);

    return $directory === '/var/log/supervisor/plesk'
        && preg_match('/^[A-Za-z0-9_.-]+\.log$/', $file);
}

function supervisorManagerRefreshSupervisor()
{
    $supervisorctl = supervisorManagerFindExecutable(array('/usr/bin/supervisorctl', '/usr/local/bin/supervisorctl', '/bin/supervisorctl'));
    if ($supervisorctl !== null) {
        supervisorManagerRun(array($supervisorctl, 'reread'));
        supervisorManagerRun(array($supervisorctl, 'update'));
    }

    supervisorManagerRunShell('systemctl restart supervisor 2>/dev/null || systemctl restart supervisord 2>/dev/null || service supervisor restart 2>/dev/null || true');
}

function supervisorManagerFindExecutable(array $paths)
{
    foreach ($paths as $path) {
        if (is_executable($path)) {
            return $path;
        }
    }

    return null;
}

function supervisorManagerRun(array $parts)
{
    supervisorManagerRunShell(implode(' ', array_map('escapeshellarg', $parts)) . ' 2>/dev/null || true');
}

function supervisorManagerRunShell($command)
{
    $descriptors = array(
        0 => array('pipe', 'r'),
        1 => array('pipe', 'w'),
        2 => array('pipe', 'w'),
    );
    $process = @proc_open($command, $descriptors, $pipes);
    if (!is_resource($process)) {
        return;
    }
    fclose($pipes[0]);
    stream_get_contents($pipes[1]);
    stream_get_contents($pipes[2]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($process);
}