[Cascavel-pm] Duvida com exec

breno breno em rio.pm.org
Segunda Agosto 18 10:57:38 PDT 2008


Agustinho,

o pessoal aqui é muito bom, conte com eles para ajudá-lo em sua busca
por conhecimento e *aceite* os conselhos sobre system() x exec(),
Net::Ping e módulos de envio de email (eu particularmente gosto do
Net::SMTP e MIME::Lite, queria saber a opinião dos outros).

Mas, técnicas de programação Perl a parte, acho que seu programa não
está fazendo o que vc quer por alguns erros de sintaxe. Veja:

> exec ('ping -c4 192.168.0.122 > /dev/null 2&1');

vc tentou rodar isso na mão? O comando:

ping -c4 192.168.0.122 > /dev/null 2&1

roda como se fossem 2 comandos:

(1o comando): ping -c4 192.168.0.122 > /dev/null 2&

(2o comando): 1

Daí o resultado ser algo como:

[1] 8442         (primeiro comando sendo executado em background devido ao "&")
bash: 1: command not found    (segundo comando, "1", não é um comando válido)

Se esperar um pouco, verá o comando que rodou em background sendo finalizado:


[1]+  Exit 1            ping ping -c4 192.168.0.122 2 > /dev/null
(note o "2" do seu comando)


Pelo comando que vc escreveu, acho q o q vc quer é redirecionar a
saída para o /dev/null. Então, o q vc deve fazer é:

ping -c4 192.168.0.122 > /dev/null 2>&1


Primeiro problema resolvido. Dito isso, lembre-se da dica do Russo e
cia, pois como o exec não retorna, não dá pra testar o valor de $?
como vc faria com system(). Vamos trocar a linha por:

system ( 'ping -c4 192.168.0.122 > /dev/null 2>&1' );

E aí surge o problema 2 do código enviado:

> if ( $? == 0 ); then {

Tem dois problemas aí. O ponto e vírgula após o "if" (que mata a
instrução) e o "then" (que não faz parte da sintaxe do Perl). Como o
código assim simplesmente não compila, estou assumindo confusão na
hora de escrever o email, e que o seu código na verdade está assim:

if ( $? == 0 ) {

Dito isso, vamos ao envio de email em si:

>      exec ('echo "teste" | mail -s "host $(hostname) is up" email em dominio.com.br');

Esse comando funciona corretamente, supondo que seu MTA está
propriamente configurado, assim como o "mail". Há algumas restrições
sobre modo interativo, mailboxes, permissões, etc, não estou muito
familiarizado com o "mail" para te dar dicas de depuração que não
seja: não faça isso, use módulos. Mas testei aqui e, com tudo
configurado, fuciona. Lembre-se, no entanto, que (exatamente como
Alceu, Champs e Rondon já te disseram), desse jeito vc não tem
garantia nenhuma de que o email sequer saiu da sua máquina, pois não
há verificação alguma em relação ao comando "mail", muito menos em
cima de um "exec".

> } else {
>       exec ('echo "teste" | mail -s "host $(hostname)is down " email em dominio.com.br');
> }

outra dica (além das óbvias, "não faça isso, vc está programando Perl
com sotaque de Shell Scripting, use módulos, etc") é fazer mais ou
menos assim:

------------------8<-------------------
my $status = "down";
system ( 'ping -c4 192.168.0.122 > /dev/null 2>&1' );
if ( $? == 0 ) {
    $status = 'up';
}
exec ( 'echo "teste" | mail -s "host $(hostname) is ' . $status . ' "
email em dominio.com.br' );
------------------8<-------------------

Mas de qq forma essa não é a forma adequada de se usar $?, é? perldoc
-f system para mais informações.

Além disso, lembre-se que vc está testando 192.168.0.122 e não
$(hostname), que devolverá o nome da sua máquina local. Isso é outro
ponto possível de falhas e que não escala bem, além do seu ' echo
"teste" ' que tenho certeza não ser o que vc de fato vai mandar por
email :-)

De novo, não faça isso. Use módulos! :-)

Mas se há urgência, isso deve funcionar. Melhore o código à medida que
for aprendendo mais Perl (e se livrando do sotaque de Shell)

Boa sorte! E continue mandando suas dúvidas para a lista!

[]s

-b

2008/8/13 Luis Motta Campos <luismottacampos em yahoo.co.uk>:
> Agustinho Coelho wrote:
>>
>>> RTFM:
>>>
>>>       exec LIST
>>>       exec PROGRAM LIST
>>>               The "exec" function executes a system command and never
>>> returns-- use "system" instead of "exec" if you
>>>               want it to return.  It fails and returns false only if the
>>> command does not exist and it is executed
>>>               directly instead of via your system's command shell (see
>>> below).
>>>
>>> []s,
>>> Russo
>>
>> Russo,
>>
>> Eu li o manual e já tinha tentado antes do exec() usar o system() de
>> diversas maneiras mas sem conseguir o efeito desejado. Achava que justamente
>> por não retornar uma saída ele fosse mais simples. Segue o código como
>> estava com o system() (seguindo exemplo do próprio perldoc):
>>
>> #/usr/bin/perl -w
>>
>> use strict;
>> use warnings;
>>
>> my @ping = ("ping" , "-c4" , "192.168.0.222" , " " , "\>" , " " ,
>> "/dev/null\>2\&1");
>> my @mailup = ("sendmail" , "-f" , "user\@host.com.br" , "-t" ,
>> "user\@host.com.br" , " " , "\<" , " " , "/home/bkpuser/netmailup.txt");
>> my @maildown = ("sendmail" , "-f" , "user\@host.com.br" , "-t" ,
>> "user\@host.com.br" , " " , "\<" , " " , "/home/bkpuser/netmaildown.txt");
>>
>> system (@ping);
>>
>> if ( $? == 0 ) {
>>       system (@mailup);
>> } else {
>>       system (@maildown);
>> }
>>
>> Eu tentei escapar todos os caracteres duvidosos, tentei interpolar de
>> várias maneiras, mas sem sucesso algum. Ele sempre apresenta os seguintes
>> erros:
>> *sh: 1: command not found* ou *ping: unknown host >
>> *
>
> Mamma mia, nem posso acreditar. Alguém que tentou tratar erros do system().
>
> Parabéns, Daniel. A única coisa que você não fez certo é esperar que o
> system() incorpore a tua variável de ambiente PATH. Não tem PATH setado
> quando você executa system, esta é a regra (sim, pode haver path, mas isso é
> excessão).
>
> Assim, você precisa passar caminho completo para todos os comandos que
> executar:
>
>  __PERL__
>  my @ping = ("ping" , "-c4" , "192.168.0.222" );
>  if ($? == -1) {
>    print "failed to execute: $!\n";
>  }
>  elsif ($? & 127) {
>    printf "child died with signal %d, %s coredump\n",
>      ($? & 127),  ($? & 128) ? 'with' : 'without';
>  }
>  else {
>    printf "child exited with value %d\n", $? >> 8;
>  }
>
>  Repare em como eu trato erros de ping.
>
>  Agora, sério: se você vai "pingar" uma máquina, use o Net::Ping. E, se
> pretende mandar emails, use Mail::Send ou seu módulo de SMTP favorito...
> tenho certeza de que bastante gente aqui pode te dar boas indicações.
>
>  Putamplexos.
> --
> Luis Motta Campos is a software engineer,
> Perl Programmer, foodie and photographer.
> _______________________________________________
> Cascavel-pm mailing list
> Cascavel-pm em pm.org
> http://mail.pm.org/mailman/listinfo/cascavel-pm
>


Mais detalhes sobre a lista de discussão Cascavel-pm