Bearsampp 2026.5.5
Loading...
Searching...
No Matches
class.commandrunner.php
Go to the documentation of this file.
1<?php
2/*
3 * Copyright (c) 2021-2024 Bearsampp
4 * License: GNU General Public License version 3 or later; see LICENSE.txt
5 * Author: Bear
6 * Website: https://bearsampp.com
7 * Github: https://github.com/Bearsampp
8 */
9
28{
34 private static function writeLog(string $log): void
35 {
36 global $bearsamppRoot;
37 Log::debug($log, $bearsamppRoot->getBatchLogFilePath());
38 }
39
51 public static function exec(string $executable, array $args = [], string &$stderr = ''): string|false
52 {
53 $cmd = escapeshellarg($executable);
54 foreach ($args as $arg) {
55 $cmd .= ' ' . escapeshellarg((string) $arg);
56 }
57
58 self::writeLog('CommandRunner::exec: ' . $cmd);
59
60 $descriptorspec = [
61 0 => ['pipe', 'r'],
62 1 => ['pipe', 'w'],
63 2 => ['pipe', 'w'],
64 ];
65
66 $process = @proc_open($cmd, $descriptorspec, $pipes, null, null, ['bypass_shell' => true]);
67
68 if (!is_resource($process)) {
69 self::writeLog('CommandRunner::exec: failed to start process: ' . $cmd);
70 return false;
71 }
72
73 fclose($pipes[0]);
74 $output = stream_get_contents($pipes[1]);
75 $stderr = stream_get_contents($pipes[2]);
76 fclose($pipes[1]);
77 fclose($pipes[2]);
78 proc_close($process);
79
80 if (!empty($stderr)) {
81 self::writeLog('CommandRunner::exec stderr: ' . $stderr);
82 }
83
84 return $output;
85 }
86
97 public static function execCombined(string $executable, array $args = []): string|false
98 {
99 $stderr = '';
100 $output = self::exec($executable, $args, $stderr);
101
102 if ($output === false) {
103 return false;
104 }
105
106 if (!empty($stderr)) {
107 $output .= "\n" . $stderr;
108 }
109
110 return $output;
111 }
112
126 public static function stream(string $executable, array $args, callable $lineCallback): int|false
127 {
128 $cmd = escapeshellarg($executable);
129 foreach ($args as $arg) {
130 $cmd .= ' ' . escapeshellarg((string) $arg);
131 }
132
133 self::writeLog('CommandRunner::stream: ' . $cmd);
134
135 $process = popen($cmd, 'rb');
136 if (!$process) {
137 self::writeLog('CommandRunner::stream: failed to start process: ' . $cmd);
138 return false;
139 }
140
141 $buffer = '';
142 while (!feof($process)) {
143 $buffer .= fread($process, 8192);
144 while (($pos = strpos($buffer, "\r")) !== false) {
145 $line = trim(substr($buffer, 0, $pos));
146 $buffer = substr($buffer, $pos + 1);
147 $lineCallback($line);
148 }
149 }
150
151 // Flush any remaining data not terminated by \r
152 if (!empty($buffer)) {
153 $lineCallback(trim($buffer));
154 }
155
156 return pclose($process);
157 }
158
168 public static function background(string $command): void
169 {
170 self::writeLog('CommandRunner::background: ' . $command);
171 pclose(popen('start /B ' . $command, 'r'));
172 }
173
185 public static function shellExec(string $command): ?string
186 {
187 self::writeLog('CommandRunner::shellExec: ' . $command);
188 return shell_exec($command);
189 }
190}
global $bearsamppRoot
static execCombined(string $executable, array $args=[])
static writeLog(string $log)
static stream(string $executable, array $args, callable $lineCallback)
static shellExec(string $command)
static background(string $command)
static exec(string $executable, array $args=[], string &$stderr='')
static debug($data, $file=null)