edrisa / command
PHP的外部命令运行器/执行器
Requires
- php: >=5.4
Requires (Dev)
- phpunit/phpunit: 4.*
This package is auto-updated.
Last update: 2024-09-04 17:15:42 UTC
README
PHP的外部命令运行器/执行器。这是一个面向对象的、健壮的exec
、shell_exec
、反引号操作符等的替代品。
由于PHP中proc_open()
支持不完整,此包在Windows上无法可靠地运行。
运行命令
在最简单的形式中,您可以像这样执行命令
$cmd = Command::factory('ls')->run();
添加参数和选项
在这里我们安全地添加参数
use Edrisa\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 Edrisa\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 Edrisa\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 Edrisa\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 Edrisa\Command\Command; $cmd = Command::factory('grep CRON < /var/log/syslog | head', true)->run(); echo $cmd->getStdOut();
输出到STDERR
要将内容输出到STDERR
,有一个辅助函数Command::echoStdErr(string $content)
use Edrisa\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 Edrisa\Command\Command; $stdin = "banana orange apple pear "; $cmd = Command::factory("sort") ->run($stdin); echo $cmd->getStdOut();
STDIN来自流
use Edrisa\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 Edrisa\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()