Solución:
Mira esto /etc/php.ini
, ahí debajo:
; 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 =
asegúrese de que el ejecutivo no esté listado así:
disable_functions=exec
Si es así, elimínelo y reinicie apache.
Para una depuración fácil, generalmente me gusta ejecutar el archivo php manualmente (puedo solicitar más errores sin configurarlo en el ini principal). para hacerlo agregue el encabezado:
#!/usr/bin/php
ini_set("display_errors", 1);
ini_set("track_errors", 1);
ini_set("html_errors", 1);
error_reporting(E_ALL);
al principio del archivo, dele permisos usando chmod +x myscript.php
y ejecutarlo ./myscript.php
. Es muy atento, especialmente en un servidor ocupado que escribe mucho en el archivo de registro.
EDITAR
Suena como un permisos asunto. Cree un script bash que haga algo simple como echo "helo world"
e intenta ejecutarlo. Asegúrate de tener permisos para el archivo. y para la carpeta que contiene el archivo. deberías simplemente hacer chmod 755
solo para probar.
Dado que está saliendo del contexto PHP en el shell nativo, tendrá muchos problemas de depuración.
Lo mejor y más infalible que he usado en el pasado es escribir la salida del script en un archivo de registro y seguirlo durante la ejecución de PHP.
<?php
shell_exec("filename > ~/debug.log 2>&1");
Luego, en un caparazón separado:
tail -200f ~/debug.log
Cuando ejecuta su script PHP, sus errores y la salida de su llamada de shell se mostrarán en su debug.log
expediente.
Algunas notas más
-
Para la depuración, envuelva siempre su función exec / shell_exec en
var_dump()
. -
error_reporting(-1);
debería estar encendido, como debería estardisplay_errors
, como último recurso inclusoset_error_handler("var_dump");
– aunque solo sea para ver si PHP mismo no invocóexecvp
si no. -
Usar
2>&1
(fusionar el flujo de shells STDERR con STDOUT) para ver por qué falla una invocación.
En algunos casos, es posible que deba envolver su comando en una invocación de shell adicional:// capture STDERR stream via standard shell echo shell_exec("/bin/sh -c 'ffmpeg -opts 2>&1' ");
De lo contrario el redireccionamiento del archivo de registro como aconseja @Mike es el enfoque más recomendable.
-
Alterne entre las diversas funciones ejecutivas para descubrir mensajes de error. Si bien en su mayoría hacen lo mismo, las rutas de retorno de salida varían:
-
exec()
→ devuelve la salida como resultado de la función, o a través de la opción$output
paramater.
También proporciona un$return_var
parámetro, que contiene el código errno / exit de la aplicación de ejecución o shell. Puede obtener:-
ENOENT
(2) – No existe tal archivo -
EIO
(127) – Error de E / S: archivo no encontrado
// run command, conjoined stderr, output + error number var_dump(exec("ffmpeg -h 2>&1", $output, $errno), $output, $errno));
-
-
shell_exec()
→ es lo que desea ejecutar principalmente para expresiones de estilo shell.
Asegúrese de asignar / imprimir el valor de retorno con, por ejemplo,var_dump(shell_exec("..."));
-
``
comillas invertidas en línea → son idénticas ashell_exec
. -
system()
→ es similar aexec
, pero siempre devuelve la salida como resultado de la función (¡imprímalo!). Además permite capturar el código de resultado. -
passthru()
→ es otroexec
alternativa, pero siempre envía los resultados de STDOUT al búfer de salida de PHP. Lo que a menudo lo convierte en el contenedor ejecutivo más adecuado. -
popen()
o mejorproc_open()
→ permite capturar STDOUT y STDERR individualmente.
-
-
La mayoría de los errores de shell terminan en PHP o Apaches
error.log
cuando no se redirige. Verifique su syslog o el registro de Apache si nada arroja mensajes de error útiles.
Problemas más comunes
-
Como lo menciona @Kuf: para planes de alojamiento web obsoletos, aún puede encontrar
safe_mode
odisable_functions
activado. Ninguna de las funciones ejecutivas de PHP funcionará. (Lo mejor es encontrar un mejor proveedor; de lo contrario, investigue “CGI”, pero no instale su propio intérprete de PHP mientras no está leído). -
Del mismo modo puede AppArmor / SELinux / Firejail a veces estar en su lugar. Esos limitan la capacidad de cada aplicación para generar nuevos procesos.
-
La intención binario no existe. Prácticamente ningún servidor web tiene herramientas como
ffmpeg
pre instalado. No puede simplemente ejecutar comandos de shell arbitrarios sin preparación. ¡Es necesario instalar algunas cosas!// Check if `ffmpeg` is actually there: var_dump(shell_exec("which ffmpeg"));
-
los
PATH
esta apagado. Si instaló herramientas personalizadas, deberá asegurarse de que estén accesibles. Utilizandovar_dump(shell_exec("ffmpeg -opts"))
buscará todas las rutas comunes, o como se le ha dicho / restringido a Apache (a menudo solo/bin:/usr/bin
).Comprobar con
print_r($_SERVER);
qué contiene su PATH y si eso cubre la herramienta que desea ejecutar. De lo contrario, es posible que deba adaptar la configuración del servidor (/ etc / apache2 / envvars) o utilizar rutas completas:// run with absolute paths to binary var_dump(shell_exec("/bin/sh -c '/usr/local/bin/ffmpeg -opts 2>&1'"));
Esto está subvirtiendo un poco el concepto de caparazón. Personalmente, no creo que esto sea preferible. Sin embargo, tiene sentido por motivos de seguridad; además, por utilizar una instalación personalizada, por supuesto.
-
Permisos
-
Para ejecutar un binario en un sistema BSD / Linux, debe hacerse “ejecutable”. Esto es lo que
chmod a+x ffmpeg
lo hace. -
Además, la ruta a dichos binarios personalizados debe ser legible por el Usuario de Apache, bajo el cual se ejecutan sus scripts PHP.
-
Las configuraciones más contemporáneas usan PHP incorporado en el modo FPM (suexec + FastCGI), donde su cuenta de alojamiento web es igual a la que se ejecuta PHP.
-
-
Prueba con SSH. No hace falta decirlo, pero antes de ejecutar comandos a través de PHP, probarlo en un shell real sería muy sensato. Sonda con, por ejemplo
ldd ffmpeg
si todas las dependencias de lib están ahí, y si funciona de otra manera. -
Usar
namei -m /Usr/local/bin/ffmpeg
para sondear toda la ruta, si no está seguro de dónde pueden surgir problemas de permisos de acceso. -
Valores de entrada (GET, POST, nombres de FILE, datos de usuario) que se pasan como argumentos de comando en exec las cadenas deben escaparse con
escapeshellarg()
.$q = "escapeshellarg"; var_dump(shell_exec("echo {$q($_GET['text'])} | wc"));
De lo contrario, obtendrá fácilmente errores de sintaxis de shell; y probablemente explotar el código instalado más tarde …
-
Tenga cuidado de no combinar las comillas inversas con ninguno de los
*exec()
funciones:$null = shell_exec(`wc file.txt`); ↑ ↑
Las comillas invertidas ejecutarían el comando y dejarían shell_exec con la salida del comando ya ejecutado. Utilice comillas normales para envolver el parámetro de comando.
-
También verifique en una sesión de shell cómo funciona el programa previsto con una cuenta diferente:
sudo -u www-data gpg -k
En particular, para las configuraciones de PHP-FPM, pruebe con la identificación de usuario correspondiente.
www-data
/apache
en su mayoría solo se utilizan en configuraciones mod_php antiguas.Muchas herramientas de cmdline dependen de alguna configuración por usuario. Esta prueba a menudo revelará lo que falta.
-
No puede obtener resultados para procesos de ejecución en segundo plano que se inician con
… &
onohup …
. En tales casos, definitivamente necesita usar una redirección de archivo de registroexec("cmd > log.txt 2>&1 &");
En Windows
-
Las invocaciones de CMD no funcionan bien con las transmisiones STDERR a menudo.
-
Definitivamente pruebe un script de Powershell para ejecutar cualquier otra aplicación CLI, o use una línea de comando como:
system("powershell -Command 'pandoc 2>&1'");
-
Utilice rutas completas y prefiera siempre las barras diagonales (
"C:/Program Files/Whatevs/run.exe"
con comillas adicionales si las rutas contienen espacios).Las barras diagonales también funcionan en Windows, desde que se introdujeron en MS-DOS 2.0
-
Averigüe con qué servicio y cuenta SAM se ejecutan IIS / Apache y PHP. Verifique que tenga permisos de ejecución.
-
Por lo general, no puede ejecutar aplicaciones GUI. (La solución típica es el programador de tareas o las invocaciones de WMI).
PHP → Python, Perl
Si está invocando otro intérprete de secuencias de comandos de PHP, utilice cualquier medio de depuración disponible en caso de fallas:
passthru("PYTHONDEBUG=2 python -vvv script.py 2>&1");
passthru("perl -w script.pl 2>&1");
passthru("ruby -wT1 script.rb 2>&1");
O tal vez incluso ejecutar con cualquier sintaxis -c
marque la opción primero.