exec всегда возвращает -1 (или 127)

Я использую php 5.2.9 на производственном сервере, и кажется, что Функция exec () ведет себя «нестандартно».

Если я запустил exec ("ls", $ output, $ return_var) , то $ output будет содержать список файлов в текущей папке, как и ожидалось, но $ return_var будет установлено в -1 вместо 0, как ожидалось. Я использую $ return_var , чтобы определить, где команда завершилась успешно, и на каждом другом протестированном сервере это работает, как ожидалось :)

Кто-нибудь когда-либо попадал в такую ​​ситуацию?


edit:

<?php
$command = "asd";

$t1 = time();

$output = Array();
$result = -5;
$r = exec($command, $output, $result);
$t2 = time();

echo "<pre>";
var_export(Array(
    'command'=>$command,
    'result'=>$result,
    'output'=>implode("\n", $output),
    'r'=>$r,
    't2-t1'=>$t2-$t1,
));
echo "</pre>";

Какую бы команду я ни ввел в $ command , $ result всегда будет -1, даже для несуществующих команд ... это очень странно

12
задан Quamis 2 December 2011 в 15:52
поделиться

5 ответов

Предполагается, что система, возвращающая $ result == -1, основана на Unix (я не знаю, как поведет себя Windows с тем же кодом)

Функция exec () PHP (5.2.9) не вызывает примитив C exec () (который возвращает -1, если он не может заменить / выполнить процесс, что здесь не так). Вместо этого он вызывает popen (), который создает канал, выполняет fork () и выполняет оболочку с вашей командой. Return_value, -1, не является прямым результатом примитива C, а скорее создается внутри PHP, в зависимости от способа обработки вашей команды. Другими словами, команда «ls» могла быть хорошо выполнена, в то время как, например, PHP не мог должным образом закрыть канал.

Глядя на код C в ext / standard / exec.c, может быть две причины, по которым код возврата -1, вызванный ошибкой; второй происходит после вызова popen ()

  fp = VCWD_POPEN(cmd_p, "r");

  if (!fp) {
       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", cmd);
       goto err;
  }
  // ...
  err:

  pclose_return = -1;
  goto done;

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

Позже return_value устанавливается через строку

  pclose_return = php_stream_close(stream);

Если посмотреть на _php_stream_free () (php_stream_close () - это макрос, замененный на _php_stream_free ()), наиболее вероятным кандидатом, который может вернуть -1, является

  ret = stream->ops->close(stream, preserve_handle ? 0 : 1 TSRMLS_CC);

Что в свою очередь косвенно вызывает примитив C pclose (). Согласно руководству

функция pclose () возвращает -1, если wait4 (2) возвращает ошибку или обнаружена другая ошибка.

Похоже, что при закрытии канала обнаружена ошибка, которая не препятствует установке результирующих данных. Чтобы точно найти причину, необходимо проверить настройки операционной системы и журналы, конфигурацию PHP и параметры компиляции.

Я бы порекомендовал

  • применить исправления для вашей ОС и, возможно, обновить его до более новой версии (если применимо),
  • , чтобы обновить PHP до версии 5.3.3 (последней на данный момент), поскольку PHP exec ( ) код существенно изменился.

Имейте в виду, что в модуль PHP suhosin версии 5.3 были внесены изменения, которые по умолчанию повышают безопасность при запуске файлов PHP.

1
ответ дан 3 December 2019 в 00:08
поделиться

Убедитесь, что вы не работаете в безопасном режиме и что exec не указан в disable_functions в php.ini.

Любая из этих ситуаций приведет к сбою exec () , хотя я думаю, что будет подано уведомление.

0
ответ дан 3 December 2019 в 00:08
поделиться

Можем ли мы получить результат выполнения strace'а процесса PHP? Вероятно, это будет содержать ответ, который мы ищем.

Также 5.2.14 является новейшей из серии 5.2. Есть ли шанс попробовать это там? Если вы пользуетесь услугами провайдера общего хостинга, вы все равно можете запустить его локально, чтобы увидеть, не изменится ли поведение.

0
ответ дан 3 December 2019 в 00:08
поделиться

Я опробовал его на двух разных компьютерах с Linux (PHP 5.03 и PHP 5.2.10) - оба работали нормально.

Пример PHP 5.2.10:

array (
  'command' => 'ls',
  'result' => 0,
  'output' => 'atmail
...
vhosts',
  'r' => 'vhosts',
  't2-t1' => 0,
)

Я бы дважды проверил наличие директив, связанных с безопасностью, в вашем файле php.ini, проверил права доступа к файлу в каталоге, который вы пытаетесь найти, и посмотрел, есть ли у вас SELinux и / или AppArmor работает.

Вы также можете рассмотреть альтернативный вариант, например opendir () / readdir ().

ИМХО .. PSM

0
ответ дан 3 December 2019 в 00:08
поделиться

Похоже, проблему решил администратор сервера. Понятия не имею, что он сделал, но теперь это работает. Дело в том, что администратор сервера довольно "строгий" и, возможно, он стал немного ограничивать с какой-то конфигурацией системы. Например, из оболочки SSH я не мог видеть, где были установлены двоичные файлы php. Я почти уверен, что оболочка SSH была chrooted, а также веб-сервер (либо тот, либо они были совершенно разными серверами, но я не знаю, как это было возможно без использования какого-либо монтирования) ...

0
ответ дан 3 December 2019 в 00:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: