2009-10-07 30 views
9

He estado buscando y desbordando un poco y no he podido encontrar nada utilizable.Monitorear la carpeta para nuevos archivos usando unix ksh shell script o perl script y desencadenar script perl

Necesito una secuencia de comandos que supervisa una carpeta pública y se desencadena en la creación de archivos nuevos y luego mueve los archivos a una ubicación privada.

Tengo una carpeta compartida de samba /exam/ple/ en Unix mapeada a X:\ en windows. En ciertas acciones, los archivos txt se escriben en el recurso compartido. Quiero secuestrar cualquier archivo de texto que aparezca en la carpeta y colocarlo en una carpeta privada /pri/vate en Unix. Después de mover ese archivo, quiero activar un script de Perl por separado.

EDITAR A la espera de ver un script de shell, si alguien tiene alguna idea ... algo que va a monitorear para los nuevos archivos y luego ejecutar algo como:

#!/bin/ksh 
mv -f /exam/ple/*.txt /pri/vate 
+1

¿necesita hacerlo programáticamente o puede hacer uso de las instalaciones existentes? esto es para lo que se hizo cron. –

+0

puede cron ser activado por un nuevo archivo? – CheeseConQueso

+0

tampoco quiero que cron ejecute el segundo script una y otra vez ... solo quiero que el segundo script se ejecute después de que un nuevo archivo se transfirió con éxito a la carpeta privada – CheeseConQueso

Respuesta

9

Comprobar incron. Parece hacer exactamente lo que necesitas.

+0

esto se ve bastante decente ... lástima que pueda 't install it: < – CheeseConQueso

+0

Un gran ejemplo de hello world type de incron: http://www.errr-online.com/2011/02/25/monitor-a-directory-or-file-for-changes-on- linux-using-inotify/ – mdaddy

+0

¿Se puede instalar incron en Windows? –

6

Si entiendo bien, ¿quieres algo como esto?

#!/usr/bin/perl 

use strict; 
use warnings; 

use File::Copy 

my $poll_cycle = 5; 
my $dest_dir = "/pri/vate"; 

while (1) { 
    sleep $poll_cycle; 

    my $dirname = '/exam/ple'; 

    opendir my $dh, $dirname 
     or die "Can't open directory '$dirname' for reading: $!"; 

    my @files = readdir $dh; 
    closedir $dh; 

    if (grep(!/^[.][.]?$/, @files) > 0) { 
     print "Dir is not empty\n"; 

     foreach my $target (@files) { 
      # Move file 
      move("$dirname/$target", "$dest_dir/$target"); 

      # Trigger external Perl script 
      system('./my_script.pl'); 
    } 
} 
+0

lo pruebo ... ¿esto funciona infinitamente? también, estoy buscando solo archivos de texto, pero la bomba grep es genial tener – CheeseConQueso

+1

@CheeseConQueso: Sí, es un ciclo while infinito, sondeo a la frecuencia que usted especifique. No probé rigurosamente el código, pero la idea es bastante simple. –

+0

@ CheeConQueso: obviamente puede modificar el 'grep' para ignorar archivos con un sufijo particular si esa es su situación. –

1

Esto dará lugar a una buena cantidad de io - stat() llama y similares. Si desea una rápida notificación sin la sobrecarga de tiempo de ejecución (pero esfuerzo más adelantado), echar un vistazo a la FAM/dnotify: link text o link text

0
#!/bin/ksh 
while true 
do 
    for file in `ls /exam/ple/*.txt` 
    do 
      # mv -f /exam/ple/*.txt /pri/vate 
      # changed to 
      mv -f $file /pri/vate 

    done 
    sleep 30 
done 
+0

aquí hay una manera de hacer una búsqueda cada 30 segundos en el shell korn que encontré en línea ... no es activado por un nuevo archivo, es más un proceso de tipo cron ... todavía no puedo encontrar un script de shell korn que se ejecute con la presencia de un nuevo archivo – CheeseConQueso

+0

@ Cheese, es un ejemplo un poco torpe, si hay dos archivos en/examen/ple en una sola iteración, entonces el cuerpo se ejecutará dos veces, pero ambos archivos serán mv'ed la primera vez. Entonces verás errores en la segunda llamada de mv. ¿Son necesarios esos backticks? –

+0

@Martin - buen punto ... Lo encontré en línea y no lo probé, así que no estoy seguro de si son necesarios los backticks. Acabo de ponerlo aquí porque era un enfoque de shell. También es torpe en que cron puede hacer lo mismo – CheeseConQueso

2
$ python autocmd.py /exam/ple .txt,.html /pri/vate some_script.pl 

Ventajas:

  • más fácil de instalar que incron debido a pyinotify es puro Python
  • orientada a eventos - menos impacto que the perl script

autocmd.py:

#!/usr/bin/env python 
"""autocmd.py 

Adopted from autocompile.py [1] example. 

[1] http://git.dbzteam.org/pyinotify/tree/examples/autocompile.py 

Dependencies: 

Linux, Python, pyinotify 
""" 
import os, shutil, subprocess, sys 

import pyinotify 
from pyinotify import log 

class Handler(pyinotify.ProcessEvent): 
    def my_init(self, **kwargs): 
     self.__dict__.update(kwargs) 

    def process_IN_CLOSE_WRITE(self, event): 
     # file was closed, ready to move it 
     if event.dir or os.path.splitext(event.name)[1] not in self.extensions: 
      # directory or file with uninteresting extension 
      return # do nothing 

     try: 
      log.debug('==> moving %s' % event.name) 
      shutil.move(event.pathname, os.path.join(self.destdir, event.name)) 
      cmd = self.cmd + [event.name] 
      log.debug("==> calling %s in %s" % (cmd, self.destdir)) 
      subprocess.call(cmd, cwd=self.destdir) 
     except (IOError, OSError, shutil.Error), e: 
      log.error(e) 

    def process_default(self, event): 
     pass 


def mainloop(path, handler): 
    wm = pyinotify.WatchManager() 
    notifier = pyinotify.Notifier(wm, default_proc_fun=handler) 
    wm.add_watch(path, pyinotify.ALL_EVENTS, rec=True, auto_add=True) 
    log.debug('==> Start monitoring %s (type c^c to exit)' % path) 
    notifier.loop() 


if __name__ == '__main__': 
    if len(sys.argv) < 5: 
     print >> sys.stderr, "USAGE: %s dir ext[,ext].. destdir cmd [args].." % (
      os.path.basename(sys.argv[0]),) 
     sys.exit(2) 

    path = sys.argv[1] # dir to monitor 
    extensions = set(sys.argv[2].split(',')) 
    destdir = sys.argv[3] 
    cmd = sys.argv[4:] 

    log.setLevel(10) # verbose 

    # Blocks monitoring 
    mainloop(path, Handler(path=path, destdir=destdir, cmd=cmd, 
          extensions=extensions)) 
+0

esto se ve picante ... No tengo Python, pero por lo que dices sobre que la notificación es nativa, podría tener que instalarla y probarla ... .gracias – CheeseConQueso

+0

CheeseConQueso: si la subclase http://search.cpan.org/~drolsky/File-ChangeNotify-0.07/lib/File/ChangeNotify/Watcher/Inotify.pm está disponible entonces File :: ChangeNotify mencionado por @jsoversion puede hacer lo mismo que pyinotify. La búsqueda rápida de CPAN reveló otra posible solución http://search.cpan.org/~mlehmann/Linux-Inotify2-1.21/Inotify2.pm – jfs

+0

gracias ... lo comprobaré – CheeseConQueso

1

No consumo ksh pero aquí es como lo hago con sh. Estoy seguro de que se adapta fácilmente a ksh.

#!/bin/sh 
trap 'rm .newer' 0 
touch .newer 
while true; do 
    (($(find /exam/ple -maxdepth 1 -newer .newer -type f -name '*.txt' -print \ 
     -exec mv {} /pri/vate \; | wc -l))) && found-some.pl & 
    touch .newer 
    sleep 10 
done 
+0

gracias, intentaré convertir la sintaxis y Pruébalo – CheeseConQueso

3

Llego tarde a la fiesta, lo sé, pero en interés de la integridad y de proporcionar información a los futuros visitantes;

#!/bin/ksh 
# Check a File path for any new files 
# And execute another script if any are found 

POLLPATH="/path/to/files" 
FILENAME="*.txt" # Or can be a proper filename without wildcards 
ACTION="executeScript.sh argument1 argument2" 
LOCKFILE=`basename $0`.lock 

# Make sure we're not running multiple instances of this script 
if [ -e /tmp/$LOCKFILE ] ; then 
    exit 0 
else 
    touch /tmp/$LOCKFILE 
fi 

# check the dir for the presence of our file 
# if it's there, do something, if not exit 

if [ -e $POLLPATH/$FILENAME ] ; then 
    exec $ACTION 
else 
    rm /tmp/$LOCKFILE 
    exit 0 
fi 

Run it from cron;

*/1 7-22/1 * * * /path/to/poll-script.sh >/dev/null 2>&1

Lo que quiere utilizar el fichero de bloqueo en el script posterior ($ ACCIÓN), y luego limpiarlo en la salida, sólo por lo que no tiene ningún proceso de apilado.

Cuestiones relacionadas