Proc get status: примеры (PHP)

Использование proc_get_status для контроля процессов в PHP
Раздел: Процессы
proc_get_status(resource $process): array
Функция proc_get_status в PHP

Функция proc_get_status() возвращает информацию о процессе, запущенном через функцию proc_open(). Она используется для мониторинга состояния внешнего процесса во время его выполнения.

Назначение и использование

Эта функция применяется для получения текущего статуса дочернего процесса: работает ли он, завершился ли, код возврата. Это полезно при создании скриптов, которым нужно взаимодействовать с длительными внешними командами.

Аргументы функции

Функция принимает один обязательный параметр:

  • $process — ресурс, возвращаемый функцией proc_open(), который представляет запущенный процесс.

Возвращает ассоциативный массив со статусом или false в случае ошибки.

Базовые примеры использования
Проверка состояния процесса
$descriptors = [
    0 => ["pipe", "r"],
    1 => ["pipe", "w"],
    2 => ["pipe", "w"]
];

$process = proc_open('sleep 2', $descriptors, $pipes);

if (is_resource($process)) {
    sleep(1); // Ждем 1 секунду
    $status = proc_get_status($process);
    
    echo "Запущен: " . ($status['running'] ? 'Да' : 'Нет') . "\n";
    echo "PID: " . $status['pid'] . "\n";
    echo "Код выхода: " . $status['exitcode'] . "\n";
    
    proc_close($process);
}
Запущен: Да
PID: 12345
Код выхода: -1
Ожидание завершения процесса
$process = proc_open('ls -la', $descriptors, $pipes);

while (true) {
    $status = proc_get_status($process);
    
    if (!$status['running']) {
        echo "Процесс завершился с кодом: " . $status['exitcode'] . "\n";
        break;
    }
    
    usleep(100000); // Проверяем каждые 0.1 секунды
}
Процесс завершился с кодом: 0
Похожие функции в PHP
shell_exec()

Выполняет команду через shell и возвращает вывод как строку. Подходит для простых команд, где не требуется контроль над процессом.

exec()

Выполняет внешнюю программу и возвращает последнюю строку вывода. Позволяет получить код возврата через третий параметр.

Открывает процесс как файловый указатель для чтения или записи. Проще в использовании для однонаправленного взаимодействия.

pcntl_fork()

Создает дочерний процесс (требует модуль PCNTL). Предоставляет полный контроль над процессами, но сложнее в использовании.

proc_get_status() предпочтительнее, когда необходим детальный контроль и мониторинг состояния процесса во время его выполнения.

Аналоги в других языках
Python: subprocess.Popen.poll()
import subprocess

proc = subprocess.Popen(['sleep', '2'])
print(f"Запущен: {proc.poll() is None}")
proc.wait()
print(f"Код возврата: {proc.returncode}")
Запущен: True
Код возврата: 0
JavaScript (Node.js): child_process.spawn()
const { spawn } = require('child_process');
const ls = spawn('ls', ['-la']);

console.log(`PID: ${ls.pid}`);
ls.on('close', (code) => {
    console.log(`Код выхода: ${code}`);
});
Bash: отслеживание процессов
sleep 5 &
pid=$!
echo "PID: $pid"
if kill -0 $pid 2>/dev/null; then
    echo "Процесс работает"
else
    echo "Процесс завершен"
fi
Типичные ошибки
Передача неверного ресурса
$status = proc_get_status('не ресурс');
var_dump($status);
Warning: proc_get_status() expects parameter 1 to be resource, string given
bool(false)
Проверка закрытого процесса
$process = proc_open('ls', $descriptors, $pipes);
proc_close($process);
$status = proc_get_status($process);
var_dump($status);
Warning: proc_get_status(): supplied resource is not a valid process resource
bool(false)
Невнимание к многократным вызовам
$process = proc_open('echo test', $descriptors, $pipes);
$status1 = proc_get_status($process);
proc_close($process);
$status2 = proc_get_status($process); // Ошибка
Изменения в новых версиях PHP

В PHP 8.0 функция была сделана более строгой к типам передаваемых аргументов. В случае передачи некорректного типа данных теперь выбрасывается TypeError вместо предупреждения.

// В PHP 7.4
proc_get_status('string'); // Warning, возвращает false

// В PHP 8.0+ 
proc_get_status('string'); // TypeError

В PHP 8.1 добавлена статическая проверка типов при передаче ресурсов.

Расширенные примеры
Мониторинг нескольких процессов
Пример php
$processes = [];
for ($i = 0; $i < 3; $i++) {
    $processes[$i] = proc_open("sleep " . ($i+1), $descriptors, $pipes);
}

while (!empty($processes)) {
    foreach ($processes as $i => $process) {
        $status = proc_get_status($process);
        
        if (!$status['running']) {
            echo "Процесс $i завершен с кодом: " . $status['exitcode'] . "\n";
            proc_close($process);
            unset($processes[$i]);
        }
    }
    usleep(100000);
}
Обработка сигналов процесса
Пример php
$process = proc_open('trap "echo SIGTERM received; exit 1" SIGTERM; sleep 10', 
                    $descriptors, $pipes);

$status = proc_get_status($process);
posix_kill($status['pid'], SIGTERM);

sleep(1);
$status = proc_get_status($process);
echo "Процесс работает: " . ($status['running'] ? 'Да' : 'Нет') . "\n";
echo "Код выхода: " . $status['exitcode'] . "\n";
Интеграция с proc_nice
Пример php
$process = proc_open('dd if=/dev/zero of=/dev/null count=100000', 
                    $descriptors, $pipes);

$status = proc_get_status($process);
if ($status['running']) {
    proc_nice($process, 10); // Устанавливаем низкий приоритет
    echo "Приоритет изменен для PID: " . $status['pid'] . "\n";
}
Чтение вывода в реальном времени
Пример php
$process = proc_open('for i in {1..5}; do echo $i; sleep 0.5; done', 
                    $descriptors, $pipes);

if (is_resource($process)) {
    stream_set_blocking($pipes[1], false);
    
    while (true) {
        $status = proc_get_status($process);
        
        // Чтение вывода
        $output = fread($pipes[1], 1024);
        if ($output !== false && $output !== '') {
            echo "Вывод: $output";
        }
        
        if (!$status['running']) {
            break;
        }
        usleep(100000);
    }
    
    fclose($pipes[1]);
    proc_close($process);
}

PHP proc_get_status function comments

En
Proc get status Get information about a process opened by proc_open