• Publicidad

Problema con funcion qx()

¿Eres administrador de sistemas? Este foro es para todos aquellos temas relacionados con el uso de Perl para administración de sistemas.

Problema con funcion qx()

Notapor magnobalt » 2012-06-28 19:48 @866

Hola, comunidad.

Estoy realizando un script en Perl con agregados de bash, más precisamente con el comando find en este último, que me permite encontrar archivos de distintas extensiones y en un periodo de tiempo, para luego analizarlo en busca de malware.

El problema es que desde la consola al ejecutar el siguiente comando, por ejemplo,
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. find /home/user/www/ -type f \( -iname "*.php" -o  -iname "*.js" \) -mtime -1 -ls
  2.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

lo ejecuta sin problemas y realiza la búsqueda de todos los archivos que tengan la extensión php o js que se hayan modificado en un periodo de un 1 día.

El problema resulta al llevar este comando con la función qx() para luego analizar la salida y trabajarlo con Perl, pues me arroja errores de sintaxis en bash.

Al ejecutar de esta manera, en Perl:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. @files=qx(find /home/ -type f \( -iname "*.php" -o  -iname "*.js"\) -mtime -$t  -ls );
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

tengo el siguiente error sh: Syntax error: "(" unexpected

Entonces pensé en colocar doble barra diagonal:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. @files=qx(find /home/ -type f \( -iname "*.php" -o  -iname "*.js"\) -mtime -$t  -ls | awk '{print  \$8 ":" \$9":" \$11}');     
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

tengo el siguiente error find: expresión no válida; se esperaba encontrar un «)» pero no hay ninguno.


¿Alguna ayuda?

Muchas gracias
magnobalt
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2010-03-24 17:59 @791

Publicidad

Re: Problema con funcion qx()

Notapor explorer » 2012-06-28 20:35 @899

El error está en que '\)' está pegado a la comilla doble, por lo que find no lo interpreta como un argumento más.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2.  
  3. my $t = -1;
  4. my @files = qx(find . -type f \\( -iname "*.pl" -o -iname "*.txt" \\) -mtime $t -ls | awk '{print  \$8 ":" \$9 ":" \$10 ":" \$11}');
  5.  
  6. print "@files";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


De todas maneras, esto es muy ineficiente: estás llamando a dos comandos externos (find y awk) que, perfectamente, podrías hacer con el propio Perl.

Empezando por el find...

Perl viene con un programa que se llama find2perl, que sirve para traducir comandos find en programas Perl (de ahí le viene el nombre :) )

Entonces, si ejecutamos
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. find2perl  find . -type f \( -iname "*.pl" -o -iname "*.txt" \) -mtime -1 -ls
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

