php 进程类 symfony,Process组件

Process组件在子进程(sub-processes)中执行命令。

超高难内容

译注:本文档并非孤立,建议与Console组件一起学习。本文需要较为高深的computer学科背景知识,请学者注意。

安装 ¶

你可以通过下述两种方式安装:

然后,包容vendor/autoload.php文件,以开启Composer提供的自动加载机制。否则,你的程序将无法找到这个Symfony组件的类。

用法 ¶

1

2

3

4

5

6

7

8

9

10

11

12use Symfony\Component\Process\Process;

use Symfony\Component\Process\Exception\ProcessFailedException;

$process = new Process('ls -lsa');

$process->run();

// executes after the command finishes / 命令完成后执行

if (!$process->isSuccessful()) {

throw new ProcessFailedException($process);

}

echo $process->getOutput();

本组件负责处理在执行命令行时“不同平台之间的微妙区别”。

getOutput() 方法始终返回“命令的标准输出(standard output)”的全部内容,而 getErrorOutput() 返回的是error output的内容。可以选择

3.1

对一个进程的流化输出(streaming the output)支持,是从Symofny3.1开始引入的。

你也可以使用

1

2

3

4

5

6

7

8

9

10$process = new Process('ls -lsa');

$process->start();

foreach ($process as $type => $data) {

if ($process::OUT === $type) {

echo "\nRead from stdout: ".$data;

} else { // $process::ERR === $type

echo "\nRead from stderr: ".$data;

}

}

mustRun() 方法等同于 run(),除了它将抛出一个

1

2

3

4

5

6

7

8

9

10

11

12use Symfony\Component\Process\Exception\ProcessFailedException;

use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');

try {

$process->mustRun();

echo $process->getOutput();

} catch (ProcessFailedException $e) {

echo $e->getMessage();

}

获取实时Process输出 ¶

当执行一个长时间运行的命令时(比如同步文件到远程服务器),你可以把反馈信息实时地返给末级用户,这时要传递一个匿名函数给

1

2

3

4

5

6

7

8

9

10use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');

$process->run(function ($type, $buffer) {

if (Process::ERR === $type) {

echo 'ERR > '.$buffer;

} else {

echo 'OUT > '.$buffer;

}

});

运行异步进程 ¶

你也可以启用子进程,并让它异步运行,在你需要的时候,取出output和主进程状态。使用

1

2

3

4

5

6

7

8$process = new Process('ls -lsa');

$process->start();

while ($process->isRunning()) {

// waiting for process to finish / 等待进程完成

}

echo $process->getOutput();

异步启动时,你也可以等待进程结束,然后再做些事情:

1

2

3

4

5

6

7

8

9$process = new Process('ls -lsa');

$process->start();

// ... do other things / 做一些事

$process->wait();

// ... do things after the process has finished

// .. 在进程完成后做一些事

1

2

3

4

5

6

7

8

9

10$process = new Process('ls -lsa');

$process->start();

$process->wait(function ($type, $buffer) {

if (Process::ERR === $type) {

echo 'ERR > '.$buffer;

} else {

echo 'OUT > '.$buffer;

}

});

---流化Process的标准Input---

3.1

对一个进程的input进行流化,是从Symfony 3.1开始支持的。

在进程启动之前,你可以使用

1

2

3$process = new Process('cat');

$process->setInput('foobar');

$process->run();

当input被完全写到子进程的standard input时,对应的pipe将关闭。

为了能对一个“正在运行”的子进程编写standard input,本组件提供了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17$input = new InputStream();

$input->write('foo');

$process = new Process('cat');

$process->setInput($input);

$process->start();

// ... read process output or do other things

// ... 读取进程的output,或者做其他事

$input->write('bar');

$input->close();

$process->wait();

// will echo: foobar / 将执行echo: foobar

echo $process->getOutput();

中止一个进程 ¶

任何一个异步进程都可以通过 SIGKILL。请参考 下文的signal文档 来了解Process组件中关于“信号处理”(signal handling)的更多内容:

1

2

3

4

5

6$process = new Process('ls -lsa');

