PHP shell_exec () vs exec ()


345

Estou lutando para entender a diferença entre shell_exec()e exec()...

Eu sempre usei exec()para executar comandos do lado do servidor, quando eu usaria shell_exec()?

É shell_exec()apenas uma abreviação para exec()? Parece ser a mesma coisa com menos parâmetros.


2
bom exemplo para ver as diferenças é tentar estes comandos: date, whoami, ifconfig, netstat.

Existem também outras funções: system (), passthru ()… veja esta pergunta relacionada e, em particular, esta resposta .
— Gras Double

Respostas:


353

shell_execretorna todo o fluxo de saída como uma sequência. execretorna a última linha da saída por padrão, mas pode fornecer toda a saída como uma matriz especificada como o segundo parâmetro.

Vejo


21
Se você precisa do valor de saída E de toda a saída, provavelmente ainda é melhor usar "exec" do que "shell_exec". Assim que você passar o parâmetro de saída para "exec", ele será preenchido com cada linha da saída, parece-me "exec" pode tudo de "shell_exec" e mais :)
— Preexo

4
@ daniel-a-white Eu sei que é antiga, mas é popular, então você deve editar sua resposta para refletir o comentário feito por @preexo - exec () também tem a capacidade de retornar toda a saída se você usar seus parâmetros opcionais . Além disso, alguém deve comparar os dois comandos para ver qual é o melhor porque @preexo disse: " parece-me que exec()posso fazer tudo shell_exec()[pode e] e mais :) " #
— 314 SimpleAnecdote

77

Aqui estão as diferenças. Observe as novas linhas no 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) ""

Observe que o uso do operador backtick é idêntico ao shell_exec().

Atualização: Eu realmente deveria explicar essa última. Olhando para essa resposta anos depois, nem sei por que isso saiu em branco! Daniel explica isso acima - é porque execapenas retorna a última linha e ifconfiga última linha fica em branco.


o que acontece se ocorrer um erro com o comando ..? Estou recebendo o erro / Não existe esse arquivo ou diretório, mas como posso capturá-lo em uma variável ????
— Feliz Coder

@AlwinAugustin: Hein? Pode estar sendo escrito para STDERR. Tente adicionar 2>&1no final do seu comando para redirecionar STDERR para STDOUT se você estiver em uma máquina Linux.
— MPEN

Eu adicionei também. Mas ainda estou recebendo 0 como o valor. Eu usei um comando wc -l e, se o arquivo não estiver lá, preciso receber a mensagem de erro dizendo Não existe esse arquivo ou diretório.
— Feliz Coder

50

shell_exec- Executar comando via shell e retornar a saída completa como uma string

exec - Execute um programa externo.

A diferença é que shell_execvocê obtém a saída como um valor de retorno.


4
Resumo sucinto agradável! Deve-se notar ainda que execretorna a última linha da saída. Se desejar, é possível transmitir opcionalmente uma matriz como o segundo parâmetro para capturar a saída completa e um número inteiro como o terceiro parâmetro para capturar o valor de retorno do comando shell, que pode ser usado para verificação de erros. A maior desvantagem shell_execé que ele retorna nulo se o comando falhar OU se não produzir nenhuma saída, portanto, seu valor de retorno não pode ser usado com segurança para verificação de erros.
— Sean the Bean

38

Algumas distinções que não foram mencionadas aqui:

  • Com exec (), você pode passar uma variável param opcional que receberá uma matriz de linhas de saída. Em alguns casos, isso pode economizar tempo, especialmente se a saída dos comandos já for 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 outro lado, se a saída do comando for xml ou json, ter cada linha como parte de uma matriz não é o que você deseja, pois será necessário pós-processar a entrada em algum outro formato, portanto, nesse caso, use shell_exec .

Também vale ressaltar que shell_exec é um alias para o operador backtic, para aqueles que costumavam * nix.

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

exec também suporta um parâmetro adicional que fornecerá o código de retorno do comando executado:

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

Conforme observado na página de manual do shell_exec, quando você realmente requer um código de retorno do comando que está sendo executado, você não tem escolha a não ser usar exec.


3
Além disso: execpermite obter o código de retorno do comando (via &$return_varparâmetro), enquanto shell_execnão fornece nenhuma maneira de obtê-lo.
— Mark Amery

Embora a resposta aceita também esteja correta, na minha opinião, essa resposta é mais importante. Provavelmente a melhor resposta seria a combinação dos dois.
— UncaAlby
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.