PHP exec () и пробелы в путях - PullRequest
14 голосов
/ 30 марта 2011

Я выполняю следующее в PHP-приложении:

  $source = '/home/user/file.ext';
  $output_dir = $this->setOutputString();

  chdir('/home/ben/xc/phplib/bgwatcher-2011a/a01/');
  exec('php bin/createjob.php $source $output_dir', $output);

  return $output[0];

Проблема в следующем: у меня есть контроль над $source, но не $output_dir, который является устаревшей файловой системой Windows, и в пути есть пробелы. Пример $output_dir:

/home/vol1/district id/store id/this_is_the_file.html

Вставляя строку вывода в функцию exec(), я попробовал оба:

addslashes($output_dir) и '"' . $output_dir . '"' для экранирования всей выходной строки. В первом случае путь соединяется с:

/home/vol1/districtthis_is_the_file.html

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

Какое решение здесь? Я sprintf() всю строку для exec()? Я очень озадачен тем, почему addslashes не работает правильно, чтобы избежать пробелов, и я предполагаю, что это как-то связано с очисткой с exec (), но я не могу найти какую-либо документацию для его резервного копирования.

Обновление: Я пробовал escapeshellarg () и preg_replace () безуспешно. Размышляя об этом дальше, нужно ли мне дважды уходить с пути? Или избежать пути и команды? Если путь не экранируется один раз exec () и один раз PHP перед выполнением команды, то понятно ли, что мне нужно учитывать оба выхода? Или это не так?

Ответы [ 6 ]

8 голосов
/ 30 марта 2011

Я не верю, addslashes() делает что-то с пробелами. escapeshellarg() может быть тем, что вы хотите вместо этого. Документы на escapeshellarg

7 голосов
/ 30 марта 2011

Из документа PHP ( здесь ),

Возвращает строку с обратными косыми чертами перед символами, которые необходимо заключать в кавычки в запросах к базе данных и т. Д. Эти символы - одинарные кавычки ('), двойные кавычки ("), обратная косая черта () и NUL (байт NULL).

Это ничего не сделает с пробелами. Вам нужно будет использовать str_replace() для добавления слешей, например:

$new_string = str_replace(" ", "\\ ", $old_string);

7 голосов
/ 30 марта 2011

Согласно PHP документам ,

Возвращает строку с обратным слешем перед символами, которые должны быть заключены в кавычки в запросах к базе данных и т. Д. Это символы одинарных кавычек ('), двойных кавычек ("), обратного слеша () и NUL (байт NULL) .

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

Изменить:

Несмотря на то, что это тема другого обсуждения, если производительность - это проблема, то если посмотреть на нее немного больше, кажется, что str_replace на самом деле немного быстрее, чем preg_replace :

Тест с надписью "str_replace ()" был быстрее на 0,9053 секунды (это заняло 10,3% времени.)

Первый тест занял 1,0093 секунды. (preg_replace)

Второй тест занял 0,104 секунды. (str_replace)

Здесь найден бенчмарк.

3 голосов
/ 30 марта 2011

Ранее я использовал exec() с путями с пробелами, как на хостах Windows, так и на Linux, и в обоих случаях цитирование пути работало для меня идеально.

Тем не менее, если у вас нет контроля над безопасностью аргумента оболочки, всегда сначала пропустите escapeshellarg()!

2 голосов
/ 30 марта 2011

Вы можете очень хорошо использовать shell кавычки, так как это то, через что проходят все команды exec:

exec("php bin/createjob.php '$source' '$output_dir'", $output);

Между прочим, это работает не только для аргументов, но и для самой команды:

exec('"/bin/echo" "one parameter"');

В любом случае используйте escapeshellcmd().

0 голосов
/ 08 февраля 2018

это работает для меня при использовании exec () с soffice (LibreOffice):

$file_name = "Some, file name.xlsx";
exec('/usr/bin/soffice --headless --convert-to pdf '."'".$file_name."'".' 2>&1', $output, $r);
...