kamermans/command

PHP的外部命令运行器/执行器

v1.2.4 2017-09-29 19:06 UTC

This package is auto-updated.

Last update: 2024-09-07 05:22:30 UTC


README

Build Status

PHP的外部命令运行器/执行器。这是一个面向对象的、健壮的execshell_exec、反引号操作符等的替代品。

由于PHP中proc_open()支持不完整,此包在Windows上无法可靠地工作。

此包受到了http://pollinimini.net/blog/php-command-runner/的启发。

运行命令

在其最简单的形式中,您可以像这样执行命令

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

添加参数和选项

在这里我们安全地添加参数

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();

使用回调进行增量更新

通常所有命令输出都会被缓冲,一旦命令完成,就可以访问它。通过使用回调,输出将被缓冲,直到接收到的字节数达到所需数量(见Command::setReadBuffer(int $bytes)),然后传递到您的回调函数

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();

或者,您可以将Command::run(string $stdin, bool $lines)的第二个参数设置为true,以便对每一行输出执行一次回调

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);

流式传输大命令输出

默认情况下,STDOUT和STDERR被PHP收集。如果您有大量数据要传递给命令,您应该以流的形式输入(见下面的STDIN来自流)。如果您有来自命令的大量输出,您应该使用回调以流的形式输出

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);

不转义运行命令

默认情况下,传递给Command::factory(string $command, bool $escape)的命令是转义的,所以像|>这样的字符将被分别替换为\|\>。为了防止命令工厂转义您的命令,您可以将第二个参数传递为true

use kamermans\Command\Command;

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

echo $cmd->getStdOut();

输出到STDERR

要将内容输出到您的STDERR,有一个辅助函数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();

使用STDIN

您可以使用字符串或流资源(如文件句柄)提供STDIN的数据

STDIN来自字符串

use kamermans\Command\Command;

$stdin = "banana
orange
apple
pear
";

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

echo $cmd->getStdOut();

STDIN来自流

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";

您的系统的STDIN也是一个流,因此您可以接受在命令行中键入的输入或通过管道传递到您的脚本中的输入

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();

更多功能

  • StdIn数据可以作为run()的参数提供给进程
  • 使用setEnv()为进程设置环境变量
  • option()的第二个参数和argument()的参数默认是自动转义的。
  • 选项分隔符默认为空格,可以通过手动将第三个参数设置为option()或使用setOptionSeparator()设置新的默认值来更改。
  • 为了方便起见,proc_open包装器作为静态方法公开Command::exec()