php exec: не возвращает результат

У меня есть эта проблема: на веб-сервере ISS установлен Windows 7 x64 professional, сервер zend. Выполнение этой команды в php:

exec('dir',$output, $err); 

$output is empty, $err=1. Таким образом, exec не сохраняет результат, кажется, есть некоторые ошибки. Php disable_functions пуст, php не находится в безопасном режиме, является стандартным, я проверяю все параметры. Похоже, что это общие ошибки, даже поиск в google не дает результатов.

Пожалуйста, напишите каждый свой опыт и возможные решения или обходные пути.

Related of "php exec: не возвращает результат"

В соответствующих разделах руководства по PHP есть несколько сообщений, например:

У меня возникла проблема с использованием команды PHP exec для выполнения любого командного файла. Выполнение других команд (т. Е. «Dir») отлично работает). Но если я выполнил пакетный файл, я не получил выход из команды exec.

Установки сервера, которые у меня есть, состоит из сервера Windows Server 2003, на котором запущены IIS6 и PHP 5.2.3. На этом сервере у меня есть:

  1. Предоставленные разрешения на выполнение для пользователя Интернета в c: \ windows \ system32 \ cmd.exe.
  2. Предоставлено Everyone-> Full Control в каталог, в котором написан командный файл.
  3. Предоставлено Everyone-> Full Control для всего каталога c: \ cygwin \ bin и его содержимого.
  4. Предоставлено разрешение «войти в систему как пакетное».
  5. Указывает полный путь к каждому исполняемому файлу.
  6. Протестированы эти сценарии, запущенные из командной строки на сервере, и они работают нормально.
  7. Убедитесь, что% systemroot% \ system32 находится в системном пути.

Оказывается, что даже со всем вышеперечисленным на сервере я должен был указать полный путь к cmd.exe в вызове exec.

Когда я использовал вызов: $output = exec("c:\\windows\\system32\\cmd.exe /c $batchFileToRun");

тогда все сработало нормально. В моей ситуации $batchFileToRun был фактическим системным путем для командного файла (т. Е. Результатом вызова realpath ()).

На страницах руководства exec и shell_exec есть еще несколько. Возможно, после них они поднимутся и будут работать на вас.

Основная причина, по которой вы получаете нулевой вывод из команды, такой как dir состоит в том, что dir не существует. Это часть командной строки, и решение этой конкретной проблемы хорошо, на этой странице где-то.

Вы можете найти это, нажав WIN + R , и набрав dir или start в этом случае – появится сообщение об ошибке!

Однако это может показаться порочным, я обнаружил, что самым надежным способом сделать что-либо, связанным с Windows, является использование Component Object Model. Вы сказали нам поделиться своим опытом, верно?

$ me слышит смех людей

Улучшилось ваше самообладание?

Итак, сначала мы создадим 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.exe и выберите «Никогда не уведомлять»,

и php exec () работает отлично!

Я использую: Apache Version: 2.2.11
Версия PHP: 5.2.8
Windows 7 SP1 32bit

С наилучшими пожеланиями! : D

В целях безопасности ваш сервер может иметь ограниченный доступ к команде «exec». В этом случае, возможно, вам следует связаться с хостинговой компанией, чтобы удалить это ограничение (если оно есть).

Вы можете проверить разрешения пользователя IIS на cmd.exe

 cacls C:\WINDOWS\system32\cmd.exe 

Если на выходе есть строка типа (COMPUTERNAME = имя вашего компьютера):

 C:\WINDOWS\system32\cmd.exe COMPUTERNAME\IUSR_COMPUTERNAME:N 

Это означает, что пользователь не имеет права выполнять cmd.

Вы можете добавить разрешения выполнения с помощью команды:

 cacls C:\WINDOWS\system32\cmd.exe /E /G COMPUTERNAME\IUSR_COMPUTERNAME:R 

Попробуй это:

 shell_exec('dir 2>&1'); 

Он отлично работает на Windows 8.1 64 бит с включенным UAC.

Если вы находитесь на машине 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. Это дает больше контроля, потому что вы можете отделить процесс от вывода:

 $p = popen("dir", "r"); if (!$p) exit("Cannot run command.\n"); while (!feof($p)) echo fgets($p); pclose($p);