从带有滚动的命令行 PHP 执行“less”

Posted

技术标签:

【中文标题】从带有滚动的命令行 PHP 执行“less”【英文标题】:Execute "less" from command-line PHP w/ Scrolling 【发布时间】:2011-03-29 14:49:19 【问题描述】:

我想在 php 的命令行中执行 less 和类似的程序。

我已经尝试过通常的嫌疑人(exec、shell_exec、passthru 等),虽然他们中的许多人可以将文件转储到屏幕上,但在我可以使用它之前进程就被终止了。如果我想要cat,我会使用它。

如何以这种方式执行程序?

【问题讨论】:

您想通过浏览器中的 php 脚本与控制台进行交互吗? 没有浏览器。我只是想从 PHP 启动其他工具,然后实际上是 in 这些工具,直到我退出。 【参考方案1】:

添加 exec('stty cbreak');到 PHP 脚本也解决了这个问题。

我将以下内容放在由 php.ini 中的 auto_prepend_file 设置定义的文件中

所以,我会做类似编辑 php.ini 到以下内容:

auto_prepend_file = /path/to/prepend.php

然后在 /path/to/prepend.php 中,我将添加以下行:

if (php_sapi_name() == 'cli') exec('stty cbreak');

我不确定原因。我已经阅读了 PHP 的错误报告。我不确定版本。我注意到以下设置存在问题:

$ php -v
PHP 5.3.3 (cli) (built: Jul 12 2013 20:35:47)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

但是,以下没有显示问题:

# php -v
PHP 5.3.26 (cli) (built: Oct 21 2013 16:50:03)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies
    with the ionCube PHP Loader v4.4.1, Copyright (c) 2002-2013, by ionCube Ltd.

值得注意的是,没有问题的版本是使用 cPanel,而另一个是使用默认的 CentOS 6 通过 yum 安装。

【讨论】:

【参考方案2】:

您可以使用proc_open 通过管道向进程提供输入并从进程中获取输出。然而,它似乎并没有允许通过管道进行用户交互,因为它基本上降级为cat 命令。这是我的第一个(失败的)方法:

<?php
$dspec = array(
  0 = array('pipe', 'r'), // pipe to child process's stdin
  1 = array('pipe', 'w'), // pipe from child process's stdout
  2 = array('file', 'error_log', 'a'), // stderr dumped to file
);
// run the external command
$proc = proc_open('less name_of_file_here', $dspec, $pipes, null, null);
if (is_resource($proc)) 
  while (($cmd = readline('')) != 'q') 
    // if the external command expects input, it will get it from us here
    fwrite($pipes[0], $cmd);
    fflush($pipes[0]);
    // we can get the response from the external command here
    echo fread($pipes[1], 1024);
  
fclose($pipes[0]);
fclose($pipes[1]);
echo proc_close($proc);

我猜对于某些命令,这种方法实际上可能有效 - 在proc_open 的 php 手册页中有一些示例可能有助于查看 - 但对于 less,您可以取回整个文件并且不可能为了互动,可能是因为 Viper_Sb 的回答中提到的原因。

...但是如果你只需要模拟less 似乎很容易。例如,您可以将命令的输出读入一个行数组并以小块的形式提供:

<?php
$pid = popen('cat name_of_file_here', 'r');
$buf = array();
while ($s = fgets($pid, 1024))
  $buf[] = $s;
pclose($pid);
for ($i = 0; $i < count($buf)/25 && readline('more') != 'q'; $i++) 
  for ($j = 0; $j < 25; $j++) 
    echo array_shift($buf);
  

【讨论】:

伟大的概念,和基本的模拟可能是要走的路(或者在 Bash 中重新设计整个事情)。答案的后半部分加上一些 ncurses 酱可能就是这些东西。【参考方案3】:

我不相信这是可能的。 PHP 不是 VM/shell 环境,它必须访问其他程序的命令都将控制权返回给它,通常在 PHP 运行时没有交互。

最后一件事,尝试使用反引号运算符,如果这不起作用,那么我很确定如果不自己编写一些会休眠并允许用户输入等的东西,你就无法做到这一点......默认情况下没有

`nano file.txt`

【讨论】:

以上是关于从带有滚动的命令行 PHP 执行“less”的主要内容,如果未能解决你的问题,请参考以下文章

如何从命令行执行 PHP 代码?

为啥这个带有 shell_exec 调用的 PHP 脚本从 Windows 10 的命令行运行,而不是浏览器/本地主机?

通过命令行执行用 ZendGuard 编码的 PHP 脚本

用于发送邮件的 php 脚本在通过浏览器执行时不起作用,但在从命令行执行时工作正常

more和less命令:

Linux中查看文件内容的命令(cat,more,less,head,tail)