Executor
Executor is a collection of wrappers for PHP's command execution functions., (*1)
- These classes takes care of escaping, preventing command injection
- Class interface to each of php's command execution functions. Common
functionality like exit codes and output have logical wrappers.
- Complex cases like proc_open() have additional helpers to make use easier
Installation
Composer, (*2)
require {
"fool/executor": "1.3.0"
}
PSR4 Autoloader, (*3)
Source: Namespace Prefix: fool Base Directory: src/fool, (*4)
Tests: Namsepace Prefix: fool\test Base Directory: test/fool, (*5)
There's an example of autoloading with a PSR4 compatible autoloader in the source., (*6)
Note: The normal installation includes tests and executables you do not need unless you intend to run tests or develop extensions. For a minimum installation you can delete everything but the src directory., (*7)
Examples
There are real executable examples for every type Executor in the source., (*8)
grep $userName error.log-2013-12-23, (*9)
:::php
$grep = new Exec('grep', array($user->getName(), 'error.log-2013-12-23'));
$grep->execute();
if ($grep->wasSuccessful()) {
echo implode(PHP_EOL, $grep->getOutput()); /* exec() returns an array of lines */
} else {
echo "grep failed with exit status " . $this->getExitStatus() . PHP_EOL;
}
Running command multiple times, (*10)
:::php
$ps = new Passthru('ps', array('aux'));
while(true) {
$ps->execute();
sleep(5);
}
Comparisons
Vanilla PHP executing a command safely. Escaping arguments,
and checking exit status., (*11)
:::php
$output = array();
$exitStatus = 0;
$command = 'command' . escapeshellarg($argument);
$lastLineOfOutput = exec($command, $output, $exitStatus);
id ($exitStatus !== 0) {
echo $exitStatus;
} else {
echo implode(PHP_EOL, $output);
}
Equivalent using Executor:, (*12)
:::php
$exec = new Exec();
$exec->setProgram('command');
$exec->addArgument($argument);
$lastLineOfOutput = $exec->execute();
if (!$exec->wasSuccessful()) {
echo $exec->getExitStatus();
} else {
echo implode(PHP_EOL, $exit->getOutput();
}
Vanilla PHP:, (*13)
:::php
$composer = trim(shell_exec('locate composer.phar'));
Equivalent using Executor:, (*14)
:::php
$shellExec = new ShellExec('locate', array('composer.phar'));
$composer = trim($shellExec->execute());
Here's a more complex case with piping programs to each other using PHP. Imagine you had a program named 'echo.php'
and it echo out any argument or standard in when no arguments., (*15)
Youwant to set up a call to echo.php, pipe the ouput to another call to echo.php, and then read the final output.
This is a contrived example with echoing output but it demonstrates chaining many commands with proc open's features
available., (*16)
Vanilla PHP:, (*17)
:::php
$pipes = array();
$descriptorspec = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w'),
);
$resource1 = proc_open('php bin/echo.php', $descriptorspec, $pipes);
$descriptorspec2 = array(
0 => $pipes[1],
1 => array('pipe', 'w'),
2 => array('pipe', 'w'),
);
$pipes2 = array();
$resource2 = proc_open('php bin/echo.php', $descriptorspec2, $pipes2);
fwrite($pipes[0], 'hello world');
fclose($pipes[0]);
$result = stream_get_contents($pipes2[1]);
$pipesToClose = array($pipes[1], $pipes[2], $pipes2[0], $pipes2[1], $pipes2[2]);
foreach ($pipesToClose as $pipe) {
if (is_resource($pipe)) {
fclose($pipe);
}
}
if (is_resource($resource1)) {
proc_close($resource1);
}
if (is_resource($resource2)) {
proc_close($resource2);
}
echo $result;
Equivalent Executor:, (*18)
:::php
$echo1 = new ProcOpen('php', array('bin/echo.php'));
$echo2 = new ProcOpen('php', array('bin/echo.php'));
$echo1->pipeTo($echo2);
$echo1->execute();
$standardIn = $echo1->getStandardIn();
fwrite($standardIn, 'hello world');
fclose($standardIn);
$echo1->close();
$standardOut = $echo2->getStandardOut();
$result = stream_get_contents($standardOut);
$echo2->close();
echo $result;