PHP shell_exec () vs exec ()

345

Estoy luchando por entender la diferencia entre shell_exec()y exec()...

Siempre solía exec()ejecutar comandos del lado del servidor, ¿cuándo los usaría shell_exec()?

¿Es shell_exec()solo una taquigrafía para exec()? Parece ser lo mismo con menos parámetros.

Webnet
fuente
2
buen ejemplo para ver las diferencias es tratar estos comandos: date, whoami, ifconfig, netstat.
También hay otras funciones: system (), passthru () ... vea esta pregunta relacionada , y en particular esta respuesta .
Gras Double
1
Posible duplicado de PHP exec () vs system () vs passthru ()
jww

Respuestas:

353

shell_execdevuelve todo el flujo de salida como una cadena. execdevuelve la última línea de salida de forma predeterminada, pero puede proporcionar toda la salida como una matriz especificada como el segundo parámetro.

Ver

Daniel A. White
fuente
21
Si necesita el valor de salida Y toda la salida, probablemente todavía sea mejor usar "exec" en lugar de "shell_exec". Tan pronto como pase el parámetro de salida a "exec", se completará con cada línea de la salida, me parece que "exec" puede todo lo de "shell_exec" y más :)
Preexo
44
@ daniel-a-white Sé que este es antiguo, pero es popular, por lo que debe editar su respuesta para reflejar el comentario hecho por @preexo - exec () también tiene la capacidad de devolver la salida completa si usa sus parámetros opcionales . Además, sin relación, alguien debería comparar los dos comandos para ver cuál es mejor porque @preexo dijo " me parece que exec()puedo [hacer] todo shell_exec()[puede,] y más :) "
SimpleAnecdote
77

Aquí están las diferencias. Tenga en cuenta las nuevas líneas al final.

> shell_exec('date')
string(29) "Wed Mar  6 14:18:08 PST 2013\n"
> exec('date')
string(28) "Wed Mar  6 14:18:12 PST 2013"

> shell_exec('whoami')
string(9) "mark\n"
> exec('whoami')
string(8) "mark"

> shell_exec('ifconfig')
string(1244) "eth0      Link encap:Ethernet  HWaddr 10:bf:44:44:22:33  \n          inet addr:192.168.0.90  Bcast:192.168.0.255  Mask:255.255.255.0\n          inet6 addr: fe80::12bf:ffff:eeee:2222/64 Scope:Link\n          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n          RX packets:16264200 errors:0 dropped:1 overruns:0 frame:0\n          TX packets:7205647 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000 \n          RX bytes:13151177627 (13.1 GB)  TX bytes:2779457335 (2.7 GB)\n"...
> exec('ifconfig')
string(0) ""

Tenga en cuenta que el uso del operador de retroceso es idéntico a shell_exec().

Actualización: realmente debería explicar eso último. ¡Mirando esta respuesta años después, ni siquiera sé por qué quedó en blanco! Daniel lo explica arriba: es porque execsolo devuelve la última línea y ifconfigla última línea está en blanco.

mpen
fuente
¿Qué sucede si se produce un error con el comando ..? Recibo el error / No existe tal archivo o directorio, pero ¿cómo puedo capturarlo en una variable?
Happy Coder
@AlwinAugustin: ¿Eh? Podría estar siendo escrito a STDERR. Intente agregar 2>&1al final de su comando para redirigir STDERR a STDOUT si está en una máquina Linux.
mpen
Lo he agregado también. Pero aún así obtengo 0 como valor. He usado un comando wc -l y si el archivo no está allí, necesito recibir el mensaje de error que dice No existe tal archivo o directorio.
Happy Coder
50

shell_exec- Ejecute el comando a través de shell y devuelva la salida completa como una cadena

exec - Ejecuta un programa externo.

La diferencia es que con shell_execusted obtiene la salida como un valor de retorno.

J0HN
fuente
44
Bonito resumen sucinto! Todavía debe tenerse en cuenta que execdevuelve la última línea de la salida. Si lo desea, puede pasar opcionalmente una matriz como el segundo parámetro para capturar la salida completa, y un número entero como el tercer parámetro para capturar el valor de retorno del comando de shell, que puede usarse para la verificación de errores. El mayor inconveniente shell_execes que devuelve nulo si el comando falla O si no produce ningún resultado, por lo que su valor de retorno no se puede usar de manera confiable para la verificación de errores.
Sean the Bean
38

Un par de distinciones que no se mencionaron aquí:

  • Con exec (), puede pasar una variable param opcional que recibirá una matriz de líneas de salida. En algunos casos, esto puede ahorrar tiempo, especialmente si la salida de los comandos ya es tabular.

Comparar:

exec('ls', $out);
var_dump($out);
// Look an array

$out = shell_exec('ls');
var_dump($out);
// Look -- a string with newlines in it

Por el contrario, si la salida del comando es xml o json, entonces tener cada línea como parte de una matriz no es lo que desea, ya que deberá procesar posteriormente la entrada en otra forma, por lo que en ese caso use shell_exec .

También vale la pena señalar que shell_exec es un alias para el operador backtic, para aquellos que se usan para * nix.

$out = `ls`;
var_dump($out);

exec también admite un parámetro adicional que proporcionará el código de retorno del comando ejecutado:

exec('ls', $out, $status);
if (0 === $status) {
    var_dump($out);
} else {
    echo "Command failed with status: $status";
}

Como se señaló en la página del manual shell_exec, cuando realmente necesita un código de retorno del comando que se está ejecutando, no tiene más remedio que usar exec.

gview
fuente
3
Además: le execpermite obtener el código de retorno del comando (a través del &$return_varparámetro), mientras que shell_execno proporciona ninguna forma de obtenerlo.
Mark Amery
Aunque la respuesta aceptada también es correcta, en mi opinión, esta respuesta es más importante. Probablemente la mejor respuesta sería una combinación de ambos.
UncaAlby