Proc close: примеры (PHP)
proc_close(resource $process): intФункция proc_close в PHP
Функция proc_close() завершает процесс, открытый с помощью proc_open(), и возвращает код его завершения. Она используется для управления внешними процессами в PHP, позволяя запускать системные команды или другие программы с возможностью двустороннего взаимодействия через каналы ввода-вывода.
Функция принимает один обязательный аргумент:
- $process – ресурс типа process, возвращаемый функцией proc_open(). Этот ресурс представляет запущенный внешний процесс.
Возвращаемое значение – целое число, представляющее код завершения процесса. В случае ошибки возвращается -1.
Функция применяется в сценариях, требующих взаимодействия с внешними программами: обработка данных специализированными утилитами, управление системными службами, параллельное выполнение задач. Основное назначение – корректное завершение процесса после завершения обмена данными.
Примеры использования proc_close
<?
$descriptors = [
0 => ["pipe", "r"], // stdin
1 => ["pipe", "w"], // stdout
2 => ["pipe", "w"] // stderr
];
$process = proc_open('echo "Тестовый вывод"', $descriptors, $pipes);
if (is_resource($process)) {
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
echo "Код завершения: " . $return_value;
}
?>Тестовый вывод Код завершения: 0
<?
$process = proc_open('несуществующая_команда', [], $pipes);
if (is_resource($process)) {
$return_value = proc_close($process);
echo "Код: " . $return_value;
} else {
echo "Не удалось запустить процесс";
}
?>Код: -1
Альтернативные функции в PHP
Выполняет команду через оболочку и возвращает вывод в виде строки. Подходит для простых задач без необходимости управления вводом-выводом.
Выполняет внешнюю программу и возвращает последнюю строку вывода. Позволяет получить полный вывод в массив и код возврата.
Выполняет внешнюю команду и выводит результат непосредственно в браузер. Возвращает последнюю строку вывода.
Открывает процесс для односторонней передачи данных (только чтение или только запись). Не обеспечивает такого же уровня контроля, как proc_open().
Аналоги в других языках программирования
import subprocess
result = subprocess.run(['echo', 'Тестовый вывод'],
capture_output=True, text=True)
print(result.stdout)
print(f"Код завершения: {result.returncode}")Тестовый вывод Код завершения: 0
const { spawn } = require('child_process');
const process = spawn('echo', ['Тестовый вывод']);
process.stdout.on('data', (data) => {
console.log(data.toString());
});
process.on('close', (code) => {
console.log(`Код завершения: ${code}`);
});Тестовый вывод Код завершения: 0
echo "Тестовый вывод"
echo "Код завершения: $?"Тестовый вывод Код завершения: 0
Типичные ошибки при использовании
<?
$descriptors = [
0 => ["pipe", "r"],
1 => ["pipe", "w"]
];
$process = proc_open('sleep 5', $descriptors, $pipes);
fclose($pipes[0]);
// Не закрыт $pipes[1] перед proc_close()
$return_value = proc_close($process);
?>Ошибка: процесс может зависнуть, ожидая записи в закрытый канал.
<?
$process = proc_open('echo test', [], $pipes);
proc_close($process);
$result = proc_close($process); // Второй вызов
var_dump($result);
?>Warning: proc_close(): supplied resource is not a valid stream resource int(-1)
<?
$fp = fopen('file.txt', 'r');
$result = proc_close($fp); // Передача ресурса файла
?>Warning: proc_close(): supplied resource is not a valid stream resource
Изменения в последних версиях PHP
Функция теперь выбрасывает исключение TypeError при передаче аргумента нересурсного типа. Ранее выдавалось предупреждение и возвращалось значение null.
<?
// PHP 8+
try {
proc_close(null);
} catch (TypeError $e) {
echo "Ошибка типа: " . $e->getMessage();
}
?>Ошибка типа: proc_close(): supplied resource is not a valid stream resource
Улучшена обработка процессов в Windows, исправлены проблемы с блокировкой при чтении/записи.
Расширенные примеры использования
<?
$descriptors = [
0 => ["pipe", "r"],
1 => ["pipe", "w"],
2 => ["pipe", "w"]
];
$process = proc_open(
'find /var/www -name "*.php" 2>&1',
$descriptors,
$pipes,
null,
null,
['bypass_shell' => true]
);
if (is_resource($process)) {
fclose($pipes[0]);
stream_set_blocking($pipes[1], false);
stream_set_blocking($pipes[2], false);
$stdout = '';
$stderr = '';
$running = true;
while ($running) {
$read = [$pipes[1], $pipes[2]];
$write = null;
$except = null;
if (stream_select($read, $write, $except, 0, 200000) !== false) {
foreach ($read as $stream) {
if ($stream === $pipes[1]) {
$stdout .= stream_get_contents($stream);
} else {
$stderr .= stream_get_contents($stream);
}
}
}
$status = proc_get_status($process);
$running = $status['running'];
}
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
echo "STDOUT: " . substr($stdout, 0, 200) . "...\n";
echo "STDERR: " . $stderr . "\n";
echo "Код возврата: " . $return_value;
}
?><?
$descriptors = [
0 => ["pipe", "r"],
1 => ["pipe", "w"],
2 => ["pipe", "w"]
];
$process = proc_open(
'bc -q',
$descriptors,
$pipes
);
if (is_resource($process)) {
fwrite($pipes[0], "2 + 2 * 2\n");
fwrite($pipes[0], "quit\n");
fclose($pipes[0]);
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
fclose($pipes[2]);
$return_value = proc_close($process);
echo "Результат вычислений: " . $output;
}
?>Результат вычислений: 6
<?
$descriptors = [
1 => ["pipe", "w"],
2 => ["pipe", "w"]
];
$cwd = '/tmp';
$env = ['CUSTOM_VAR' => 'test_value'];
$process = proc_open(
'echo $CUSTOM_VAR && pwd',
$descriptors,
$pipes,
$cwd,
$env
);
if (is_resource($process)) {
$output = stream_get_contents($pipes[1]);
$errors = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
echo $output;
}
?>test_value /tmp