2009-10-07 77 views
9

我一直在谷歌搜索和溢出了一下,找不到任何可用的東西。使用unix ksh shell腳本或perl腳本監控新文件夾並觸發perl腳本

我需要一個腳本來監視公用文件夾並觸發新文件的創建,然後將這些文件移動到一個私有位置。

我有一個桑巴共享文件夾/exam/ple/在UNIX上映射到X:\在Windows上。在某些操作中,txt文件被寫入共享。我想綁架出現在該文件夾中的任何txt文件,並將其放入unix上的私人文件夾/pri/vate。在移動該文件後,我想觸發一個單獨的perl腳本。

編輯 仍觀望shell腳本,如果任何人有任何想法...的東西,將監測的新文件,然後運行是這樣的:

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

您是否需要通過編程的方式來完成它,還是可以利用現有的設施?這是cron的目標。 – 2009-10-07 20:19:43

+0

可以通過新文件觸發cron嗎? – CheeseConQueso 2009-10-07 20:21:40

+0

我也不希望cron反覆運行第二個腳本...我只希望第二個腳本在新文件成功轉移到私人文件夾後運行 – CheeseConQueso 2009-10-07 20:27:18

回答

9

檢查incron。它似乎正是你所需要的。

+0

這看起來相當不錯...我可以安裝它:< – CheeseConQueso 2009-10-08 19:25:48

+0

incron的一個很棒的hello world類型示例:http://www.errr-online.com/2011/02/25/monitor-a-directory-or-file-for-changes-on- linux-using-inotify/ – mdaddy 2012-01-04 03:01:59

+0

可以在Windows上安裝incron嗎? – 2013-09-26 19:05:19

6

如果我理解正確,你只是想要這樣的事情?

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

虐待它測試....這運行無限im猜測?另外,即時通訊只尋找文本文件,但grep炸彈很酷,有 – CheeseConQueso 2009-10-07 20:41:14

+1

@ CheeseConQueso:是的,這是一個無限的循環,按您指定的頻率進行輪詢。我沒有嚴格測試代碼,但這個想法很簡單。 – 2009-10-07 20:45:25

+0

@CheeseConQueso:如果這是你的情況,你顯然可以修改'grep'來忽略帶有特定後綴的文件。 – 2009-10-07 20:46:17

1

這將導致IO公平一點 - STAT()調用等。如果您想在不運行時開銷(但更多的前期工作)迅速通知,看一看FAM/dnotify:link textlink 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

小時這裏是一種方法來做一個搜索每30秒鐘korn shell,我在網上找到....它不是由觸發一個新的文件,它更多的是一個cron類型的過程....我仍然無法找到一個運行在新文件存在的korn shell腳本 – CheeseConQueso 2009-10-08 15:02:24

+0

@Cheese,這是一個笨重的例子 - 如果有兩個文件在一次迭代中,對於身體將運行兩次,但是這兩個文件將首次被mv'ed。所以你會在第二次調用MV時看到錯誤。這些反引號是否需要? – 2009-10-11 20:53:45

+0

@Martin - 好點...我在網上找到它,並沒有對它進行測試,所以我不確定是否需要反引號。我只是把它放在這裏,因爲它是一個shell方法。這也是笨重的,因爲cron可以做同樣的事情 – CheeseConQueso 2009-10-12 12:55:08

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

優點:

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

這看起來很辛辣....我沒有python,但是從你所說的關於通知是原生的,我可能不得不安裝它並嘗試一下。 。謝謝 – CheeseConQueso 2009-10-08 19:57:34

+0

CheeseConQueso:如果http://search.cpan.org/~drolsky/File-ChangeNotify-0.07/lib/File/ChangeNotify/Watcher/Inotify.pm子類可用,那麼@jsoversion提到的File :: ChangeNotify可以做與pyinotify相同。快速CPAN搜索揭示了另一種可能的解決方案http://search.cpan.org/~mlehmann/Linux-Inotify2-1.21/Inotify2.pm – jfs 2009-10-08 20:36:37

+0

謝謝...我將檢查出 – CheeseConQueso 2009-10-08 20:44:01

1

我不使用ksh的,但這裏是我如何與SH做到這一點。我確定它很容易適應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

謝謝,虐待嘗試轉換語法和試試看 – CheeseConQueso 2011-01-21 16:08:25

3

我遲到了,我知道,但爲了完整性和爲未來的遊客提供信息;

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

從cron運行它;

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

你想使用鎖文件在隨後的腳本($ ACTION),然後清理退出,只是讓你沒有任何堆放過程。