Perl Inotify Script Help

Hi all,

I have a perl script using Inotify2 to watch a directory. I have it almost working the way I want it in that it sends an e-mail notification when a file is modified in the directory. This is an sftp directory for incoming files. When a large file is received, the watch will call a sub routine to perform actions (along with sending an e-mail) that the file is modified. However, since the file is being sent via sftp, it is constantly being modified during the send, causing the user to receive multiple e-mails.

Is there any way to set a timeout after it has noticed that a file is being modified? Is this the way to go, or should I try something else?

Can’t you call *sleep *from Perl? (not being a Perl programmer myself).

If I use sleep, will it suspend the process? This would not be desired in case any other files are arriving during the nap time ;).

I was thinking of this, but wanted to steer away from this because of my comment above.

Yes, it will (see man sleep).

You didn’t mention you did look into sleep allready. I can also not study your script nor your design, so I can not decide if this sleep (of mabe a few seconds) influences things negative. Just wanted to point you to its existance.

Hi
Aside from Henk’s comments I’ve used http://kodu.neti.ee/~risto/sec/ in
the past for these sorts of activities.


Cheers Malcolm °¿° (Linux Counter #276890)
SUSE Linux Enterprise Desktop 11 (x86_64) Kernel 2.6.27.29-0.1-default
up 2 days 19:54, 2 users, load average: 0.16, 0.29, 0.42
GPU GeForce 8600 GTS Silent - CUDA Driver Version: 190.18

I have posted my script below for any comments:

#!/usr/bin/perl

use Linux::Inotify2;

close STDIN;
close STDOUT;
close STDERR;

sub perform_actions;

$dir_base = “/srv/sftp/sftpuser/incoming/”;
my @directories = qw(dir1 dir2);

#create new object
my $inotify = new Linux::Inotify2 or die “unable to create new inotify obejct: $!”;

foreach my $directory (@directories)
{
#add watchers
#print "Adding watch for " . $dir_base.$directory;
$inotify->watch($dir_base.$directory, IN_CREATE | IN_MODIFY, sub { my $event = shift;

my $name = $event->fullname;

if($event->IN_CREATE)
{
perform_actions($name, $dir_base.$directory, “created”);
}
elsif($event->IN_MODIFY)
{
perform_actions($name, $dir_base.$directory, “modified”);
}

#print "$name was accessed
" if $event->IN_ACCESS;
#print "events for $name have been lost
" if $event->IN_Q_OVERFLOW;

$event->w->cancel;

}) or die “watch creation failed: $!”;
}

1 while $inotify->poll;

sub perform_actions {
my ($name, $dir, $action) = @_;

#DO MULTIPLE ACTIONS HERE. NOT RELEVANT FOR POST

e-mail notification if the size is > 0

my $date = date;
my $cmd = qq(echo “The $name file has been $action on machine” | mailx -s “A new file has been received on $date” user_to_email);
system($cmd) if -s $name;
}
}

It seems to me that your SFTP daemon is the appropriate place to trigger the notification action. Are their options to the daemon that would allow for this?

I can look into options to the daemon. I am using scponlyc as a shell for the sftp user and I think this automatically calls the sftp-server program as it chroots.

Anybody have experience with this?