2017 © Pedro Peláez
 

library shell-command

A basic wrapper around execution of shell commands.

image

ptlis/shell-command

A basic wrapper around execution of shell commands.

  • Thursday, June 28, 2018
  • by ptlis
  • Repository
  • 1 Watchers
  • 11 Stars
  • 819 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 2 Forks
  • 0 Open issues
  • 33 Versions
  • 13 % Grown

The README.md

ptlis/shell-command

A developer-friendly wrapper around execution of shell commands., (*1)

There were several goals that inspired the creation of this package:, (*2)

  • Use the command pattern to encapsulate the data required to execute a shell command, allowing the command to be passed around and executed later.
  • Maintain a stateless object graph allowing (for example) the spawning of multiple running processes from a single command.
  • Provide clean APIs for synchronous and asynchronous usage.
  • Running processes can be wrapped in promises to allow for easy composition.

Build Status codecov Latest Stable Version, (*3)

Install

From the terminal:, (*4)

$ composer require ptlis/shell-command

Usage

The Builder

The package ships with a command builder, providing a simple and safe method to build commands., (*5)

use ptlis\ShellCommand\CommandBuilder;

$builder = new CommandBuilder();

The builder will attempt to determine your environment when constructed, you can override this by specifying an environment as the first argument:, (*6)

use ptlis\ShellCommand\CommandBuilder;
use ptlis\ShellCommand\UnixEnvironment;

$builder = new CommandBuilder(new UnixEnvironment());

Note: this builder is immutable - method calls must be chained and terminated with a call to buildCommand like so:, (*7)

$command = $builder
    ->setCommand('foo')
    ->addArgument('--bar=baz')
    ->buildCommand()

Set Command

First we must provide the command to execute:, (*8)

$builder->setCommand('git')             // Executable in $PATH

$builder->setCommand('./local/bin/git') // Relative to current working directory

$builder->setCommand('/usr/bin/git')    // Fully qualified path

$build->setCommand('~/.script.sh')      // Path relative to $HOME

If the command is not locatable a RuntimeException is thrown., (*9)

Set Process Timeout

The timeout (in microseconds) sets how long the library will wait on a process before termination. Defaults to -1 which never forces termination., (*10)

$builder
    ->setTimeout(30 * 1000 * 1000)          // Wait 30 seconds

If the process execution time exceeds this value a SIGTERM will be sent; if the process then doesn't terminate after a further 1 second wait then a SIGKILL is sent., (*11)

Set Poll Timeout

Set how long to wait (in microseconds) between polling the status of processes. Defaults to 1,000,000 (1 second)., (*12)

$builder
    ->setPollTimeout(30 * 1000 * 1000)          // Wait 30 seconds

Set Working Directory

You can set the working directory for a command:, (*13)

$builder
    ->setCwd('/path/to/working/directory/')

Add Arguments

Add arguments to invoke the command with (all arguments are escaped):, (*14)

$builder
    ->addArgument('--foo=bar')

Conditionally add, depending on the result of an expression:, (*15)

$builder
    ->addArgument('--foo=bar', $myVar === 5)

Add several arguments:, (*16)

$builder
    ->addArguments([
        '--foo=bar',
        '-xzcf',
        'if=/dev/sda of=/dev/sdb'
    ])

Conditionally add, depending on the result of an expression:, (*17)

$builder
    ->addArguments([
        '--foo=bar',
        '-xzcf',
        'if=/dev/sda of=/dev/sdb'
    ], $myVar === 5)

Note: Escaped and raw arguments are added to the command in the order they're added to the builder. This accommodates commands that are sensitive to the order of arguments., (*18)

Add Raw Arguments

WARNING: Do not pass user-provided data to these methods! Malicious users could easily execute arbitrary shell commands., (*19)

Arguments can also be applied without escaping:, (*20)

$builder
    ->addRawArgument("--foo='bar'")

Conditionally, depending on the result of an expression:, (*21)

