PHP - запуск программы с таймаутом

ckpunmkug

Null
Пользователь
Регистрация
13 Янв 2026
Сообщения
3
Реакции
0
Очень полезная вещица для запуска прог которые могут застрять с выполнением. Если честно я подзабыл на кой её смастерил, по любому была какая-то конкретная необходимость. Сейчас использую вместо встроенного в php exec, потому что эта функция отдаёт и stdout и stderr. А ещё она это возвращает вместе со статусом в array или false.

Код:
<?php

function launch(string $command, int $timeout = 30) // array
{//{{{//
	
	$timeout *= 1000000;
	
	$std = [
		["pipe", "r"],
		["pipe", "w"],
		["pipe", "w"],
	];
	$PIPE = [];
	$cwd = getcwd();
	if(!is_string($cwd)) {
		trigger_error("Can't get current working directory", E_USER_WARNING);
		return(false);
	}
	
	$proc = proc_open($command, $std, $PIPE, $cwd);
	if(!is_resource($proc)) {
		if (defined('DEBUG') && DEBUG) var_dump(['$command' => $command]);
		trigger_error("Can't open process for command", E_USER_WARNING);
		return(false);
	}
	
	$stdout = '';
	$stderr = '';
	stream_set_blocking($PIPE[1], false);
	stream_set_blocking($PIPE[2], false);
	
	while(true) {//
		$proc_status = proc_get_status($proc);
		if(!is_array($proc_status)) {
			if (defined('DEBUG') && DEBUG) var_dump(['$command' => $command]);
			trigger_error("Can't get process status for command", E_USER_WARNING);
			return(false);
		}
		
		if($proc_status["running"] == false) break;
		
		$stdout .= stream_get_contents($PIPE[1]);
		$stderr .= stream_get_contents($PIPE[2]);
	
		usleep(100000);
		$timeout -= 100000;
		
		if($timeout <= 0) {
			proc_terminate($proc, 9);
			
			foreach($PIPE as $pipe) {
				fclose($pipe);
			}
			proc_close($proc);
			
			if (defined('DEBUG') && DEBUG) var_dump(['$command' => $command]);
			trigger_error("Process with command timeout", E_USER_WARNING);
			return(false);
		}
	}// while(true)
	
	$result = [
		"status" => $proc_status["exitcode"],
	];
	
	fclose($PIPE[0]);
	
	$contents = stream_get_contents($PIPE[1]);
	if(!is_string($contents)) {
		if (defined('DEBUG') && DEBUG) var_dump(['$command' => $command]);
		trigger_error("Can't get command stdout contents", E_USER_WARNING);
		return(false);
	}
	$result["stdout"] = $stdout.$contents;
	fclose($PIPE[1]);
	
	$contents = stream_get_contents($PIPE[2]);
	if(!is_string($contents)) {
		if (defined('DEBUG') && DEBUG) var_dump(['$command' => $command]);
		trigger_error("Can't get command stderr contents", E_USER_WARNING);
		return(false);
	}
	$result["stderr"] = $stderr.$contents;
	fclose($PIPE[2]);
	
	proc_close($proc);
	
	return($result);
	
}//}}}//
 
Сверху