Выполнить «меньше» из командной строки PHP с прокруткой - PullRequest
3 голосов
/ 13 августа 2010

Я хочу выполнить less и аналогичные программы из командной строки на PHP.

Я попробовал обычных подозреваемых (exec, shell_exec, passthru и т. Д.), И хотя многие из них могут вывести файл на экран, процесс прекращается, прежде чем я могу его использовать. Если бы я хотел cat, я бы использовал его.

Как мне выполнить программу таким образом?

Ответы [ 3 ]

2 голосов
/ 14 августа 2010

Вы можете использовать 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);

Я полагаю, что для некоторых команд этот подход может сработать - и в справочной странице php есть несколько примеров для proc_open, которые могут быть полезны для просмотра - но для 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);
  }
}
0 голосов
/ 03 декабря 2013

Добавление exec ('stty cbreak');в сценарии PHP также исправляет проблему.

Я поместил следующее в файл, определенный настройкой auto_prepend_file в php.ini

Итак, я бы сделал что-то вроде редактирования 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.

0 голосов
/ 13 августа 2010

Я не верю, что это возможно.PHP не является средой VM / оболочки, все команды, которые он имеет для доступа к другим программам, возвращают ему управление, и, как правило, во время работы PHP взаимодействие отсутствует.

И последнее, попробуйте операторы backtickесли это не сработает, то я почти уверен, что вы не сможете сделать это, не написав что-то самостоятельно, что будет спать и разрешать ввод данных пользователем и т. д. по умолчанию нет

`nano file.txt`
...