PHPackages                             kamermans/command - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. kamermans/command

ActiveLibrary

kamermans/command
=================

External command runner / executor for PHP

v1.2.4(8y ago)68.7k2[1 issues](https://github.com/kamermans/command/issues)2BSDPHPPHP &gt;=5.4

Since Dec 15Pushed 8y ago1 watchersCompare

[ Source](https://github.com/kamermans/command)[ Packagist](https://packagist.org/packages/kamermans/command)[ RSS](/packages/kamermans-command/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (1)Versions (13)Used By (2)

kamermans/command
=================

[](#kamermanscommand)

[![Build Status](https://camo.githubusercontent.com/d85f6446f9947997da991800109a0c9e1a6706c67e6b624760c910ae7e43cbec/68747470733a2f2f7472617669732d63692e6f72672f6b616d65726d616e732f636f6d6d616e642e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/kamermans/command)

External command runner / executor for PHP. This is an object oriented, robust replacement for `exec`, `shell_exec`, the backtick operator and the like.

**This package does not work reliably in Windows due to a lack of complete `proc_open()` support in PHP**

> This package is inspired by .

Running Commands
----------------

[](#running-commands)

At its simplest form, you can execute commands like this:

```
$cmd = Command::factory('ls')->run();
```

### Adding Arguments and Options

[](#adding-arguments-and-options)

Here we are safely adding arguments:

```
use kamermans\Command\Command;

$cmd = Command::factory('/usr/bin/svn')
    ->option('--username', 'drslump')
    ->option('-r', 'HEAD')
    ->option('log')
    ->argument('http://code.google.com/drslump/trunk')
    ->run();

echo $cmd->getStdOut();
```

### Using a Callback for Incremental Updates

[](#using-a-callback-for-incremental-updates)

Normally all command output is buffered and once the command completes you can access it. By using a callback, the output is buffered until the desired number of bytes is received (see `Command::setReadBuffer(int $bytes)`), then it is passed to your callback function:

```
use kamermans\Command\Command;

$cmd = Command::factory('ls')
    ->setCallback(function($pipe, $data) {
        // Gets run for every 4096 bytes
        echo $data;
    })
    ->setReadBuffer(4096)
    ->setDirectory('/tmp')
    ->option('-l')
    ->run();
```

Alternately, you can set the second argument for `Command::run(string $stdin, bool $lines)` to `true` to execute your callback once for every line of output:

```
use kamermans\Command\Command;

$cmd = Command::factory('ls')
    ->setCallback(function($pipe, $data){
        // Gets run for each line of output
        echo $data;
    })
    ->setDirectory('/tmp')
    ->option('-l')
    ->run(null, true);
```

### Streaming large command output

[](#streaming-large-command-output)

The STDOUT and STDERR is collected inside PHP by default. If you have a large amount of data to pass into the command, you should stream it in (see STDIN from a stream below). If you have a large amount of output from the command, you should stream it out using a callback:

```
use kamermans\Command\Command;

require_once __DIR__.'/../vendor/autoload.php';

$filename = __DIR__.'/../README.md';
$stdin = fopen($filename, 'r');

// This will read README.md and grep for lines containing 'the'
$cmd = Command::factory("grep 'the'")
    ->setCallback(function($pipe, $data) {
        // Change the text to uppercase
        $data = strtoupper($data);

        if ($pipe === Command::STDERR) {
            Command::echoStdErr($data);
        } else {
            echo $data;
        }
    })
    ->run($stdin);

fclose($stdin);
```

### Running a Command without Escaping

[](#running-a-command-without-escaping)

By default, the command passed to `Command::factory(string $command, bool $escape)` is escaped, so characters like `|` and `>` will replaced with `\|` and `\>` respectively. To prevent the command factory from escaping your command, you can pass `true` as the second argument:

```
use kamermans\Command\Command;

$cmd = Command::factory('grep CRON < /var/log/syslog | head', true)->run();

echo $cmd->getStdOut();
```

### Outputting to STDERR

[](#outputting-to-stderr)

To output content to your `STDERR` there is a helper function `Command::echoStdErr(string $content)`:

```
use kamermans\Command\Command;

$cmd = Command::factory('grep CRON < /var/log/syslog | head', true)
    ->setCallback(function($pipe,$data) {
        if ($pipe === Command::STDERR) {
            Command::echoStdErr($data);
        } else {
            echo $data;
        }
    })
    ->run();
```

Using STDIN
-----------

[](#using-stdin)

You can provide data for STDIN using a string or a stream resource (like a file handle)

### STDIN from a String

[](#stdin-from-a-string)

```
use kamermans\Command\Command;

$stdin = "banana
orange
apple
pear
";

$cmd = Command::factory("sort")
    ->run($stdin);

echo $cmd->getStdOut();
```

### STDIN from a Stream

[](#stdin-from-a-stream)

```
use kamermans\Command\Command;

$filename = __DIR__.'/../README.md';
$stdin = fopen($filename, 'r');

// This will count the number of words in the README.md file
$cmd = Command::factory("wc")
    ->option("--words")
    ->run($stdin);

fclose($stdin);

$words = trim($cmd->getStdOut());
echo "File $filename contains $words words\n";
```

Your system's `STDIN` is also a stream, so you can accept input that is typed on the command line or piped into your script as well:

```
use kamermans\Command\Command;

echo "Type some words, one per line, then press CTRL-D and they will be sorted:\n";

$cmd = Command::factory("sort")
    // This causes Command to use the real STDIN
    ->run(STDIN);

echo "\n";
echo $cmd->getStdOut();
```

Some more features:

- `StdIn` data can be provided to the process as a parameter to `run()`
- Set environment variables for the process with `setEnv()`
- Second argument to `option()` and argument to `argument()` are automatically escaped.
- Options separator is white space by default, it can be changed by manually setting it as third argument to `option()` or setting a new default with `setOptionSeparator()`.
- The `proc_open` wrapper is exposed as a static method for your convenience `Command::exec()`

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance17

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 97.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~102 days

Total

11

Last Release

3152d ago

Major Versions

v0.9.1 → v1.02014-12-17

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/266265?v=4)[Steve Kamerman](/maintainers/kamermans)[@kamermans](https://github.com/kamermans)

---

Top Contributors

[![kamermans](https://avatars.githubusercontent.com/u/266265?v=4)](https://github.com/kamermans "kamermans (41 commits)")[![lucor](https://avatars.githubusercontent.com/u/313577?v=4)](https://github.com/lucor "lucor (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/kamermans-command/health.svg)

```
[![Health](https://phpackages.com/badges/kamermans-command/health.svg)](https://phpackages.com/packages/kamermans-command)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
