2009-10-07 10 views
9

Sono stato googling e traboccante per un po 'e non ho trovato nulla di utile.Monitorare la cartella per i nuovi file utilizzando lo script di shell kix o script perl e trigger perl

Ho bisogno di uno script che monitora una cartella pubblica e attiva la nuova creazione di file e quindi sposta i file in una posizione privata.

Ho una cartella condivisa di samba /exam/ple/ su unix mappata a X:\ su Windows. Su determinate azioni, i file txt vengono scritti nella condivisione. Voglio sequestrare qualsiasi file txt che appare nella cartella e metterlo in una cartella privata /pri/vate su unix. Dopo che il file è stato spostato, voglio attivare uno script perl separato.

EDIT Ancora in attesa di vedere uno script di shell, se qualcuno ha qualche idea ... qualcosa che controllerà per i nuovi file e quindi eseguire qualcosa di simile a:

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

hai bisogno di farlo a livello di programmazione o puoi fare uso di strutture esistenti? questo è ciò per cui cron è stato creato. –

+0

può cron essere attivato dal nuovo file? – CheeseConQueso

+0

anche io non voglio che cron esegua il secondo script più e più volte ... voglio solo che il secondo script venga eseguito dopo che un nuovo file è stato trasferito correttamente nella cartella privata – CheeseConQueso

risposta

9

Controllare incron. Sembra fare esattamente quello che ti serve.

+0

questo sembra abbastanza decente ... peccato che io possa installarlo: < – CheeseConQueso

+0

Un esempio di buon esempio di incron world: http://www.errr-online.com/2011/02/25/monitor-a-directory-or-file-for-changes-on- linux-using-inotify/ – mdaddy

+0

È possibile installare incron su Windows? –

6

Se ho capito bene, vuoi solo qualcosa di simile?

#!/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

mal provarlo .... questo funziona all'infinito? inoltre, sto solo cercando i file di testo, ma la bomba grep è fredda per avere – CheeseConQueso

+1

@CheeseConQueso: Sì, è un ciclo infinito mentre esegue il polling alla frequenza specificata. Non ho rigorosamente testato il codice, ma l'idea è abbastanza semplice. –

+0

@CheeseConQueso: puoi ovviamente modificare 'grep' per ignorare i file con un suffisso particolare, se questa è la tua situazione. –

1

Questo si tradurrà in un bel po 'di io - stat() chiama e simili. Se si desidera che la notifica rapida senza il sovraccarico di esecuzione (ma lo sforzo di più in anticipo), dare un'occhiata a 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

qui è un modo per fare una ricerca ogni 30 secondi in korn shell che ho trovato online .... non è innescato da un nuovo file, è più un processo di tipo cron .... Non riesco ancora a trovare uno script di shell korn che funzioni sulla presenza di un nuovo file – CheeseConQueso

+0

@Cheese, è un esempio un po 'goffo - se ci sono due file in/exam/ple su una singola iterazione, il corpo for verrà eseguito due volte, ma entrambi i file verranno riprodotti per la prima volta. Quindi vedrai errori nella seconda chiamata di mv. Sono necessari quei backtick? –

+0

@ Martin - buon punto ... L'ho trovato online e non l'ho verificato, quindi non sono sicuro che siano necessari i backtick. L'ho messo qui perché era un approccio a shell. E 'anche goffo che cron possa fare la stessa cosa – CheeseConQueso

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

Vantaggi:

  • facile da installare rispetto incron a causa di pyinotify è puro Python
  • event-driven - meno impatto di 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

questo sembra piccante .... Non ho Python, ma da quello che stai dicendo sulla notifica di essere nativo, potrei doverlo installare e provarlo .. grazie – CheeseConQueso

+0

CheeseConQueso: se è disponibile la sottoclasse http://search.cpan.org/~drolsky/File-ChangeNotify-0.07/lib/File/ChangeNotify/Watcher/Inotify.pm, allora File :: ChangeNotify menzionato da @jsoversion può fare lo stesso di pyinotify. La ricerca CPAN rapida ha rivelato un'altra possibile soluzione http://search.cpan.org/~mlehmann/Linux-Inotify2-1.21/Inotify2.pm – jfs

+0

grazie ... lo verificherò – CheeseConQueso

1

Io non uso ksh, ma ecco come lo faccio con sh. Sono sicuro che si adatta facilmente 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

grazie, tenterò di convertire la sintassi e Provalo – CheeseConQueso

3

Sono in ritardo alla festa, lo so, ma nell'interesse della completezza e fornendo informazioni ai futuri visitatori;

#!/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 

Eseguire da cron;

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

Che ci si vuole utilizzare il file di lock nella successiva sceneggiatura ($ ACTION), e poi ripulirlo in uscita, solo così non si dispone di alcun processo di accatastamento.

Problemi correlati