过程组件
编辑本页过程组件
Process组件在子进程中执行命令。
安装
1
$作曲家需要交响乐/过程ob娱乐下载
请注意
如果在Symfony应用程序外部安装此组件,则必须要求ob娱乐下载供应商/ autoload.php
文件,以启用Composer提供的类自动加载机制。读这篇文章欲知详情。
使用
的过程类在子进程中执行命令,处理操作系统和转义参数之间的差异,以防止安全问题。它可以替换PHP函数执行,passthru,shell_exec而且系统:
12 3 4 5 6 7 8 9 10 11 12
使用ob娱乐下载\组件\过程\异常\ProcessFailedException;使用ob娱乐下载\组件\过程\过程;$过程=新过程([“ls”,“文理学院”]);$过程->run ();//在命令完成后执行如果(!$过程->isSuccessful ()) {扔新ProcessFailedException ($过程);}回声$过程->getOutput ();
的getOutput ()
方法总是返回命令和标准输出的全部内容getErrorOutput ()
错误输出的内容。或者,getIncrementalOutput ()而且getIncrementalErrorOutput ()方法返回自上次调用以来的新输出。
的clearOutput ()方法清除输出和的内容clearErrorOutput ()清除错误输出的内容。
你也可以使用过程类,以便在生成输出时获取输出。默认情况下,循环在进行下一次迭代之前等待新的输出:
1 2 3 4 5 6 7 8 9 10
$过程=新过程([“ls”,“文理学院”]);$过程->开始();foreach($过程作为$类型= >$数据){如果($过程::出= = =$类型){回声\nRead from stdout: ".$数据;}其他的{// $process::ERR === $type回声\nRead from stderr: ".$数据;}}
提示
Process组件在内部使用一个PHP迭代器来获取生成的输出。迭代器通过getIterator ()
方法来允许自定义其行为:
1 2 3 4 5 6
$过程=新过程([“ls”,“文理学院”]);$过程->开始();$迭代器=$过程->getIterator ($过程::ITER_SKIP_ERR |$过程::ITER_KEEP_OUTPUT);foreach($迭代器作为$数据){回声$数据.“\ n”;}
的mustRun ()
方法与run ()
,除了它会抛出一个ProcessFailedException如果进程不能成功执行(即进程以非零代码退出):
12 3 4 5 6 7 8 9 10 11 12
使用ob娱乐下载\组件\过程\异常\ProcessFailedException;使用ob娱乐下载\组件\过程\过程;$过程=新过程([“ls”,“文理学院”]);试一试{$过程->mustRun ();回声$过程->getOutput ();}抓(ProcessFailedException$异常){回声$异常->getMessage ();}
提示
方法可以获得以秒为单位的最后输出时间getLastOutputTime ()方法。这个方法返回零
如果这个过程没有开始!
配置流程选项
ob娱乐下载Symfony使用PHPproc_open函数运行进程。属性传递的选项other_options
的观点proc_open ()
使用setoption ()
方法:
1 2 3
$过程=新过程(['...','...','...']);//该选项允许子进程在主脚本退出后继续运行$过程->setoption ([“create_new_console”= >真正的]);
使用来自OS Shell的特性
使用参数数组是定义命令的推荐方式。这可以避免任何转义,并允许无缝发送信号(例如,在进程运行时停止进程):
1 2
$过程=新过程([“/道路/命令”,”,选择“,“参数”,“等等。”]);$过程=新过程([/道路/ / php的,“——定义”,“memory_limit = 1024”,“/道路/ / script.php”]);
方法将命令定义为字符串,如果需要使用流重定向、条件执行或操作系统的shell提供的任何其他特性fromShellCommandline ()静态工厂。
每个操作系统都为它们的命令行提供了不同的语法,因此您有责任处理转义和可移植性。
类的第二个参数将变量参数作为环境变量传递run ()
,mustRun ()
或start ()
方法。引用它们也依赖于操作系统:
1 2 3 4 5 6 7 8
//在类unix操作系统(Linux, macOS)上$过程=过程::fromShellCommandline (“回声“元信息””);//在Windows上$过程=过程::fromShellCommandline (“回声”消息!“‘);//在类unix和Windows上$过程->运行(零, (“消息”= >“要输出的东西”]);
如果你喜欢创建独立于操作系统的可移植命令,你可以这样写上面的命令:
1 2
//在Windows、Linux和macOS上工作相同$过程=过程::fromShellCommandline (”echo ${:消息}”);
可移植命令需要使用特定于组件的语法:当将变量名封装到“$ {:
而且}”
正是如此,进程对象将用其转义值替换它,或者如果在附加到命令的环境变量列表中没有找到该变量,则进程对象将失败。
设置进程的环境变量
的构造函数。过程类及其与执行流程相关的所有方法(run ()
,mustRun ()
,start ()
,等等)允许在运行进程时传递一个环境变量数组来设置:
1 2 3
$过程=新过程(['...'],零, (“ENV_VAR_NAME”= >“价值”]);$过程=过程::fromShellCommandline ('...',零, (“ENV_VAR_NAME”= >“价值”]);$过程->运行(零, (“ENV_VAR_NAME”= >“价值”]);
除了显式传递的env变量外,进程还继承系统中定义的所有env变量。可以通过设置为来防止这种情况假
要删除的环境变量:
1 2 3 4
$过程=新过程(['...'],零, (“APP_ENV”= >假,“ob娱乐下载SYMFONY_DOTENV_VARS”= >假]);
获得实时流程输出
当执行一个长时间运行的命令(如rsync
对象的匿名函数可以实时地向最终用户提供反馈run ()方法:
1 2 3 4 5 6 7 8 9 10
使用ob娱乐下载\组件\过程\过程;$过程=新过程([“ls”,“文理学院”]);$过程->运行(函数($类型,$缓冲){如果(过程::呃= = =$类型){回声' err > '.$缓冲;}其他的{回声' out > '.$缓冲;}});
请注意
在使用PHP输出缓冲的服务器中,该特性无法正常工作。在这些情况下,禁用output_bufferingPHP选项或使用ob_flushPHP函数强制发送输出缓冲区。
异步运行进程
您还可以启动子进程,然后让它异步运行,在需要时检索主进程中的输出和状态。使用start ()方法来启动异步进程正在()方法检查进程是否已完成getOutput ()方法获取输出:
1 2 3 4 5 6 7 8
$过程=新过程([“ls”,“文理学院”]);$过程->开始();而($过程->正在()){//等待进程结束}回声$过程->getOutput ();
你也可以等待一个进程结束,如果你异步启动它,并完成了其他事情:
1 2 3 4 5 6 7 8
$过程=新过程([“ls”,“文理学院”]);$过程->开始();/ /……做其他事情$过程->wait ();/ /……在流程完成后再做事情
请注意
的wait ()方法正在阻塞,这意味着您的代码将在这一行停止,直到外部进程完成。
请注意
如果一个响应
发送之前如果子进程有机会完成,服务器进程将被杀死(取决于你的操作系统)。这意味着您的任务将立即停止。运行异步进程与运行其父进程存活下来的进程是不同的。
如果希望流程在请求/响应周期中存活,可以利用kernel.terminate
事件,并运行您的命令同步在此事件内部。请注意kernel.terminate
只在使用PHP-FPM时调用。
谨慎
还要注意的是,如果这样做,在子进程完成之前,上述PHP-FPM进程将无法为任何新请求提供服务。这意味着如果你不够小心,你可能很快就会阻塞你的FPM池。这就是为什么即使在发送请求之后也不要做任何花哨的事情,而是使用作业队列的原因。
wait ()接受一个可选参数:在进程仍在运行时重复调用的回调,传递输出及其类型:
1 2 3 4 5 6 7 8 9 10
$过程=新过程([“ls”,“文理学院”]);$过程->开始();$过程->等待(函数($类型,$缓冲){如果(过程::呃= = =$类型){回声' err > '.$缓冲;}其他的{回声' out > '.$缓冲;}});
方法,而不是等待过程完成,可以使用waitUntil ()方法根据一些PHP逻辑来保持或停止等待。下面的例子启动一个长时间运行的进程,并检查它的输出,直到它完全初始化:
1 2 3 4 5 6 7 8 9 10 11
$过程=新过程([“/ usr / bin / php”,“slow-starting-server.php”]);$过程->开始();/ /……做其他事情//等待直到给定的匿名函数返回true$过程->waitUntil (函数($类型,$输出){返回$输出= = =“准备好了。等待命令……”;});/ /……做事情的过程准备好了吗
流到流程的标准输入
方法指定其标准输入,然后启动流程setInput ()方法或构造函数的第4个参数。提供的输入可以是字符串、流资源或可否认的
对象:
1 2 3
$过程=新过程([“猫”]);$过程->setInput (“foobar”);$过程->run ();
当这个输入完全写入子进程标准输入时,相应的管道将被关闭。
为了在子流程运行时写入子流程标准输入,组件提供了InputStream类:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$输入=新InputStream ();$输入->写(“foo”);$过程=新过程([“猫”]);$过程->setInput ($输入);$过程->开始();/ /……读取流程输出或做其他事情$输入->写(“酒吧”);$输入->close ();$过程->wait ();//将回显:foobar回声$过程->getOutput ();
的write ()方法接受标量、流资源或可否认的
对象作为参数。如上面的示例所示,需要显式调用close ()当您完成对子流程的标准输入的写入时,可以使用。
使用PHP流作为进程的标准输入
流程的输入也可以使用PHP流:
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
$流= fopen (php: / /临时的,“w +”);$过程=新过程([“猫”]);$过程->setInput ($流);$过程->开始();写入文件($流,“foo”);/ /……读取流程输出或做其他事情写入文件($流,“酒吧”);fclose ($流);$过程->wait ();//将回显:'foobar'回声$过程->getOutput ();
使用TTY和PTY模式
上面的所有示例都表明,您的程序可以控制进程的输入(使用setInput ()
)和该进程的输出(使用getOutput ()
).Process组件有两种特殊的模式来调整程序和流程之间的关系:teletype (tty)和伪teletype (pty)。
在TTY模式中,您将流程的输入和输出连接到程序的输入和输出。这允许以进程的形式打开像Vim或Nano这样的编辑器。通过调用启用TTY模式setTty ():
1 2 3 4 5 6 7
$过程=新过程([“活力”]);$过程->setTty (真正的);$过程->run ();//由于输出连接到终端,不再可能//读取或修改进程的输出!转储($过程->getOutput ());/ /空
在PTY模式下,您的程序表现为进程的终端,而不是简单的输入和输出。有些程序在与真实终端交互而不是与另一个程序交互时表现不同。例如,有些程序在与终端通话时提示输入密码。使用setPty ()启用该模式。
停止进程
方法可以在任何时候停止任何异步进程stop ()方法。这个方法有两个参数:一个超时和一个信号。一旦超时,信号就被发送到正在运行的进程。发送给进程的默认信号是SIGKILL
.请细阅信号文档如下欧宝官网下载app以了解更多关于Process组件中信号处理的信息:
1 2 3 4 5 6
$过程=新过程([“ls”,“文理学院”]);$过程->开始();/ /……做其他事情$过程->停止(3.、信号情报);
单独执行PHP代码
如果要单独执行某些PHP代码,请使用PhpProcess
而不是:
1 2 3 4 5 6 7
使用ob娱乐下载\组件\过程\PhpProcess;$过程=新PhpProcess (< < < EOF < ?='Hello World' ?> EOF);$过程->run ();
过程超时
默认情况下,进程的超时时间为60秒,但您可以将不同的超时时间(以秒为单位)传递给setTimeout ()
方法:
1 2 3 4 5
使用ob娱乐下载\组件\过程\过程;$过程=新过程([“ls”,“文理学院”]);$过程->setTimeout (3600);$过程->run ();
如果达到超时,则aProcessTimedOutException抛出。
对于长时间运行的命令,你有责任定期执行超时检查:
1 2 3 4 5 6 7 8 9 10 11
$过程->setTimeout (3600);$过程->开始();而($条件){/ /……//检查是否超时$过程->checkTimeout ();usleep (200000);}
提示
方法可以获取流程开始时间getStartTime ()
方法。
进程空闲超时
与上一段的超时相反,空闲超时只考虑从进程产生最后一个输出到现在的时间:
1 2 3 4 5 6
使用ob娱乐下载\组件\过程\过程;$过程=新过程([“something-with-variable-runtime”]);$过程->setTimeout (3600);$过程->setIdleTimeout (60);$过程->run ();
在上面的例子中,当总运行时超过3600秒,或者进程在60秒内没有产生任何输出时,进程就被认为超时了。
过程的信号
方法向程序发送POSIX信号信号()方法:
1 2 3 4 5 6 7
使用ob娱乐下载\组件\过程\过程;$过程=新过程([“发现”,' / ',“- name”,“兔子”]);$过程->开始();//将向进程发送一个SIGKILL$过程->信号(SIGKILL);
过程Pid
您可以访问pid属性的正在运行进程的getPid ()方法:
1 2 3 4 5 6
使用ob娱乐下载\组件\过程\过程;$过程=新过程([“/ usr / bin / php”,“worker.php”]);$过程->开始();$pid=$过程->getPid ();
禁用输出
由于标准输出和错误输出总是从底层进程中获取,因此在某些情况下禁用输出以节省内存可能很方便。使用disableOutput ()而且enableOutput ()切换此功能:
1 2 3 4 5
使用ob娱乐下载\组件\过程\过程;$过程=新过程([“/ usr / bin / php”,“worker.php”]);$过程->disableOutput ();$过程->run ();
谨慎
在流程运行时,不能启用或禁用输出。
如果禁用输出,则无法访问getOutput ()
,getIncrementalOutput ()
,getErrorOutput ()
,getIncrementalErrorOutput ()
或setIdleTimeout ()
.
对象的回调函数是可能的开始
,运行
或mustRun
方法以流方式处理流程输出。
查找可执行文件
Process组件提供了一个名为ExecutableFinder查找并返回可执行文件的绝对路径:
1 2 3 4 5
使用ob娱乐下载\组件\过程\ExecutableFinder;$executableFinder=新ExecutableFinder ();$chromedriverPath=$executableFinder->找到(“chromedriver”);// $chromedriverPath = '/usr/local/bin/chromedriver'(在你的电脑上结果会不同)
的find ()方法还接受额外的参数来指定要返回的默认值和查找可执行文件的额外目录:
1 2 3 4
使用ob娱乐下载\组件\过程\ExecutableFinder;$executableFinder=新ExecutableFinder ();$chromedriverPath=$executableFinder->找到(“chromedriver”,“/道路/ / chromedriver”, (“本地bin /”]);
查找可执行PHP二进制文件
该组件还提供了一个特殊的实用程序类PhpExecutableFinder返回服务器上可用的可执行PHP二进制文件的绝对路径:
1 2 3 4 5
使用ob娱乐下载\组件\过程\PhpExecutableFinder;$phpBinaryFinder=新PhpExecutableFinder ();$phpBinaryPath=$phpBinaryFinder->find ();// $phpBinaryPath = '/usr/local/bin/php'(结果在您的计算机上将是不同的)
检查TTY支持
此组件提供的另一个实用程序是名为isTtySupported ()返回是否TTY当前操作系统支持:
1 2 3
使用ob娱乐下载\组件\过程\过程;$过程= (新过程())->setTty(过程::isTtySupported ());