Popen: примеры (PHP)
popen(string $command, string $mode): resource|falseОсновные сведения о popen
Функция popen() открывает односторонний канал для выполнения внешней команды. Она позволяет запустить процесс и взаимодействовать с ним через файловый указатель, используя стандартный ввод (stdin) или вывод (stdout).
Функция применяется для асинхронного выполнения внешних программ, обработки больших объемов данных потоком без загрузки в память, логирования или непрерывного взаимодействия с сервисами.
command (string): Строка команды для выполнения в оболочке.
mode (string): Режим открытия канала. Допустимые значения: 'r' (чтение из stdout процесса), 'w' (запись в stdin процесса).
Функция возвращает файловый указатель или false в случае ошибки.
Простые примеры использования
<?php
$handle = popen('ls -la', 'r');
if ($handle) {
while (!feof($handle)) {
echo fgets($handle, 4096);
}
pclose($handle);
}
?>total 12 drwxr-xr-x 2 user user 4096 Jan 1 10:00 . drwxr-xr-x 10 user user 4096 Jan 1 09:55 .. -rw-r--r-- 1 user user 0 Jan 1 10:00 index.php
<?php
$handle = popen('grep "error"', 'w');
fwrite($handle, "error: file not found\nwarning: deprecated\n");
pclose($handle);
?>// В консоли будет выведено: error: file not found
Альтернативы в PHP
Предоставляет расширенный контроль над процессом, включая stdin, stdout, stderr и управление дескрипторами. Предпочтительнее для сложных взаимодействий.
Функции для простого выполнения команд с захватом или прямым выводом результата. Используются для синхронных операций без двустороннего обмена данными.
Возвращает весь вывод команды как строку. Подходит для коротких команд с небольшим выводом.
Аналоги в других языках
import subprocess
proc = subprocess.Popen(['ls', '-la'], stdout=subprocess.PIPE)
output, error = proc.communicate()
print(output.decode())const { spawn } = require('child_process');
const ls = spawn('ls', ['-la']);
ls.stdout.on('data', (data) => {
console.log(data.toString());
});ls -la | grep "example"Типичные ошибки
<?php
$handle = popen('несуществующая_команда', 'r');
// $handle будет false, но без проверки вызов fgets() вызовет ошибку
?><?php
// Попытка чтения из канала, открытого для записи
$handle = popen('ls', 'w');
$data = fread($handle, 1024); // Не будет данных
?>Невызов pclose() может оставить процессы зависшими.
Изменения в новых версиях PHP
В PHP 8.0 улучшена обработка ошибок: при сбое вызова функции теперь выбрасывается исключение типа ValueError для некорректных параметров. В более ранних версиях возвращалось false без деталей.
<?php
// PHP 8+
try {
$handle = popen([], 'r'); // Неверный аргумент
} catch (ValueError $e) {
echo $e->getMessage();
}
?>Расширенные сценарии
<?php
$handle = popen('python3 -u interactive_script.py', 'w');
// -u в Python отключает буферизацию вывода
fwrite($handle, "input_data\n");
fflush($handle); // Принудительная отправка
sleep(1);
$output = fread($handle, 4096);
pclose($handle);
?><?php
$logFile = 'app.log';
$handle = popen("tail -f $logFile | grep 'CRITICAL'", 'r');
while (!feof($handle)) {
$line = fgets($handle);
if ($line) {
// Отправка уведомления или обработка
echo "Критическая ошибка: $line";
}
}
?><?php
// Запись одного набора данных в две команды параллельно
$sourceData = "sample data\n";
$handles = [
popen('gzip > output.gz', 'w'),
popen('tee raw_output.txt', 'w')
];
foreach ($handles as $handle) {
fwrite($handle, $sourceData);
pclose($handle);
}
?>