2009-10-07 4 views
9

J'ai été googling et débordement pour un peu et ne pouvait rien trouver utilisable.Moniteur dossier pour les nouveaux fichiers en utilisant un script ksh Unix ou un script Perl et le déclencheur Perl script

J'ai besoin d'un script qui surveille un dossier public et qui se déclenche lors de la création d'un nouveau fichier, puis déplace les fichiers vers un emplacement privé.

J'ai un dossier partagé samba /exam/ple/ sur unix mappé à X:\ sur Windows. Sur certaines actions, les fichiers txt sont écrits sur le partage. Je veux enlever tout fichier txt qui apparaît dans le dossier et le placer dans un dossier privé /pri/vate sur unix. Une fois ce fichier déplacé, je veux déclencher un script Perl distinct.

EDIT Toujours en attente pour voir un script shell si quelqu'un a des idées ... quelque chose qui va suivre pour les nouveaux fichiers et lancer quelque chose comme:

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

avez-vous besoin de le faire par programmation ou pouvez-vous utiliser les installations existantes? c'est pour ça que cron a été fait. –

+0

peut être déclenché par un nouveau fichier? – CheeseConQueso

+0

Je ne veux pas non plus que cron exécute le deuxième script encore et encore ... Je veux seulement que le deuxième script fonctionne après qu'un nouveau fichier a été transféré avec succès dans le dossier privé – CheeseConQueso

Répondre

9

Vérifier incron. Il semble faire exactement ce dont vous avez besoin.

+0

cela semble assez décent ... dommage que je peux ne l'installez pas: < – CheeseConQueso

+0

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

+0

Peut-on installer incron sur Windows? –

6

Si je comprends bien, vous voulez juste quelque chose comme ça? File :: ChangeNotify vous permet de surveiller les fichiers et les répertoires pour y apporter des modifications.

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

ill tester it .... cela fonctionne infiniment im deviner? aussi, je ne cherche que des fichiers texte, mais la bombe grep est cool d'avoir – CheeseConQueso

+1

@CheeseConQueso: Oui, c'est une boucle infinie, interrogeant à la fréquence que vous spécifiez. Je n'ai pas rigoureusement testé le code, mais l'idée est assez simple. –

+0

@CheeseConQueso: Vous pouvez évidemment modifier le 'grep' pour ignorer les fichiers avec un suffixe particulier si c'est votre situation. –

1

Cela se traduira par un peu juste de io - stat() appelle et autres. Si vous voulez une notification rapide sans les frais généraux d'exécution (mais l'effort plus d'avance), jetez un oeil à FAM/dnotify: link text ou 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

voici un moyen de faire une recherche toutes les 30 secondes dans korn shell que j'ai trouvé en ligne .... il n'est pas déclenché par un nouveau fichier, son plus d'un processus de type cron .... je ne peux toujours pas trouver un script shell korn qui fonctionne sur la présence d'un nouveau fichier – CheeseConQueso

+0

@Cheese, c'est un peu un exemple maladroit - s'il y a deux fichiers Dans le cas/exam/ple sur une seule itération, le corps sera exécuté deux fois, mais les deux fichiers seront passés en premier. Donc, vous verrez des erreurs dans le deuxième appel de mv. Ces backticks sont-ils nécessaires? –

+0

@Martin - bon point ... Je l'ai trouvé en ligne et je ne l'ai pas testé, donc je ne sais pas si les backticks sont nécessaires. Je l'ai juste mis ici parce que c'était une approche coquille. Il est aussi maladroit que cron puisse faire la même chose – CheeseConQueso

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

Avantages:

  • plus facile à installer que incron en raison de pyinotify est pur Python
  • événementiel - moins d'impact 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

cela semble épicé .... Je n'ai pas de python, mais d'après ce que vous dites à propos de l'avis d'être natif, je pourrais avoir à l'installer et l'essayer .. merci – CheeseConQueso

+0

CheeseConQueso: si http://search.cpan.org/~drolsky/File-ChangeNotify-0.07/lib/File/ChangeNotify/Watcher/Inotify.pm sous-classe est disponible alors File :: ChangeNotify mentionné par @jsoversion peut faire le même que pyinotify. Recherche rapide CPAN a révélé encore une autre solution possible http://search.cpan.org/~mlehmann/Linux-Inotify2-1.21/Inotify2.pm – jfs

+0

merci ... je vais vérifier – CheeseConQueso

1

Je n'utilise pas ksh mais voici comment je le fais avec sh. Je suis sûr que c'est facilement adapté à 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

merci, mal essayer de convertir la syntaxe et Essaye le – CheeseConQueso

3

Je suis en retard à la fête, je sais, mais dans l'intérêt de l'exhaustivité et de fournir des informations aux futurs visiteurs;

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

Exécutez-le à partir de cron;

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

Vous voudriez utiliser le lockfile dans votre script suivant (ACTION $), puis le nettoyer à la sortie, juste pour que vous n'avez pas des processus d'empilement.

Questions connexes