Я написал веб-приложение, которое использует exec () для запуска внешней программы. Путь к программе настраивается и, как ожидается, будет содержать пробелы в имени. Как мы все знаем, командная строка Windows принимает пробелы в именах файлов или параметрах, вам просто нужно их удвоить:
C:\>C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe "C:\Archivos" no se reconoce como un comando interno o externo, programa o archivo por lotes ejecutable. C:\>"C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" GraphicsMagick 1.3.12 2010-03-08 Q16 http://www.GraphicsMagick.org/
Все идет нормально. Проблема, с которой я столкнулась, – это использование самой функции exec () PHP. На некоторых серверах Windows требуется заключить полную команду (параметры программы +) в двойные кавычки:
exec('""C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" version"');
… и другие серверы Windows требуют не использовать двойные кавычки:
exec('"C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" version');
Я могу прочитать константу PHP_OS
чтобы определить, работает ли на сервере Windows, но я не знаю, каково правило за кавычками или не цитирует тему. Если это объясняется в руководстве PHP, я не могу его найти.
Можно ли программно определить, нужны ли кавычки, поэтому мне не нужно вручную настраивать каждый экземпляр приложения?
Обновление № 1: меня неправильно поняли, поэтому я переформулировал части вопроса, чтобы сделать его более понятным.
Обновление № 2: я нашел комментарий в руководстве по PHP, в котором объясняется точная причина, по которой необходимы дополнительные кавычки (PHP выдает внутренний вызов cmd /c
). Я до сих пор не знаю, почему это кажется истинным или ложным в зависимости от системы.
Я написал это быстрое и грязное обходное решение:
<?php class Thumb{ const GM_PATH = 'C:\\Archivos de programa\\GraphicsMagick-1.3.12-Q16\\gm.exe'; /** * Quote full command if required by server (program + arguments) */ private static function quoteFullCommand($command){ // Test only once per script static $extra_quotes_required=NULL; if( is_null($extra_quotes_required) ){ if(PHP_OS=='WINNT'){ // This call will be correct (0) if and only if the server requires extra quotes exec('""sort" /?"', $output, $return); $extra_quotes_required = $return==0; }else{ $extra_quotes_required = FALSE; } } if($extra_quotes_required){ $command = '"' . $command . '"'; } return $command; } /** * Return output from "gm version" */ public static function graphicsMagickVersion(){ $command = escapeshellarg(self::GM_PATH) . ' version '; $command = self::quoteFullCommand($command); exec($command, $output, $return); return trim(implode(PHP_EOL, $output)); } }
Однако было бы лучше предсказать это из версии PHP или серверной ОС, поэтому ссылки на документацию или дополнительные советы приветствуются.
Обновление: я просмотрел часть исходного кода PHP, которая заботится о запуске внешних команд в Windows:
http://svn.php.net/viewvc/php/php-src/trunk/TSRM/tsrm_win32.c
Следующая строка добавляет дополнительные команды к полной команде:
sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command);
Согласно истории файлов, эта строка была впервые добавлена 29 мая 2008 года ( r260429 ):
MFH: Исправить ошибку при цитировании команды и указать параметры во время вызова exec, результатом является то, что cmd.exe / c разбивает первую и последнюю цитату.
Следующие версии PHP были 5.3.0 и 5.2.7, но строка находится в ветви 5_3, а не в 5_2. Я недостаточно знаком с процессом разработки PHP, поэтому я не могу найти журнал изменений или сказать, к каким точным версиям PHP исправлено исправление, но я бы осмелился сказать, что это была ошибка в PHP, и она была исправлена на PHP /5.3.0 (но он не был обращен к 5.2, поэтому они не сломали устаревшие вещи).
Таким образом, мое обходное решение, вероятно, слишком велико. Вам просто нужно проверить PHP-версию и версию:
if( PHP_OS=='WINNT' && version_compare(PHP_VERSION, '5.3.0', '<') ){ $command = $command = '"' . $command . '"'; }