• Publicidad

Ejecutar comandos Linux

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Ejecutar comandos Linux

Notapor jimr1984 » 2016-02-05 15:56 @706

Saludos, buenas tardes.

Por favor, si pueden darme una mano para ejecutar comandos Linux y guardar el resultado en una variable, para luego manipularla en un array.

Yo estoy realizando lo siguiente. El problema es cuando aumento awk '' y grep " "
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $comando  =  system(grep "for .*@.*" /var/log/exim_mainlog | grep "<= <>" | awk -F"T=" '{print $2}' | awk '{print $NF,$0}' | awk -F" for" '{print $1}' | sort | uniq -c | sort -n);
  2.  
  3. my $comando2  = system(exim -bpr | grep "<" | awk {'print $4'} | cut -d "<" -f 2 | cut -d  ">" -f 1 | sort -n | uniq -c | sort -n);
  4.  
  5. my $comando3= system(exim -bpr | exiqsumm -c | head | awk '{print $1,$2}');
  6.  
  7.  
  8. print $comando."\n";
  9. print $comando2."\n";
  10. print $comando3."\n";
  11.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Por las comillas o comillas dobles.

NOTA: utilicé system() y qx(), pero no me dió resultados.

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$  exim –bpr | exiqsumm –c | head  
Count  Volume  Oldest  Newest  Domain
-----  ------  ------  ------  ------

   51    72MB      4d     26m  abcd.bo
   50  2203KB     33h      5h  adasd.com
   10   287KB      3d      8h  ddddddd.com
    8    52KB     24h      2h  aaaaaaaaaa.com.bo
    8    6825      3d      6h  bbbbbbb.it
    5   699KB     71h     14h  44sssss.com


$ exim -bpr | exiqsumm -c | head  | awk '{print $2} '

Volume
------

72MB
2203KB
287KB
52KB
6825
699KB
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Así debería guardarme el resultado.

Aguardo si pueden ayudarme. Gracias.
Última edición por explorer el 2016-02-05 17:03 @752, editado 2 veces en total
Razón: Corrección ortográfica, poner marcas de texto y Perl.
jimr1984
Perlero nuevo
Perlero nuevo
 
Mensajes: 123
Registrado: 2012-11-25 07:11 @341

Publicidad

Re: Ejecutar comandos Linux

Notapor explorer » 2016-02-05 18:33 @815

Hay dos fallos: la función system() no sirve para lo que quieres. Esta función es cierto que ejecuta un comando en el sistema, pero no devuelve el resultado de la ejecución (la salida estándar), sino el ESTADO del resultado de la ejecución. Es decir, devolverá un 0 o un 1 según el último comando se ejecutó sin problemas u ocurrió un error.

Como lo que quieres es obtener la salida (estándar) del resultado de una serie de comandos en línea, debes usar las comillas inversas (``) o qx().

Ahora bien... ¿por qué no te funciona cuando usas qx()? Ahora viene el segundo fallo.

Resulta que qx() es un comando "de entrecomillado". Quiere decir que lo que pongamos dentro de los paréntesis será interpolado por Perl ANTES de pasarse al sistema. Una interpolación igual a la que ocurre con comillas dobles.

Y ahí está el problema: en tus comandos hay cosas como $1 o $NF. Y para Perl, esas cosas son variables escalares, así que las interpolará -sacará su valor como si fueran variables Perl y pondrá ese valor en la línea de comandos.

Pero eso no son variables para Perl. Son variables para el shell o para el awk. Así que hay que evitar que Perl las reconozca.

La solución es "escapar" el significado de los '$', para que pasen directamente a la línea de comandos que se ejecutará por el sistema:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2.  
  3. my $comando  = qx(grep 'for .*@.*' /var/log/exim4/mainlog | grep '<= <>' | awk '{print \$NF, \$0}' | awk -F ' for' '{print \$1}' | sort | uniq -c | sort -n);
  4. my $comando2 = qx(exim -bpr | grep "<" | awk {'print \$4'} | cut -d "<" -f 2 | cut -d  ">" -f 1 | sort -n | uniq -c | sort -n);
  5. my $comando3 = qx(exim -bpr | exiqsumm -c | head | awk '{print \$1,\$2}');
  6.  
  7. print $comando  . "\n";
  8. print $comando2 . "\n";
  9. print $comando3 . "\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

O... también... hay otra forma...

Usar las comillas simples como delimitadores de qx()... pero entonces no podemos usar comillas simples en la línea de comandos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $comando  = qx'comando $1 $2 $3';   # $1, $2 y $3 son variables del shell. No son variables Perl
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

(Más información en perldoc perlop, sección Quote-Like Operators).

Ahora bien... ¿Por qué tanto lío? ¿No es mejor resolver este problema solo con Perl? Nuestro lenguaje favorito es capaz de hacer todo eso, de forma más independiente del sistema (no necesitas que en tu sistema estén instalados los comandos sort, uniq, cut, head, grep y awk).

¿Qué es lo que hace este programa? Sacar estadísticas de actividad del sistema de correo electrónico.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3. use autodie;
  4.  
  5. ## Listado de mensajes rebotados
  6. my $archivo_log = '/var/log/exim4/mainlog';
  7.  
  8. my %emails;
  9.  
  10. open my $LOG, '<', $archivo_log;
  11.  
  12. while (<$LOG>) {
  13.     next if not /<= <>/;
  14.     next if not / for (\S+)/;    
  15.  
  16.     $emails{ $1 }++;
  17. }
  18.  
  19. close   $LOG;
  20.  
  21. for my $email ( sort { $emails{$a} <=> $emails{$b} } keys %emails ) {
  22.     say "$emails{$email}\t$email";
  23. }
  24.  
  25. ## Remitentes con mensajes pendientes de entrega
  26. my %pendientes;
  27.  
  28. open my $PENDIENTES, 'exim4 -bpr|';
  29.  
  30. while (<$PENDIENTES>) {
  31.     next if not /<(.*?)>/;
  32.  
  33.     $pendientes{ $1 }++;
  34. }
  35.  
  36. close   $PENDIENTES;
  37.  
  38. for my $pend ( sort { $pendientes{$a} <=> $pendientes{$b} } keys %pendientes ) {
  39.     say "$pendientes{$pend}\t$pend";
  40. }
  41.  
  42. ## Tamaño de los mensajes pendientes de entrega
  43. my %size;
  44.  
  45. open my $SIZE, 'exim4 -bpr| exiqsumm -c|';
  46.  
  47. while (<$SIZE>) {
  48.     my @campos = split;
  49.     say $campos[1] ;
  50. }
  51.  
  52. close   $SIZE;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 3 invitados

cron