$builder
    ->addRawArgument('--foo=bar', $myVar === 5)

Add several raw arguments:, (*22)

$builder
    ->addRawArguments([
        "--foo='bar'",
        '-xzcf',
    ])

Conditionally, depending on the result of an expression:, (*23)

$builder
    ->addRawArguments([
        '--foo=bar',
        '-xzcf',
        'if=/dev/sda of=/dev/sdb'
    ], $myVar === 5)

Note: Escaped and raw arguments are added to the command in the order they're added to the builder. This accommodates commands that are sensitive to the order of arguments., (*24)

Add Environment Variables

Environment variables can be set when running a command:, (*25)

$builder
    ->addEnvironmentVariable('TEST_VARIABLE', '123')

Conditionally, depending on the result of an expression:, (*26)

$builder
    ->addEnvironmentVariable('TEST_VARIABLE', '123', $myVar === 5)

Add several environment variables:, (*27)

$builder
    ->addEnvironmentVariables([
        'TEST_VARIABLE' => '123',
        'FOO' => 'bar'
    ])

Conditionally, depending on the result of an expression:, (*28)

$builder
    ->addEnvironmentVariables([
        'TEST_VARIABLE' => '123',
        'FOO' => 'bar'
    ], $foo === 5)

Add Process Observers

Observers can be attached to spawned processes. In this case we add a simple logger:, (*29)

$builder
    ->addProcessObserver(
        new AllLogger(
            new DiskLogger(),
            LogLevel::DEBUG
        )
    )

Build the Command

One the builder has been configured, the command can be retrieved for execution:, (*30)

$command = $builder
    // ...
    ->buildCommand();

Synchronous Execution

To run a command synchronously use the runSynchronous method. This returns an object implementing CommandResultInterface, encoding the result of the command., (*31)

$result = $command
    ->runSynchronous(); 

When you need to re-run the same command multiple times you can simply invoke runSynchronous repeatedly; each call will run the command returning the result to your application., (*32)

The exit code & output of the command are available as methods on this object:, (*33)

$result->getExitCode();         // 0 for success, anything else conventionally indicates an error
$result->getStdOut();           // The contents of stdout (as a string)
$result->getStdOutLines();      // The contents of stdout (as an array of lines)
$result->getStdErr();           // The contents of stderr (as a string)
$result->getStdErrLines();      // The contents of stderr (as an array of lines)
$result->getExecutedCommand();  // Get the executed command as a string, including environment variables
$result->getWorkingDirectory(); // Get the directory the command was executed in 

Asynchronous Execution

Commands can also be executed asynchronously, allowing your program to continue executing while waiting for the result., (*34)

Command::runAsynchronous

The runAsynchronous method returns an object implementing the ProcessInterface which provides methods to monitor the state of a process., (*35)

$process = $command->runAsynchronous();

As with the synchronouse API, when you need to re-run the same command multiple times you can simply invoke runAsynchronous repeatedly; each call will run the command returning the object representing the process to your application., (*36)

Process API

ProcessInterface provides the methods required to monitor and manipulate the state and lifecycle of a process., (*37)

Check whether the process has completed:, (*38)

if (!$process->isRunning()) {
    echo 'done' . PHP_EOL;
}

Force the process to stop:, (*39)

$process->stop();

Wait for the process to stop (this blocks execution of your script, effectively making this synchronous):, (*40)

$process->wait();

Get the process id (throws a \RuntimeException if the process has ended):, (*41)

$process->getPid();

Read output from a stream:, (*42)

$stdOut = $process->readStream(ProcessInterface::STDOUT);

Provide input (e.g. via STDIN):, (*43)

$process->writeInput('Data to pass to the running process via STDIN');

Get the exit code (throws a \RuntimeException if the process is still running):, (*44)

$exitCode = $process->getExitCode();

Send a signal (SIGTERM or SIGKILL) to the process:, (*45)

