Как я могу отлаживать проблемы 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"));
В противном случае вы легко получите ошибки синтаксиса оболочки; и, вероятно, использовать код, установленный позже...