我试图从proc_openphp中获取方法的输出,但是,当我打印它时,我变空了.
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "files/temp/error-output.txt", "a")
);
$process = proc_open("time ./a a.out", $descriptorspec, $pipes, $cwd);
只要我知道,我可以得到输出 stream_get_contents()
echo stream_get_contents($pipes[1]); fclose($pipes[1]);
但我不能这样做......有什么建议吗?
先谢谢......
我正在使用一个proc_open()用来调用shell命令的函数.看起来我在做STDIO的方式是错误的,有时导致PHP或目标命令锁定.这是原始代码:
function execute($cmd, $stdin=null){
$proc=proc_open($cmd,array(0=>array('pipe','r'),1=>array('pipe','w'),2=>array('pipe','w')),$pipes);
fwrite($pipes[0],$stdin); fclose($pipes[0]);
$stdout=stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr=stream_get_contents($pipes[2]); fclose($pipes[2]);
return array( 'stdout'=>$stdout, 'stderr'=>$stderr, 'return'=>proc_close($proc) );
}
Run Code Online (Sandbox Code Playgroud)
它大部分时间都有效,但这还不够,我想让它始终有效.
stream_get_contents()如果STDIO缓冲区超过4k的数据,则问题在于锁定.
function out($data){
file_put_contents('php://stdout',$data);
}
function err($data){
file_put_contents('php://stderr',$data);
}
if(isset($argc)){
// RUN CLI TESTCASE
out(str_repeat('o',1030);
err(str_repeat('e',1030);
out(str_repeat('O',1030);
err(str_repeat('E',1030);
die(128); // to test return error code
}else{
// RUN EXECUTION TEST CASE
$res=execute('php -f '.escapeshellarg(__FILE__));
}
Run Code Online (Sandbox Code Playgroud)
我们输出一个字符串两次到STDERR和STDOUT,总长度为4120字节(超过4k).这会导致PHP双方都锁定.
显然,stream_select()是要走的路.我有以下代码:
function execute($cmd,$stdin=null,$timeout=20000){
$proc=proc_open($cmd,array(0=>array('pipe','r'),1=>array('pipe','w'),2=>array('pipe','w')),$pipes);
$write = array($pipes[0]);
$read = array($pipes[1], $pipes[2]);
$except = null;
$stdout …Run Code Online (Sandbox Code Playgroud) 对于任何想知道的人来说,在离开它几个小时之后它现在完美无缺.
我正在尝试使用PHP将视频文件传递给VLC作为即将推出的项目提案的概念证明.
我设法通过创建一个<4KB(灰色10秒)文件并测试我的脚本来显示它的工作原理,但我很好奇为什么会发生这种情况的原因.
这是一个示例脚本,看看我的意思:
$filepath = 'Path/to/your/video';
$vlcpath = 'Path/to/your/VLC executable';
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w") // stderr
);
$vlc = proc_open($vlcpath . ' -', $descriptorspec, $pipes, null, null, ['bypass_shell' => true]);
$file = fopen($filepath, 'r');
stream_copy_to_stream($file, $pipes[0]);
fclose($file);
proc_close($vlc);
Run Code Online (Sandbox Code Playgroud)
我在Windows 10上使用PHP 5.5.31.我在PHP网站上看到了一些有关此类事情的错误报告,但他们建议最新版本修复它.我不太了解阻塞流的概念,但我已经尝试过PHP v7.0.3无济于事.
我正在使用命令行运行此脚本: php file.php
我有一个实用程序函数用于通过CLI(cmd,bash等)执行程序.它返回的3项的数组:STDOUT,STDERR和EXIT CODE.
到目前为止,它一直很好地没有问题.事实上,我遇到的问题并没有真正阻碍它的功能,但我关注的是性能.
问题是在某些情况下,PHP会多次运行相同的命令(在我的情况下是3次),即使它只应该执行一次.
/**
* Executes a program and waits for it to finish, taking pipes into account.
* @param string $cmd Command line to execute, including any arguments.
* @param string $input Data for standard input.
* @param boolean $log Whether to log execution failures or not (defaults to true).
* @return array Array of "stdout", "stderr" and "return".
*/
public static function execute($cmd,$stdin=null,$log=true){
//static $once=true; if(!$once)die; $once=false;
$proc=proc_open($cmd, array(
0=>array('pipe','r'),
1=>array('pipe','w'), …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用proc_open执行一个进程.管道处理过程的I/O !!
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
Run Code Online (Sandbox Code Playgroud)
现在,实际上,我打开的"c程序"有时会卡住,我添加了一个max_time_limit检查,强制关闭进程.我已经添加了回调函数 - 即onExit - (使用"call_user_function"),以便以有效方式或强制方式处理"进程退出"时的信息.
在"退出"功能中,我正在关闭i/o管道
foreach ($pipes as $pipe) {
fclose($pipe);
}
Run Code Online (Sandbox Code Playgroud)
如果进程有一个有效的退出,上面的工作完全正常.但是,在我强行杀死我的进程的情况下,我调用proc_terminate来执行此操作.我知道进程的终止也会继续并关闭所有I/O管道,但问题是由于回调,我的"onExit"函数进程总是被调用(这就是我希望它的方式.. .as我需要做更多的处理).现在,在这种情况下,当我尝试关闭管道时,我收到以下错误:
fclose(): 18 is not a valid stream resource
Run Code Online (Sandbox Code Playgroud)
我尝试使用"ftell"来检查管道是否有效,但是这也是错误的.如何检查管道是否已经关闭?
我正在尝试创建一个人们可以在线编译和运行代码的网站,因此我们需要找到一种用户发送指令的交互方式.
实际上,首先想到的是exec()或者system(),但是当用户想要输入时,这种方式将不起作用.所以我们必须使用proc_open().
例如,以下代码
int main()
{
int a;
printf("please input a integer\n");
scanf("%d", &a);
printf("Hello World %d!\n", a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我使用时proc_open(),就像这样
$descriptorspec = array(
0 => array( 'pipe' , 'r' ) ,
1 => array( 'pipe' , 'w' ) ,
2 => array( 'file' , 'errors' , 'w' )
);
$run_string = "cd ".$addr_base."; ./a.out 2>&1";
$process = proc_open($run_string, $descriptorspec, $pipes);
if (is_resource($process)) {
//echo fgets($pipes[1])."<br/>";
fwrite($pipes[0], '12');
fclose($pipes[0]);
while (!feof($pipes[1])) …Run Code Online (Sandbox Code Playgroud) I'm trying to spawn multiple processes at once in PHP with proc_open, but the second call won't start until the first process has ended. Here's the code I'm using:
for ($i = 0; $i < 2; $i++)
{
$cmdline = "sleep 5";
print $cmdline . "\n";
$descriptors = array(0 => array('file', '/dev/null', 'r'),
1 => array('file', '/dev/null', 'w'),
2 => array('file', '/dev/null', 'w'));
$proc = proc_open($cmdline, $descriptors, $pipes);
print "opened\n";
}
Run Code Online (Sandbox Code Playgroud) 警告:proc_open():在第102行的C:\ ...\updatedots.php中缺少数组中的句柄限定符
我试图打开记事本,关闭它2秒后.这是我的代码:
$descriptorspec = array(
0 => array("pipe" => "r"),
1 => array("pipe" => "w"),
2 => array("file" => "logs/errors.txt")
);
// Create child and start process
$child = array("process" => null, "pipes" => array());
$child["process"] = proc_open("notepad.exe > nul 2>&1", $descriptorspec, $child["pipes"]);
Run Code Online (Sandbox Code Playgroud)
知道这个错误意味着什么,是什么原因引起的?
因此,在PHP在Windows上:是否有可能都在后台运行的可执行文件和检索它的PID?我已经推断出可以单独完成这两项任务,但不能同时完成.
要对通过SHELL启动的进程进行后台处理,'start /B "bg" myprog.exe'必须使用该命令,并且必须立即关闭SHELL进程.
要做到这一点,许多人都这样使用pclose( popen( ... ) ),pclose( popen( 'start /B "bg" myprog.exe', 'r') );但据我所知,pid使用popen时无法检索.
因为pid使用popen 是不可能的,所以我们必须看看proc_open.
使用proc_open我们可以检索exe的pid当且仅当if bypass_shell设置为true.
如果bypass_shell设置为false(默认值),Windows将返回pidSHELL的内容.有关详细信息,请参阅:https://bugs.php.net/bug.php?id = 41052
该start /B传递给proc_open时,当命令失败bypass_shell = true,因为它跳过了SHELL和发送命令行参数直接MYPROG.EXE不知道他们做什么.
相反,如果bypass_shell = false(默认)和proc_close用于立即关闭SHELL,myprog.exe在后台运行就像使用pclose( popen( ... ) )BUT 时返回错误 pid(我们得到pid了SHELL).
那么,背景+正确的pid检索是否可行? …
PHP的proc_open手册说明:
文件描述符编号不限于0,1和2 - 您可以指定任何有效的文件描述符编号,并将其传递给子进程.这允许您的脚本与作为"协同进程"运行的其他脚本进行互操作.特别是,这对于以更安全的方式将密码短语传递给PGP,GPG和openssl等程序非常有用.它对于读取这些程序在辅助文件描述符上提供的状态信息也很有用.
发生了什么: 我在基于PHP的Web应用程序中调用Perl脚本并在调用中传递参数.我将来不需要将数据发送到脚本.通过stdout [1]我收到了我在PHP应用程序中使用的Perl脚本json_encoded数据.
我想补充的内容: Perl脚本正在通过网站收集信息,具体取决于其初始调用中传递的参数.我想将一个文本字符串发送回PHP应用程序,我可以将其用作一种进度条显示.
我认为我应该这样做:我希望(每1-2秒)轮询一次为"进展"更新设置的频道.我会使用Javascript/jQuery写入一个html div容器供用户查看.我不认为我应该将"进度"通道与更关键的"json_encode(数据)"通道混合,因为我需要解密stdout流.(这个想法合乎逻辑,实用吗?)
我的主要问题: 你如何使用额外的"文件描述符?" 我想将其他通道的设置想象得很简单,比如下面的3 => ...:
$tunnels = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w'),
3 => array('pipe', 'w')
);
$io = array();
$resource = proc_open("perl file/tomy/perl/code.pl $param1 $param2 $param3", $tunnels, $io);
if(!is_resource($resource)) {
$error = "No Resource";
}
fclose($io[0]);
$perlOutput = stream_get_contents($io[1]);
$output = json_decode($perlOutput);
$errors = stream_get_contents($io[2]);
print "$errors<p>";
fclose($io[1]);
fclose($io[2]);
$result = …Run Code Online (Sandbox Code Playgroud)