Added run_command() function and RunCommandFailedException exception

This commit is contained in:
Alannah Kearney 2020-04-06 17:23:44 +10:00
commit 3ccfe2477f
2 changed files with 81 additions and 0 deletions

View file

@ -210,3 +210,54 @@ if (!function_exists(__NAMESPACE__."\display_error_and_exit")) {
exit(1); exit(1);
} }
} }
/*
* Uses proc_open() to run a command on the shell. Output and errors are captured
* and returned. If the command "fails" to run (i.e. return code is != 0), this
* function will throw an exception.
*
* Note that some commands will return a non-zero status code to signify, for
* example, no results found. This function is unable to tell the difference and
* will trigger an exception regardless. In this instance, It is advised to trap
* that exception and inspect both $stderr and $stdout to decide if it was
* actually due to failed command execution.
*
* @param string $command the full bash command to run
* @param string $stdout (optional) reference to capture output from STDOUT
* @param string $stderr (optional) reference to capture output from STDERR
*
* @throws RunCommandFailedException
*/
if (!function_exists(__NAMESPACE__.'\run_command')) {
function run_command(string $command, string &$stdout = null, string &$stderr = null): void
{
$pipes = null;
$return = null;
$proc = proc_open(
$command,
[
['pipe', 'r'], // STDIN
['pipe', 'w'], // STDOUT
['pipe', 'w'], // STDERR
],
$pipes,
getcwd(),
null
);
if (true == is_resource($proc)) {
$stdout = trim(stream_get_contents($pipes[1]));
$stderr = trim(stream_get_contents($pipes[2]));
// Check the return code. If it's not 0, then the command failed.
if (0 != proc_close($proc)) {
throw new Exceptions\RunCommandFailedException($command, (string) $stderr);
}
} else {
// Something went horribly wrong with proc_open(). This should
// nearly never happen, but, accounting for it regardless.
throw new Exceptions\RunCommandFailedException($command, 'proc_open() returned FALSE');
}
}
}

View file

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace pointybeard\Helpers\Functions\Cli\Exceptions;
use pointybeard\Helpers\Exceptions\ReadableTrace;
class RunCommandFailedException extends ReadableTrace\ReadableTraceException
{
private $command;
private $error;
public function __construct(string $command, string $error, int $code = 0, \Exception $previous = null)
{
$this->command = $command;
$this->error = $error;
parent::__construct("Failed to run command. Returned: {$error}", $code, $previous);
}
public function getCommand(): string
{
return $this->command;
}
public function getError(): string
{
return $this->error;
}
}