Вопрос по php – Как я могу отладить проблемы exec ()?

13

Команда 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 не работает.

Вы пробовали error.log? Rolice
Журнал ошибок не показывает ничего о проблеме. я имеюdisplay_errors а такжеerror_reporting активируется. Все еще не могу найти ничего о проблеме. carcargi
Что вы подразумеваете под "не работает"? ? Любая ошибка вывода? Touki
Настройки ошибокdisplay_errors = 1 а такжеerror_report = E_ALL? (Обратите внимание, что вы не должны отображать ошибки в реальных системах. Отключите его, если вы сделали) KingCrunch

Ваш Ответ

4   ответа
11

посмотри на/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, Он очень внимателен, особенно на занятом сервере, который много записывает в файл журнала.

EDIT

Звучит какpermissions вопрос. Создайте скрипт bash, который делает что-то простое, какecho "helo world" и попробуйте запустить его. Убедитесь, что у вас есть разрешения для файлаand for the folder containing the file, ты должен просто сделатьchmod 755 только для тестирования.

Большое спасибо, что сделал свое дело, проблема была в том, что каким-то образом (поскольку у моего клиента есть доступ к серверу, и он считает себя экспертом по XD), он скопировал и изменил разрешения приложений. Я переместил их обратно в исходную папку и снова настроил путь, теперь все работает, я обнаружил это при тестировании разрешений приложения. Благодарю. carcargi
disable_functions пуст в моемphp.iniЯ запускаю сценарий, как вы предложили, и консоль ничего не показывает. carcargi
@ Necroside рады помочь!
@Necroside ответ обновлен.
@Necroside он изменил разрешенияwhoami??
3
A few more notes

var_dump().

error_reporting(-1); should be on, as should be display_errors, as last resort even set_error_handler("var_dump"); - if only to see if PHP itself didn't invoke execvp or else.

Use 2>&1 (merge the shells STDERR to STDOUT stream) to see why an invocation fails.
For some cases you may need to wrap your command in an additional shell invocation:

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

Else the log file redirect as advised by @Mike is the most recommendable approach.

Alternate between the various exec functions to uncover error messages otherwise. While they mostly do the same thing, the output return paths vary:

exec() → either returns the output as function result, or through the optional $output paramater.
Also provides a $return_var parameter, which contains the errno / exit code of the run application or shell. You might get:

ENOENT (2) - No such file EIO (127) - IO error: file not found

shell_exec() → is what you want to run mostly for shell-style expressions.
Be sure to assign/print the return value with e.g. var_dump(shell_exec("..."));

`` inline backticks → are identical to shell_exec.

system() → is s,imilar to exec, but always returns the output as function result (print it out!). Additionally allows to capture the result code.

passthru() → is another exec alternative, but always sends any STDOUT results to PHPs output buffer. Which oftentimes makes it the most fitting exec wrapper.

popen() or better proc_open() → allow to individually capture STDOUT and STDERR.

Most shell errors wind up in PHPs or Apaches error.log when not redirected. Check your syslog or Apache log if nothing yields useful error messages.

Most common issues

As mentioned by @Kuf: for outdated webhosting plans, you could still find safe_mode or disable_functions enabled. None of the PHP exec functions will work. (Best to find a better provider, else investigate "CGI" - but do not install your own PHP interpreter while unversed.)

Likewise can AppArmor / SELinux / Firejail sometimes be in place. Those limit each applications ability to spawn new processes.

The intended binary does not exist. Pretty much no webhost does have tools like ffmpeg preinstalled. You can't just run arbitrary shell commands without preparation. Some things need to be installed!

// Check if `ffmpeg` is actually there:
var_dump(shell_exec("which ffmpeg"));

The PATH is off. If you installed custom tools, you will need to ensure they're reachable. Using var_dump(shell_exec("ffmpeg -opts")) will search all common paths - or as Apache has been told/constrained (often just /bin:/usr/bin).

Check with print_r($_SERVER); what your PATH contains and if that ,covers the tool you wanted to run. Else you may need to adapt the server settings (/etc/apache2/envvars), or use full paths:

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

This is somewhat subverting the shell concept. Personally I don't think this preferrable. It does make sense for security purposes though; moreover for utilizing a custom installation of course.

Permissions

In order to run a binary on BSD/Linux system, it needs to be made "executable". This is what chmod a+x ffmpeg does.

Furthermode the path to such custom binaries needs to be readable by the Apache user, which your PHP scripts run under.

More contemporary setups use PHPs builtin FPM mode (suexec+FastCGI), where your webhosting account equals what PHP runs with.

Test with SSH. It should go without saying, but before running commands through PHP, testing it in a real shell would be highly sensible. Probe with e.g. ldd ffmpeg if all lib dependencies are there, and if it works otherwise.

Input values (GET, POST, FILE names, user data) that get passed as command arguments in exec strings need to be escaped with escapeshellarg().

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

Otherwise you'll get shell syntax errors easily; and probably exploit code installed later on...

Take care not to combine backticks with any of the *exec() functions:

$null = shell_exec(`wc file.txt`);
                   ↑           ↑

Backticks would run the command, and leave shell_exec with the output of the already ran command. Use normal quotes for wrapping the command parameter.

Also check in a shell session how the intended program works with a different account:

sudo -u www-data gpg -k

Notably for PHP-FPM setups test with the according user id. www-data/apache are mostly just used by olden mod_php setups.

Many cmdline tools depend on some per-user configuration. This test will often reveal what's missing.

On Windows

CMD invocations will not play nice with STDERR streams often.

Definitely try a Powershell script to run any CLI apps else, or use a command line like:

system("powershell -Command 'pandoc 2>&1'");

Use full paths, and prefer forward slashes always ("C:/Program Files/Whatevs/run.exe" with additional quotes if paths contain spaces).

Forward slashes work on Windows too, ever since they were introduced in MS-DOS 2.0

Figure out which service and SAM account IIS/Apache and PHP runs as. Verify it has execute permissions.

You can't run GUI apps usually. (Typical workaround is the taskscheduler or WMI invocations.)

Отличный ответ, я удивлен, что у него больше нет голосов. Принятое решение не так полезно, как это.
6

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

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

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

Тогда в отдельной оболочке:

tail -200f ~/debug.log

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

4

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

exec('my command', $output, $return);
Просто добавил код к вопросу и не заметил этот ответ, он просто показывает это.Error Array ( ) carcargi
А что содержит переменная $ return_val?

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