nos entrega a la salida estándar un programa así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #! /usr/bin/perl -w
  2.     eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
  3.         if 0; #$running_under_some_shell
  4.  
  5. use strict;
  6. use File::Find ();
  7.  
  8. # Set the variable $File::Find::dont_use_nlink if you're using AFS,
  9. # since AFS cheats.
  10.  
  11. # for the convenience of &wanted calls, including -eval statements:
  12. use vars qw/*name *dir *prune/;
  13. *name   = *File::Find::name;
  14. *dir    = *File::Find::dir;
  15. *prune  = *File::Find::prune;
  16.  
  17. sub wanted;
  18. sub ls ();
  19.  
  20.  
  21. my @rwx = qw(--- --x -w- -wx r-- r-x rw- rwx);
  22. my @moname = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
  23.  
  24. my (%uid, %user);
  25. while (my ($name, $pw, $uid) = getpwent) {
  26.     $user{$uid} = $name unless exists $user{$uid};
  27. }
  28.  
  29. my (%gid, %group);
  30. while (my ($name, $pw, $gid) = getgrent) {
  31.     $group{$gid} = $name unless exists $group{$gid};
  32. }
  33.  
  34.  
  35. # Traverse desired filesystems
  36. File::Find::find({wanted => \&wanted}, 'find', '.');
  37. exit;
  38.  
  39.  
  40. sub wanted {
  41.     my ($dev,$ino,$mode,$nlink,$uid,$gid);
  42.  
  43.     (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
  44.     -f _ &&
  45.     (
  46.         /^.*\.pl\z/si
  47.         ||
  48.         /^.*\.txt\z/si
  49.     ) &&
  50.     (int(-M _) < 1) &&
  51.     ls;
  52. }
  53.  
  54.  
  55. sub sizemm {
  56.     my $rdev = shift;
  57.     sprintf("%3d, %3d", ($rdev >> 8) & 0xff, $rdev & 0xff);
  58. }
  59.  
  60. sub ls () {
  61.     my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
  62.         $atime,$mtime,$ctime,$blksize,$blocks) = lstat(_);
  63.     my $pname = $name;
  64.  
  65.     $blocks
  66.         or $blocks = int(($size + 1023) / 1024);
  67.  
  68.     my $perms = $rwx[$mode & 7];
  69.     $mode >>= 3;
  70.     $perms = $rwx[$mode & 7] . $perms;
  71.     $mode >>= 3;
  72.     $perms = $rwx[$mode & 7] . $perms;
  73.     substr($perms, 2, 1) =~ tr/-x/Ss/ if -u _;
  74.     substr($perms, 5, 1) =~ tr/-x/Ss/ if -g _;
  75.     substr($perms, 8, 1) =~ tr/-x/Tt/ if -k _;
  76.     if    (-f _) { $perms = '-' . $perms; }
  77.     elsif (-d _) { $perms = 'd' . $perms; }
  78.     elsif (-l _) { $perms = 'l' . $perms; $pname .= ' -> ' . readlink($_); }
  79.     elsif (-c _) { $perms = 'c' . $perms; $size = sizemm($rdev); }
  80.     elsif (-b _) { $perms = 'b' . $perms; $size = sizemm($rdev); }
  81.     elsif (-p _) { $perms = 'p' . $perms; }
  82.     elsif (-S _) { $perms = 's' . $perms; }
  83.     else         { $perms = '?' . $perms; }
  84.  
  85.     my $user = $user{$uid} || $uid;
  86.     my $group = $group{$gid} || $gid;
  87.  
  88.     my ($sec,$min,$hour,$mday,$mon,$timeyear) = localtime($mtime);
  89.     if (-M _ > 365.25 / 2) {
  90.         $timeyear += 1900;
  91.     } else {
  92.         $timeyear = sprintf("%02d:%02d", $hour, $min);
  93.     }
  94.  
  95.     printf "%5lu %4ld %-10s %3d %-8s %-8s %8s %s %2d %5s %s\n",
  96.             $ino,
  97.                  $blocks,
  98.                       $perms,
  99.                             $nlink,
  100.                                 $user,
  101.                                      $group,
  102.                                           $size,
  103.                                               $moname[$mon],
  104.                                                  $mday,
  105.                                                      $timeyear,
  106.                                                          $pname;
  107.     1;
  108. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

¿Que es enorme para lo que queremos? Pues sí, pero... si tenemos el fuente, ahora podemos modificarlo para nuestro problema en particular, que trata de sacar la fecha y nombre de los archivos.

Solo tenemos que modificar el último printf() de la función ls() para que saque los campos que nos interesan, y ya está. Y nos ahorramos el llamar a awk.

Seguimos con awk... ya hemos dicho que no tenemos que hacer nada porque modificando el printf() lo tenemos resuelto, pero en otras ocasiones sí que nos vemos obligado a usarlo.

Bueno, en Perl, todo lo que hace awk se puede imitar bastante bien. En nuestro caso, un comando como

awk '{print \$8 ":" \$9 ":" \$10 ":" \$11}'

lo podemos escribir como

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my @campos = split;
  2. print join(":", @campos[8..11]), "\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y nos ahorramos una llamada externa a awk, que siempre es algo muy costoso desde el punto de vista del ordenador.
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

Re: Problema con funcion qx()

Notapor magnobalt » 2012-06-29 06:50 @326

Gracias, explorer.

Voy a tener en cuenta la llamada al awk y optimizar el código.

Saludos
magnobalt
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2010-03-24 17:59 @791


Volver a Administración

¿Quién está conectado?

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

cron