Как я могу отлаживать проблемы exec()?

Команда exec не работает на моем сервере, она ничего не делает, я отключил safe_mode и проверял, что все консольные команды работают, я пробовал с абсолютными путями. Я проверил разрешения для приложений и всех приложений, в которых мне нужны разрешения на выполнение. Я не знаю, что еще делать, вот краткое изложение кодов, которые я пробовал.

echo exec('/usr/bin/whoami');

echo exec('whoami');

exec('whoami 2>&1',$output,$return_val);
if($return_val !== 0) {
    echo 'Error<br>';
    print_r($output);   
}

exec('/usr/bin/whoami 2>&1',$output,$return_val);
if($return_val !== 0) {
    echo 'Error<br>';
    print_r($output);   
}

Отображаются последние два кода:

Error
Array ( ) 

Я связался с серверной службой, и они не могут мне помочь, они не знают, почему команда exec не работает. Простите мой плохой английский.

Ответ 1

посмотрите /etc/php.ini, там под:

; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.disable-functions
disable_functions =

убедитесь, что exec не указан следующим образом:

disable_functions=exec

Если это так, удалите его и перезапустите apache.

Для легкой отладки я обычно обычно запускаю файл php вручную (может запрашивать больше ошибок, не устанавливая его в основном ini). для этого добавьте заголовок:

#!/usr/bin/php
ini_set("display_errors", 1);
ini_set("track_errors", 1);
ini_set("html_errors", 1);
error_reporting(E_ALL);

в начало файла, дайте ему разрешения с помощью chmod +x myscript.php и выполните его ./myscript.php. Он очень внимателен, особенно на занятом сервере, который много записывает в файл журнала.

ИЗМЕНИТЬ

Звучит как проблема разрешений. Создайте bash script, который делает что-то простое как echo "helo world" и попытается запустить его. Убедитесь, что у вас есть разрешения для файла и для папки, содержащей файл. вы можете просто сделать chmod 755 только для тестирования.

Ответ 2

Вы можете восстановить выходные и возвратные коды команд exec, которые могут содержать информацию, которая могла бы объяснить проблему...

exec('my command', $output, $return);

Ответ 3

Так как вы выходите из контекста PHP в родную оболочку, у вас будет много отладочных проблем.

Самый лучший и самый надежный, который я использовал в прошлом, записывает вывод script в файл журнала и обрабатывает его во время выполнения PHP.

<?php
shell_exec("filename > ~/debug.log 2>&1");

Затем в отдельной оболочке:

tail -200f ~/debug.log

Когда вы выполняете свой PHP script, ваши ошибки и вывод из вашего вызова оболочки отображаются в вашем файле debug.log.

Ответ 4

Еще несколько заметок.

  • Для отладки всегда завершайте функцию exec/shell_exec в var_dump().

  • error_reporting(-1); должно быть включено, как и должно быть display_errors, в крайнем случае даже set_error_handler("var_dump"); - если только посмотреть, не вызывает ли PHP сам execvp или.

    /li >
  • Используйте 2>&1 (объедините оболочки STDERR в поток STDOUT), чтобы узнать, почему сбой вызова.
    В некоторых случаях вам может понадобиться обернуть команду в вызове дополнительной оболочки:

    // capture STDERR stream via standard shell
    shell_exec("/bin/sh -c 'ffmpeg -opts 2>&1' ");
    

    Повторите перенаправление файла журнала, как рекомендовано @Mike - наиболее рекомендуемый подход.

  • Переключение между различными функциями exec, чтобы в противном случае вскрыть сообщения об ошибках. Хотя они в основном делают то же самое, выходные пути возврата меняются:

    • exec() → либо возвращает результат как результат функции, либо через необязательный параметр $output.
      Также предоставляет параметр $return_var, который содержит код errno/exit приложения запуска или оболочки. Вы можете получить:

      • ENOENT (2) - Нет такого файла
      • EIO (127) - Ошибка ввода-вывода: файл не найден
    • shell_exec() → то, что вы хотите запускать в основном для выражений в стиле оболочки.
      Обязательно назначьте/напечатайте возвращаемое значение, например. var_dump(shell_exec("..."));

    • `` встроенные backticks → идентичны shell_exec.

    • system() → аналогичен exec, но всегда возвращает результат как результат функции (распечатайте его!). Дополнительно позволяет зафиксировать код результата.

    • passthru() → еще одна альтернатива exec, но всегда отправляет любые результаты STDOUT в выходной буфер PHP. Какой из них делает его наиболее подходящей оболочкой exec.

    • popen() или лучше proc_open() → позволяют индивидуально фиксировать STDOUT и STDERR.

  • Большинство ошибок оболочки заканчиваются на PHP или Apaches error.log, если они не перенаправлены. Проверьте свой журнал syslog или Apache, если ничего не дает полезных сообщений об ошибках.

