У меня есть эта проблема: на веб-сервере ISS установлен Windows 7 x64 professional, сервер zend. Выполнение этой команды в php:
exec('dir',$output, $err);
$output is empty, $err=1.
Таким образом, exec не сохраняет результат, кажется, есть некоторые ошибки. Php disable_functions
пуст, php не находится в безопасном режиме, является стандартным, я проверяю все параметры. Похоже, что это общие ошибки, даже поиск в google не дает результатов.
Пожалуйста, напишите каждый свой опыт и возможные решения или обходные пути.
В соответствующих разделах руководства по PHP есть несколько сообщений, например:
У меня возникла проблема с использованием команды PHP exec для выполнения любого командного файла. Выполнение других команд (т. Е. «Dir») отлично работает). Но если я выполнил пакетный файл, я не получил выход из команды exec.
Установки сервера, которые у меня есть, состоит из сервера Windows Server 2003, на котором запущены IIS6 и PHP 5.2.3. На этом сервере у меня есть:
- Предоставленные разрешения на выполнение для пользователя Интернета в c: \ windows \ system32 \ cmd.exe.
- Предоставлено Everyone-> Full Control в каталог, в котором написан командный файл.
- Предоставлено Everyone-> Full Control для всего каталога c: \ cygwin \ bin и его содержимого.
- Предоставлено разрешение «войти в систему как пакетное».
- Указывает полный путь к каждому исполняемому файлу.
- Протестированы эти сценарии, запущенные из командной строки на сервере, и они работают нормально.
- Убедитесь, что% 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);