exec всегда возвращает -1 (или 127) - PullRequest
12 голосов
/ 11 августа 2010

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

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

Кто-нибудь когда-нибудь сталкивался с подобной ситуацией?* edit:

<code><?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 "
";

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

Ответы [ 5 ]

1 голос
/ 19 августа 2010

Предполагается, что система, возвращающая $ 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, вызван ошибкой;2-й происходит после вызова 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 () значительно изменился.

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

0 голосов
/ 20 августа 2010

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

0 голосов
/ 19 августа 2010

Я опробовал его на двух разных компьютерах с 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,
)

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

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

ИМХО .. PSM

0 голосов
/ 19 августа 2010

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

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

0 голосов
/ 11 августа 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...