$process->start();

// ... do other things / 做其他事

$process->stop(3, SIGINT);

孤立执行PHP代码 ¶

如果你希望在孤立状态下执行一些PHP代码,使用 PhpProcess 来替代:

1

2

3

4

5

6

7use Symfony\Component\Process\PhpProcess;

$process = new PhpProcess(<<

EOF

);

$process->run();

要确保代码能更好地运行于全部平台之上,你可能需要使用

1

2

3

4use Symfony\Component\Process\ProcessBuilder;

$builder = new ProcessBuilder(array('ls', '-lsa'));

$builder->getProcess()->run();

如果你在构建一个二进制驱动(binary driver),可以使用

下例将为一个tar binary adapter生成两个进程命令:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16use Symfony\Component\Process\ProcessBuilder;

$builder = new ProcessBuilder();

$builder->setPrefix('/usr/bin/tar');

// '/usr/bin/tar' '--list' '--file=archive.tar.gz'

echo $builder

->setArguments(array('--list', '--file=archive.tar.gz'))

->getProcess()

->getCommandLine();

// '/usr/bin/tar' '-xzf' 'archive.tar.gz'

echo $builder

->setArguments(array('-xzf', 'archive.tar.gz'))

->getProcess()

->getCommandLine();

Process超时 ¶

你可以限制进程在完成过程中所耗费的时间数,设置一个timeout(以秒计)即可:

1

2

3

4

5use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');

$process->setTimeout(3600);

$process->run();

对于长耗时命令,你的职责就是对超时进行例行检查:

1

2

3

4

5

6

7

8

9

10

11

12$process->setTimeout(3600);

$process->start();

while ($condition) {

// ...

// check if the timeout is reached

// 检查是否到达时限

$process->checkTimeout();

usleep(200000);

}

进程空闲超时 ¶

相对于前面的超时,空间超时(idle timeout)只计算从“上一次output被进程输出”开始的时间:

1

2

3

4

5

6use Symfony\Component\Process\Process;

$process = new Process('something-with-variable-runtime');

$process->setTimeout(3600);

$process->setIdleTimeout(60);

$process->run();

上例如,一个进程将在总体运行时间超过3600秒,或是60秒内进程没有产生任何output时,被认定超时。

进程的信号 ¶

当异步运行一个程序时,你可以发送通过

1

2

3

4

5

6

7

8use Symfony\Component\Process\Process;

$process = new Process('find / -name "rabbit"');

$process->start();

// will send a SIGKILL to the process

// 将发送一个SIGKILL到进程

$process->signal(SIGKILL);

Caution

由于PHP的某些限制,如果你在Process组件中使用signals,你可能不得不对命令施以 exec 前缀。参考 Symfony Issue#5759 和 PHP Bug#39992 以了解为何会如此。

POSIX signals在Windows平台不可用,参考 PHP文档 了解可用的信号。

进程的Pid ¶

你可以访问运行中的进程的 pid,通过

1

2

3

4

5

6use Symfony\Component\Process\Process;

$process = new Process('/usr/bin/php worker.php');

$process->start();

$pid = $process->getPid();

由于PHP的某些限制,如果你要取得一个symfony进程的pid,你可能不得不对自己的命令添加 exec 前缀。参考 Symfony Issue#5759 来理解为何会发生这样的事。

关闭Output ¶

由于standard output和error output总是从背后的进程(underlying process)中被取出,在某些需要节约内存的场景下,关闭output可能更方便。使用

1

2

3

4

5use Symfony\Component\Process\Process;

$process = new Process('/usr/bin/php worker.php');

$process->disableOutput();

$process->run();

进程在运行时,你可以开启或关闭输出。

如果你关闭output,将不能使用 getOutput、getIncrementalOutput、getErrorOutput、getIncrementalErrorOutput 或是 setIdleTimeout。

然而,传入一个callback给 start、run 或 mustRun ,以streaming方式来处理进程的output,是可以的。

3.1

在output被关闭时,“向这些方法传入callback”的能力,从Symofny3.1开始被添加进来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值