Я хочу выполнить less
и подобных программ из командной строки в PHP.
Я пробовал обычных подозреваемых (exec, shell_exec, passthru и т. Д.), И хотя многие из них могут выгружать файл на экран, этот процесс заканчивается, прежде чем я смогу его использовать. Если бы я хотел cat
, я бы использовал его.
Как я могу выполнить программу таким образом?
Вы можете использовать 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);
Я думаю, что для некоторых команд этот подход может действительно работать – и есть некоторые примеры в man- proc_open
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); } }
Я не считаю, что это возможно. PHP не является средой VM / shell, команды, к которой он должен обращаться, к другим программам, все возвращают к нему контроль, и обычно нет взаимодействия во время работы PHP.
Последнее, попробуйте с операторами backtick, если это не сработает, то я уверен, что вы не можете этого сделать, не записывая что-то самостоятельно, что будет спать и разрешить ввод пользователя и т. Д. … по умолчанию нет
`nano file.txt`
Добавление 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.