Bearsampp 2026.9.23
Loading...
Searching...
No Matches
CommandRunner Class Reference

Static Public Member Functions

static background (string $command)
static exec (string $executable, array $args=[], string &$stderr='')
static execCombined (string $executable, array $args=[])
static execToFile (string $executable, array $args, string $stdoutFile, string $stderrFile)
static shellExec (string $command)
static stream (string $executable, array $args, callable $lineCallback)

Static Private Member Functions

static writeLog (string $log)

Detailed Description

Class CommandRunner

Centralizes all PHP shell-execution primitives (proc_open, popen, shell_exec) so that every external command goes through a single, auditable point with consistent argument escaping and logging.

Three execution modes:

  • exec() capture stdout/stderr, hidden console window (replaces proc_open)
  • stream() stream output line-by-line via callback (replaces popen)
  • shellExec() capture output from a fully-formed command (replaces shell_exec)

Rules:

  • exec() and stream() always escapeshellarg() every argument individually.
  • shellExec() is reserved for hardcoded commands with no dynamic user input. Pass dynamic arguments through exec() or stream() instead.

Definition at line 27 of file class.commandrunner.php.

Member Function Documentation

◆ background()

background ( string $command)
static

Launch a command in the background without waiting for output.

Uses the Windows "start /B" cmd.exe idiom to detach the process immediately. The caller is responsible for ensuring $command is properly constructed; use escapeshellarg() on any dynamic values before passing them in.

Parameters
string$commandFully-formed command string to run in the background.

Definition at line 220 of file class.commandrunner.php.

220 : void
221 {
222 self::writeLog('CommandRunner::background: ' . $command);
223 pclose(popen('start /B ' . $command, 'r'));
224 }
static writeLog(string $log)
if( $raw) foreach($opts as $opt) if( $store_system_config) if($store_user_config) $command
Definition pearcmd.php:322

References $command, and writeLog().

Referenced by QuickPick\installModule().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ exec()

exec ( string $executable,
array $args = [],
string & $stderr = '' )
static

Execute an executable with arguments, capturing stdout and stderr.

Each argument is individually escaped with escapeshellarg(). The console window is hidden on Windows via bypass_shell + CREATE_NO_WINDOW semantics.