Наиболее распространенными проблемами, возникающими у новичков PHP/LAMP, являются:

  • Как уже упоминалось @Kuf: для устаревших планов веб-хостинга вы все равно можете найти safe_mode или disable_functions. Ни одна из функций exec PHP не будет работать. (Лучше всего найти лучшего провайдера, иначе расследуйте "CGI", но не не устанавливайте собственный PHP-интерпретатор, пока не развернуты.)

  • Аналогично может существовать AppArmor/SELinux/Firejail. Они ограничивают способность каждого приложения создавать новые процессы.

  • Предложенный двоичный файл не существует. Практически нет веб-хоста, у которого есть такие инструменты, как ffmpeg. Вы не можете просто запускать произвольные команды оболочки без подготовки. Некоторые вещи необходимо установить!

    // Check if `ffmpeg` is actually there:
    var_dump(shell_exec("which ffmpeg"));
    
  • PATH выключен. Если вы установили специальные инструменты, вам необходимо убедиться, что они доступны. Использование var_dump(shell_exec("ffmpeg -opts")) будет искать все общие пути - или, как сказано/ограничено Apache (часто просто /bin:/usr/bin).

    Проверьте с помощью print_r($_SERVER);, что содержит ваш PATH, и если он охватывает инструмент, который вы хотите запустить. Кроме того, вам может потребоваться адаптировать настройки сервера (/etc/apache2/envvars) или использовать полные пути:

    // run with absolute paths to binary
    var_dump(shell_exec("/bin/sh -c '/usr/local/bin/ffmpeg -opts 2>&1'"));
    

    Это несколько подрывает концепцию оболочки. Лично я не считаю это предпочтительным. Однако это имеет смысл для целей безопасности; кроме того, для использования пользовательской установки, конечно.

  • <сильные > Права доступа

    • Чтобы запустить двоичный код в системе BSD/Linux, его нужно сделать "исполняемым". Это то, что делает chmod a+x ffmpeg.

    • Дальнейшее изменение пути к таким пользовательским двоичным файлам должно быть доступно для чтения Apache user, с которыми работают ваши скрипты PHP.

    • Более современные настройки используют PHP, встроенные в режим FPM (suexec + FastCGI), где ваша учетная запись веб-хостинга равна тем, с чем работает PHP.

  • Тест SSH. Это должно быть само собой разумеющимся, но перед запуском команд через PHP тестирование его в реальной оболочке было бы очень разумным. Зонд, например. ldd ffmpeg, если существуют все зависимости lib, и если они работают иначе.

  • Входные значения (GET, POST, имена FILE, пользовательские данные), которые передаются как аргументы команды в exec, должны быть экранированы с помощью escapeshellarg().

    $q = "escapeshellarg";
    var_dump(shell_exec("echo {$q($_GET['text'])} | wc"));
    

    В противном случае вы легко получите ошибки синтаксиса оболочки; и, вероятно, использовать код, установленный позже...