diff options
Diffstat (limited to 'sourcecodes/terminal_commands.php')
| -rw-r--r-- | sourcecodes/terminal_commands.php | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/sourcecodes/terminal_commands.php b/sourcecodes/terminal_commands.php new file mode 100644 index 00000000..fb4f4466 --- /dev/null +++ b/sourcecodes/terminal_commands.php @@ -0,0 +1,84 @@ +<?php + +function __command2string__(string $str_cmd, string $arg): string +{ + if(is_null($str_cmd) or trim($str_cmd) == '') { + return trim($arg); + } + return sprintf("%s %s", $str_cmd, $arg); +} + +/** + * Run terminal commands: thin wrapper around `proc_open`. + * + * This wraps the `proc_open(...)` function, by doing some basic checks and + * raising appropriate `RuntimeException errors in case of failures.` + * + * @param array $command An array of strings, where the first item is the + * command to run and the rest are arguments to that command. + * @returns array Returns the exit code for the process, the output on the + * standard output and the output on the standard error. + * @raises RuntimeException + */ +function runTerminalCommand(array $command): array +{ + if(!is_array($command)) + { + throw new \RuntimeException( + "Command *must* always be an array of strings."); + } + + if(sizeof($command) == 0) { + throw new \RuntimeException( + "You must provide at least the command to run."); + } + + $descriptors = [ + 1 => ['pipe', 'w'], //stdout + 2 => ['pipe', 'w'], //stderr + ]; + + // Generate `$strcmd` below to use for user notifications. + $strcmd = array_reduce( + array_merge( + [escapeshellcmd($command[0])], + array_map( + 'escapeshellarg', + array_slice($command, 1, sizeof($command)))), + '__command2string__', + ""); + $process = proc_open( + $command, // `proc_open` auto-escapes array command + $descriptors, + $pipes); + + if(!is_resource($process)) { + throw new \RunTimeException(sprintf( + "PHP was not able to spawn the process [%s]. " . + "Check system resources or paths.", + $strcmd + )); + } + + // Read streams: + $stdout = stream_get_contents($pipes[1]); + $stderr = stream_get_contents($pipes[2]); + + // Clean streams and close process resource. + fclose($pipes[1]); + fclose($pipes[2]); + $exitcode = proc_close($process); + + if($exitcode !== 0) { + throw new \RuntimeException(sprintf( + "Command [%s] failed with exit code %d.\n" . + "Stdout: %s\n\nStderr: %s", + $strcmd, + $exitcode, + trim($stdout), + trim($stderr) + )); + } + return [$exitcode, $stdout, $stderr]; +} +?> |