Parameters
string$executablePath to the executable (will be escapeshellarg'd).
array$argsArguments, each will be escapeshellarg'd.
string$stderrPopulated with any stderr output on return.
Returns
string|false stdout output on success, false if the process could not start.

Definition at line 52 of file class.commandrunner.php.

52 : string|false
53 {
54 $cmd = escapeshellarg($executable);
55 foreach ($args as $arg) {
56 $cmd .= ' ' . escapeshellarg((string)$arg);
57 }
58
59 self::writeLog('CommandRunner::exec: ' . $cmd);
60
61 $descriptorspec = [
62 0 => ['pipe', 'r'],
63 1 => ['pipe', 'w'],
64 2 => ['pipe', 'w'],
65 ];
66
67 $process = @proc_open($cmd, $descriptorspec, $pipes, null, null, ['bypass_shell' => true]);
68
69 if (!is_resource($process)) {
70 self::writeLog('CommandRunner::exec: failed to start process: ' . $cmd);
71
72 return false;
73 }
74
75 fclose($pipes[0]);
76 $output = stream_get_contents($pipes[1]);
77 $stderr = stream_get_contents($pipes[2]);
78 fclose($pipes[1]);
79 fclose($pipes[2]);
80 proc_close($process);
81
82 if (!empty($stderr)) {
83 self::writeLog('CommandRunner::exec stderr: ' . $stderr);
84 }
85
86 return $output;
87 }

References writeLog().

Referenced by execCombined().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ execCombined()

execCombined ( string $executable,
array $args = [] )
static

Execute an executable with arguments, combining stdout and stderr.

Convenience wrapper around exec() for callers that need both streams merged (e.g. sc.exe which may send status messages to either stream).

Parameters
string$executablePath to the executable (will be escapeshellarg'd).
array$argsArguments, each will be escapeshellarg'd.
Returns
string|false Combined output, or false if the process could not start.

Definition at line 147 of file class.commandrunner.php.

147 : string|false
148 {
149 $stderr = '';
150 $output = self::exec($executable, $args, $stderr);
151
152 if ($output === false) {
153 return false;
154 }
155
156 if (!empty($stderr)) {
157 $output .= "\n" . $stderr;
158 }
159
160 return $output;
161 }
static exec(string $executable, array $args=[], string &$stderr='')

References exec().

Referenced by Win32Service\fastServiceCheck().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ execToFile()

execToFile ( string $executable,
array $args,
string $stdoutFile,
string $stderrFile )
static

Execute an executable with arguments, redirecting stdout and stderr to files.

Capturing large output through a pipe with stream_get_contents() can be extremely slow on Windows, so this variant lets the child process write its output directly to the given files. The caller reads and cleans up the files.

Parameters
string$executablePath to the executable (will be escapeshellarg'd).
array$argsArguments, each will be escapeshellarg'd.
string$stdoutFileFile path the child's stdout is redirected to.
string$stderrFileFile path the child's stderr is redirected to.
Returns
int|false Process exit code on success, false if the process could not start.

Definition at line 103 of file class.commandrunner.php.

103 : int|false
104 {
105 $cmd = escapeshellarg($executable);
106 foreach ($args as $arg) {
107 $cmd .= ' ' . escapeshellarg((string)$arg);
108 }
109
110 self::writeLog('CommandRunner::execToFile: ' . $cmd);
111
112 $process = @proc_open(
113 $cmd,
114 [
115 0 => ['pipe', 'r'],
116 1 => ['file', $stdoutFile, 'w'],
117 2 => ['file', $stderrFile, 'w'],
118 ],
119 $pipes,
120 null,
121 null,
122 ['bypass_shell' => true]
123 );
124
125 if (!is_resource($process)) {
126 self::writeLog('CommandRunner::execToFile: failed to start process: ' . $cmd);
127
128 return false;
129 }
130
131 fclose($pipes[0]);
132
133 return proc_close($process);
134 }

References writeLog().

Referenced by Core\isSafeDestinationFileList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shellExec()

shellExec ( string $command)
static

Execute a fully-formed shell command and return its output.

Only use this for commands that contain no dynamic user input (e.g. hardcoded system queries such as "net session" or "whoami /groups"). For commands with dynamic arguments, use exec() or stream() instead so that escaping is enforced at the boundary.

Parameters
string$commandFully-formed command string. Must not contain unescaped user input.
Returns
string|null Command output, or null if the command could not be run.

Definition at line 238 of file class.commandrunner.php.

238 : ?string
239 {
240 self::writeLog('CommandRunner::shellExec: ' . $command);
241
242 return shell_exec($command);
243 }

References $command, and writeLog().

Referenced by Util\isAdmin().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stream()

stream ( string $executable,
array $args,
callable $lineCallback )
static

Execute an executable with arguments, streaming output line-by-line.

Useful for long-running processes that emit progress information. Each argument is individually escaped with escapeshellarg(). Lines are split on carriage-return (\r) to match Windows progress-reporting conventions. Any data remaining in the buffer after EOF is flushed as a final line.

Parameters
string$executablePath to the executable (will be escapeshellarg'd).
array$argsArguments, each will be escapeshellarg'd.
callable$lineCallbackInvoked with each trimmed output line as a string.
Returns
int|false Process exit code on success, false if the process could not start.

Definition at line 177 of file class.commandrunner.php.

177 : int|false
178 {
179 $cmd = escapeshellarg($executable);
180 foreach ($args as $arg) {
181 $cmd .= ' ' . escapeshellarg((string)$arg);
182 }
183
184 self::writeLog('CommandRunner::stream: ' . $cmd);
185
186 $process = popen($cmd, 'rb');
187 if (!$process) {
188 self::writeLog('CommandRunner::stream: failed to start process: ' . $cmd);
189
190 return false;
191 }
192
193 $buffer = '';
194 while (!feof($process)) {
195 $buffer .= fread($process, 8192);
196 while (($pos = strpos($buffer, "\r")) !== false) {
197 $line = trim(substr($buffer, 0, $pos));
198 $buffer = substr($buffer, $pos + 1);
199 $lineCallback($line);
200 }
201 }
202
203 // Flush any remaining data not terminated by \r
204 if (!empty($buffer)) {
205 $lineCallback(trim($buffer));
206 }
207
208 return pclose($process);
209 }

References writeLog().

Referenced by Core\unzipFile().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ writeLog()

writeLog ( string $log)
staticprivate

Writes a log entry to the batch log file.

Parameters
string$logThe message to log.

Definition at line 34 of file class.commandrunner.php.

34 : void
35 {
36 global $bearsamppRoot;
38 }
global $bearsamppRoot
static debug($data, $file=null)
static getBatchLogFilePath($aetrayPath=false)

References $bearsamppRoot, Log\debug(), and Path\getBatchLogFilePath().

Referenced by background(), exec(), execToFile(), shellExec(), and stream().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following file: