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.

Webnet
fonte
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
11
Possível duplicado de PHP exec () vs sistema () vs intermediário ()
JWW

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

Daniel A. White
fonte
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.

mpen
fonte
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.

J0HN
fonte
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.

gview
fonte
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