Saltar al contenido

¿Cómo puedo depurar problemas de exec ()?

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 estar display_errors, como último recurso incluso set_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:

    1. 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));
      
    2. 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("..."));

    3. `` comillas invertidas en línea → son idénticas a shell_exec.

    4. system() → es similar a exec, pero siempre devuelve la salida como resultado de la función (¡imprímalo!). Además permite capturar el código de resultado.

    5. passthru() → es otro exec 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.

    6. popen() o mejor proc_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 o disable_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. Utilizando var_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

    1. Para ejecutar un binario en un sistema BSD / Linux, debe hacerse “ejecutable”. Esto es lo que chmod a+x ffmpeg lo hace.

    2. Además, la ruta a dichos binarios personalizados debe ser legible por el Usuario de Apache, bajo el cual se ejecutan sus scripts PHP.

    3. 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 … & o nohup …. En tales casos, definitivamente necesita usar una redirección de archivo de registro exec("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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *