rikanishu / php-multi-process
用于并行执行shell命令的PHP库
Requires
- php: >=5.4.0
Requires (Dev)
This package is not auto-updated.
Last update: 2024-09-28 15:00:40 UTC
README
用于并行执行shell命令的PHP库 
通过composer安装
运行以下命令之一
php composer.phar require rikanishu/php-multi-process "*"
或在你的 composer.json
文件的 require
部分添加
"rikanishu/php-multi-process": "*"
以下内容。
示例
$cmd1 = ['echo', '"Some Command"']; $cmd2 = 'echo "Another Command"'; $cmd3 = ['echo "$SOME_ENV_VAR" "$PWD"', [ rikanishu\multiprocess\Command::OPTION_CWD => '/tmp', rikanishu\multiprocess\Command::OPTION_ENV => [ 'SOME_ENV_VAR' => 'PWD is:' ], ]]; $cmd4 = new rikanishu\multiprocess\Command('cat'); $cmd4->setStdin('hello world'); $pool = new rikanishu\multiprocess\Pool([$cmd1, $cmd2, $cmd3, $cmd4]); $pool->run(); /* @var $command rikanishu\multiprocess\Command */ foreach ($pool->getCommands() as $command) { $res = $command->getExecutionResult(); echo $res->getExitCode() . " | " . $res->getStdout() . " | " . $res->getStderr() . "\n"; } /* Output: 0 | Some Command | 0 | Another Command | 0 | PWD is: /tmp | */ $commands = $pool->getCommands(); $commands[0]->getExecutionResult()->getOutput(); // Some Command $commands[1]->getExecutionResult()->getOutput(); // Another Command $commands[2]->getExecutionResult()->getOutput(); // PWD is: /tmp $commands /* And also library provides single command execution */ $command = new rikanishu\multiprocess\Command('echo "Hello World!"'); $command->runBlocking()->getOutput(); // Hello World
描述
此库旨在在阻塞/非阻塞模式下执行单个/多个并行进程。该库提供了一种方便的配置外部进程执行的方法。基本概念是Pool和Command对象。Pool是一组创建并委托执行给ExecutionContext的命令。ExecutionContext为每个命令构建Process对象并运行它。Command对象代表单个外部命令。
该库使用由标准PHP库提供的proc_* API和select系统调用。它没有外部依赖。
使用方法
一般的用法场景表明,你可以将一些命令传递给一个Pool实例,该实例将在阻塞/非阻塞模式下并行执行,具体取决于传递的参数。以下是非阻塞执行四个命令的示例
$cmd1 = ['echo', '"Some Command"']; $cmd2 = 'echo "Another Command"'; $cmd3 = ['echo "$SOME_ENV_VAR" "$PWD"', [ rikanishu\multiprocess\Command::OPTION_CWD => '/tmp', rikanishu\multiprocess\Command::OPTION_ENV => [ 'SOME_ENV_VAR' => 'PWD is:' ], ]]; $cmd4 = new rikanishu\multiprocess\Command('cat'); $cmd4->setStdin('hello world'); $pool = new rikanishu\multiprocess\Pool([$cmd1, $cmd2, $cmd3, $cmd4]); $pool->run(); /* @var $command rikanishu\multiprocess\Command */ foreach ($pool->getCommands() as $command) { $res = $command->getExecutionResult(); echo $res->getExitCode() . " | " . $res->getStdout() . " | " . $res->getStderr() . "\n"; }
$cmd1
、$cmd2
、$cmd3
和 $cmd4
显示了Pool应用的命令的不同格式。你也可以直接传递Command实例,因为Pool隐式地将shell命令文本转换为Command实例,并首先检查此类输入数据。
… $cmd5 = new rikanishu\multiprocess\Command(‘echo instance’); … $pool = new rikanishu\multiprocess\Pool([$cmd1, $cmd2, $cmd3, $cmd4, $cmd5]); $pool->run();
Pool的run()
方法返回代表每个命令的Futures数组,例如上面的示例中的$future[3]
代表$cmd4
。你可以始终使用$command->getFuture()
方法来获取正在执行的命令的当前future。未执行的命令没有future,如果你为未执行的Command调用getFuture()
,将会抛出异常。你可以调用hasFuture()
来检查你的代码不知道,命令是否已经运行或尚未运行。
$cmd1 = ['echo', '"Some Command"']; $cmd2 = 'echo "Another Command"'; $cmd3 = new rikanishu\multiprocess\Command(‘echo instance’); $pool = new rikanishu\multiprocess\Pool([$cmd1, $cmd2, $cmd3]); $futures = $pool->run(); $commands = $pool->getCommands(); print_r(count($commands)); // Count of command objects always equals passed shell commands. Pool raise an exception on creation step if command has invalid format. print_r($cmd3 == $commands[2]); // Equals print_r($commands[1]->hasFuture()); // True, command is running print_r($commands[1]->getFuture() == $futures[1]); // Equals print_r($commands[1]->getFuture()->getResult()); // Block and waiting execution result //Or you can block process directly by alias command method print_r($command[1]->getExecutionResult()); // Alias of Future’s getResult()
在非阻塞模式下,$pool->run()
调用创建一个进程数组并返回控制权给调用程序。进程将在后台同时执行,当你调用Future的getResult()
方法时,它将阻塞执行过程直到收到结果或时间限制到期。如果你想避免阻塞并继续你的有用计算过程,你可以始终检查Future的hasResult()
。
$pool = new rikanishu\multiprocess\Pool([$cmd1, $cmd2, $cmd3]); $futures = $pool->run(); … //doing some useful work … if ($furures[1]->hasResult()) { … } //doing another useful work … //block and waiting data finally $result = $futures[1]->getResult();
此外,如果你只需要运行单个命令,可以直接使用命令方法的run()
。它将创建一个新的包含单个命令的Pool并返回Future。使用方法runBlocking()
以阻塞模式运行执行并接收执行结果。
$command = new rikanishu\multiprocess\Command('echo "Hello World!"'); $command->runBlocking()->getOutput(); // Hello World
或者
$command = new rikanishu\multiprocess\Command('echo "Hello World!"'); $future = $command->run(); … // doing some useful work … $future->getResult()->getOutput(); // Hello World
Pool选项
Pool接受一个选项数组作为第二个参数。你可以通过两种方式设置Pool的选项
- 将选项数组作为Pool构造函数的第二个参数传递
$pool = new rikanishu\multiprocess\Pool([$cmd1, $cmd2, $cmd3], [ rikanishu\multiprocess\Pool::OPTION_EXECUTION_TIMEOUT => 120, rikanishu\multiprocess\Pool::OPTION_BLOCKING_MODE => true ]);
- 在创建对象后设置参数
$pool->setExecutionTimeout(120); $pool->setBlockingMode(true);
选项列表
-
OPTION_EXECUTION_TIMEOUT
- 执行过程的秒数限制。小于零的值表示无限制的超时。默认为-1(无限制)。选项的别名方法是$pool->setExecutionTimeout(200)
。 -
OPTION_POLL_TIMEOUT
- 每个选择轮询周期的最大超时时间(秒)。这意味着等待运行中的进程的任何反应的时间,如果没有任何反应(例如,输出到stdout / stderr或停止执行),则在读取进程状态后重试轮询周期。默认值为60秒。此选项的别名方法是$pool->setPollTimeout(120)
。 -
OPTION_SELECT_USLEEP_TIME
- 如果select调用返回false或系统不支持进程轮询(例如在Windows上),则轮询周期的微秒数。默认为200微秒。此选项的别名方法是$pool->setSelectUsleepTime(400)
。 -
OPTION_DEBUG
- 调试模式。启用一些执行调试消息输出。默认为false。此方法的别名是$pool->setDebugEnabled(true)
-
OPTION_BLOCKING_MODE
- 阻塞模式标志。如果使用阻塞模式,则在所有执行时间内进程将被停止。在其他情况下,当前进程可以与Future交互以等待结果或检查执行状态。默认为false,非阻塞模式。此方法的别名是$pool->setBlockingMode(true)
。
命令选项
您可以通过两种方式配置与Pool相同的命令
$command = new rikanishu\multiprocess\Command(‘echo ‘Hello $NAME’’, [ rikanishu\multiprocess\Command::OPTIONS_ENV => [ ‘NAME’ => ‘WORLD’, ], rikanishu\multiprocess\Command::OPTIONS_CWD => ‘/tmp’ ]);
或者
$command->setEnvVariables([ ‘NAME’ => ‘WORLD’, ]); $command->setCwdPath(‘/tmp’);
您还可以在将shell命令作为数组第二个元素传递给Pool构造函数时控制选项
$cmd1 = ‘echo Hello!’; $cmd2 = ['echo "$SOME_ENV_VAR" "$PWD"', [ rikanishu\multiprocess\Command::OPTION_CWD => '/tmp', rikanishu\multiprocess\Command::OPTION_ENV => [ 'SOME_ENV_VAR' => 'PWD is:' ], ]]; $pool = new rikanishu\multiprocess\Pool([$cmd1, $cmd2]); $pool->run();
选项列表
-
OPTION_ENV
- 命令的环境变量列表。默认为null。此选项的别名方法是$command->setEnvVariables([])
。 -
OPTION_CWD
- 命令的当前工作目录。默认为null,CWD从父进程继承。此选项的别名方法是$command->setCwdPath(‘/tmp’)
。 -
OPTION_PROC
- proc_open命令的选项。请参见完整列表在 PHP 文档。此选项的别名方法是$command->setProcOptions([])
。 -
OPTION_STDIN
- 命令的stdin。此选项的别名方法是$command->setStdin('')
。 -
OPTION_DONT_CHECK_RUNNING
- 不要等待执行结束,不要检查进程状态以识别它是否运行或未运行,只需读取stdin/stdout并停止进程。在处理管道以在进程给出任何输出后停止执行进程时非常有用。此选项的别名方法是$command->setDontCheckRunning(true)
。