$process->sendSignal(ProcessInterface::SIGTERM);

Get the string representation of the running command:, (*46)

    $commandString = $process->getCommand();

Process::getPromise

Monitoring of shell command execution can be wrapped in a ReactPHP Promise. This gives us a flexible execution model, allowing chaining (with Promise::then) and aggregation using Promise::all, Promise::some, Promise::race and their friends., (*47)

Building promise to execute a command can be done by calling the getPromise method from a Process instance. This returns an instance of \React\Promise\Promise:, (*48)

$eventLoop = \React\EventLoop\Factory::create();

$promise = $command->runAsynchonous()->getPromise($eventLoop);

The ReactPHP EventLoop component is used to periodically poll the running process to see if it has terminated yet; once it has the promise is either resolved or rejected depending on the exit code of the executed command., (*49)

The effect of this implementation is that once you've created your promises, chains and aggregates you must invoke EventLoop::run:, (*50)

$eventLoop->run();

This will block further execution until the promises are resolved/rejected., (*51)

Mocking

Mock implementations of the Command & Builder interfaces are provided to aid testing., (*52)

By type hinting against the interfaces, rather than the concrete implementations, these mocks can be injected & used to return pre-configured result objects., (*53)

Contributing

You can contribute by submitting an Issue to the issue tracker, improving the documentation or submitting a pull request. For pull requests i'd prefer that the code style and test coverage is maintained, but I am happy to work through any minor issues that may arise so that the request can be merged., (*54)

Known limitations

  • Supports UNIX environments only.

The Versions

28/06 2018

dev-feature/deferred-factory

dev-feature/deferred-factory

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

12/06 2018

dev-master

9999999-dev

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

11/06 2018

0.16.6

0.16.6.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

10/06 2018

0.16.4

0.16.4.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

10/06 2018

0.16.3

0.16.3.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

10/06 2018

0.16.2

0.16.2.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

08/06 2018

dev-feature/improve-process-observers

dev-feature/improve-process-observers

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

08/06 2018

0.16.1

0.16.1.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

02/06 2018

0.16.0

0.16.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

28/02 2018

0.15.0

0.15.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

28/02 2018

0.14.0

0.14.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

25/07 2017

0.13.1

0.13.1.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

29/06 2017

v0.13.0

0.13.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

04/06 2017

v0.12.1

0.12.1.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

04/06 2017

v0.12.0

0.12.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

 

The Development Requires

command exec process shell run execute

18/05 2017

v0.11.5

0.11.5.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.5.0

 

The Development Requires

command exec process shell run execute

24/03 2017

v0.11.4

0.11.4.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.5.0

 

The Development Requires

command exec process shell run execute

12/03 2017

v0.11.3

0.11.3.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.5.0

 

The Development Requires

command exec process shell run execute

11/03 2017

v0.11.2

0.11.2.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.5.0

 

The Development Requires

command exec process shell run execute

11/03 2017

v0.11.1

0.11.1.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.5.0

 

The Development Requires

command exec process shell run execute

11/03 2017

v0.11.0

0.11.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.5.0

 

The Development Requires

command exec process shell run execute

03/02 2017

v0.10.2

0.10.2.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

03/02 2017

v0.10.1

0.10.1.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

29/01 2017

v0.10.0

0.10.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

10/01 2017

v0.9.0

0.9.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

15/03 2015

v0.8.0

0.8.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

12/03 2015

v0.7.0

0.7.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

02/03 2015

v0.6.0

0.6.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

17/02 2015

v0.5.0

0.5.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

14/02 2015

v0.4.0

0.4.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

11/02 2015

v0.3.0

0.3.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec process shell run execute

21/01 2015

v0.2.0

0.2.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec shell

20/01 2015

v0.1.0

0.1.0.0

A basic wrapper around execution of shell commands.

  Sources   Download

MIT

The Requires

  • php >=5.3.0

 

The Development Requires

command exec shell