php exec: не возвращает вывод
у меня есть эта проблема: На веб-сервере ISS установлен Windows 7 x64 professional, Zend server. Запуск этой команды в php:
exec('dir',$output, $err);
$output is empty, $err=1.
таким образом, exec не повторяет вывод, похоже, имеет некоторые ошибки.
В PHP disable_functions
пуст, php не находится в безопасном режиме, стандартен, я проверяю все опции.
Кажется, это общие ошибки, даже поиск в google не дает результатов.
пожалуйста, напишите каждый его опыт и возможные решения или обходные пути.
10 ответов
есть несколько сообщений в соответствующих разделах руководства PHP, таких как этот:
у меня возникли проблемы с использованием команды PHP exec для выполнения любой партии файл. Выполнение других команд (т. е. "dir") работает нормально). Но если я выполнил пакетный файл, я не получил вывода из команды exec.
настройка сервера у меня состоит из Windows Server 2003 server работает IIS6 и PHP 5.2.3. На этом сервере, у меня есть:
- разрешения execute для пользователя Интернет c:\windows\system32\cmd.исполняемый.
- предоставлено всем - >полный контроль над каталогом, в котором записан пакетный файл.
- предоставлено всем - >полный контроль над всем c:\cygwin\bin каталог и его содержимое.
- предоставлено пользователю Интернета разрешение "войти в систему как пакет".
- указан полный путь к каждому файлу выполняется.
- проверили эти скрипты запуска из командной строки на сервере и они работают просто отлично.
- убедитесь, что %systemroot%\system32 находится в системном пути.
оказывается, что даже со всем вышеперечисленным на месте на сервере я пришлось указать полный путь к cmd.exe в вызове exec.
когда я использовал вызов:
$output = exec("c:\windows\system32\cmd.exe
/c $batchFileToRun");
потом все работало нормально. В моем положении,
$batchFileToRun
была фактический системный путь к пакету файл (т. е. результат вызова реального пути()).
есть еще несколько на обоих exec
и shell_exec
руководство страниц. Возможно, пройдя через них, вы встанете на ноги и будете работать на вас.
основная причина, по которой вы получаете нулевой вывод от команды, такой как dir
- потому что dir
не существует. Это часть командной строки, и решение этой конкретной проблемы хорошо, где-то на этой странице.
вы можете узнать это, нажав WIN + R
, и введя в dir
или start
если на то пошло-появляется сообщение об ошибке!
как бы извращенно это ни звучало, я обнаружил, что самый надежный способ сделать что-либо, связанное с процессом в Windows с использованием объектной модели компонента. Вы сказали, чтобы мы поделились своим опытом, верно?
$меня слышит смех людей
уже обрел самообладание?
Итак, сначала мы создадим COM-объект:
$pCOM = new COM("WScript.Shell");
тогда мы просто запустим то, что когда-либо должно быть запущено.
$pShell = $pCom->Exec("C:\Random Folder\Whatever.exe");
круто! Теперь это будет висеть, пока все не закончится в этом двоичном файле. Итак, что нам нужно сделать сейчас, это схватить выход.
$sStdOut = $pShell->StdOut->ReadAll; # Standard output
$sStdErr = $pShell->StdErr->ReadAll; # Error
есть некоторые другие вещи, которые вы можете сделать - выяснить, что идентификатор процесса, код ошибки и т. д. Хотя для Visual Basic, он основан на той же схеме.
EDIT: после нескольких исследований я вижу единственный способ выполнить команду DIR так:
cmd.exe /c dir c:\
таким образом, вы можете попробовать мое решение, используя:
$command = 'cmd.exe /c dir c:\';
вы также можете использовать функцию proc_open, которая дает вам доступ к stderr, коду состояния возврата и stdout.
$stdout = $stderr = $status = null;
$descriptorspec = array(
1 => array('pipe', 'w'), // stdout is a pipe that the child will write to
2 => array('pipe', 'w') // stderr is a pipe that the child will write to
);
$process = proc_open($command, $descriptorspec, $pipes);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// 2 => readable handle connected to child stderr
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$status = proc_close($process);
}
return array($status, $stdout, $stderr);
интересная часть с proc_open, по сравнению с другими функциями, такими как popen или exec, заключается в том, что она предоставляет параметры, специфичные для платформы windows, такие как:
suppress_errors (windows only): suppresses errors generated by this function when it's set to TRUE
bypass_shell (windows only): bypass cmd.exe shell when set to TRUE
Я знаю, что выбрал ответ, поскольку я должен это сделать, но я все еще не понимаю, почему он не будет работать на моем macchine, но я нашел резервное (используя proc_open) решение, используя другой метод:
public static function exec_alt($cmd)
{
exec($cmd, $output);
if (!$output) {
/**
* FIXME: for some reason exec() returns empty output array @mine,'s machine.
* Somehow proc_open() approach (below) works, but doesn't work at
* test machines - same empty output with both pipes and temporary
* files (not we bypass shell wrapper). So use it as a fallback.
*/
$output = array();
$handle = proc_open($cmd, array(1 => array('pipe', 'w')), $pipes, null, null, array('bypass_shell' => true));
if (is_resource($handle)) {
$output = explode("\n", stream_get_contents($pipes[1]));
fclose($pipes[1]);
proc_close($handle);
}
}
return $output;
}
надеюсь, это кому-то поможет.
У меня была такая же проблема и после того, как провел много часов и чашку кофе
просто отключение управления учетными записями пользователей (UAC) в Windows 7 короткий путь: P C:\Windows\System32\UserAccountControlSettings.исполняемый и выберите "никогда не уведомлять"
и php exec () отлично работает!
Я использую:
Версия Apache: 2.2.11
PHP версия : 5.2.8
Windows 7 с пакетом обновления SP1 32бит
с наилучшими пожеланиями! : D
в целях безопасности ваш сервер может иметь ограниченный доступ к команде "exec". В этом случае, возможно, вам следует обратиться в хостинг-компанию, чтобы убрать это ограничение (если есть).
вы можете проверить permisssions пользователя IIS для УМК.exe
cacls C:\WINDOWS\system32\cmd.exe
Если на выходе есть строка like (COMPUTERNAME=имя Вашего компьютера):
C:\WINDOWS\system32\cmd.exe COMPUTERNAME\IUSR_COMPUTERNAME:N
Это означает, что пользователь не имеет прав на выполнение команды.
вы можете добавить разрешения на выполнение с помощью команды:
cacls C:\WINDOWS\system32\cmd.exe /E /G COMPUTERNAME\IUSR_COMPUTERNAME:R
Если вы находитесь на машине Windows и пытаетесь запустить исполняемый файл, как это:
shell_exec("C:\Programs\SomeDir\DirinDir\..\DirWithYourFile\YourFile.exe");
и нет вывода или ваш файл не запущен, тогда вы должны попробовать следующее:
chdir("C:\Programs\SomeDir\DirinDir\..\DirWithYourFile");
shell_exec("YourFile.exe");
это должно сработать.
Это особенно удобно, если используется относительный путь от папки где скрипт находится, например:
$dir = dirname(__FILE__).'\..\..\..\web\';
и не забудьте chdir () вернуться в исходную папку, если вам нужно запустить другие программы.
взгляните на Apache error_log, возможно, вы найдете сообщение об ошибке.
кроме того, вы можете попробовать использовать popen вместо exec. Это дает больше контроля, потому что вы можете отделить запуск процесса от вывода read:
$p = popen("dir", "r");
if (!$p)
exit("Cannot run command.\n");
while (!feof($p))
echo fgets($p);
pclose($p);