Automatically execute a program when file is written

A 5 star hangout for overworked and underpaid system admins.
foxb
Posts: 1927
Joined: 2006/04/20 19:03:33
Location: Montreal/QC

Automatically execute a program when file is written

Post by foxb » 2011/06/07 13:53:31

Hello,

I have a program that writes files in the filesystem.

Is there a way to execute a program automatically after file is created in specific folder?

Thanks,

User avatar
WhatsHisName
Posts: 1549
Joined: 2005/12/19 20:21:43
Location: /earth/usa/nj

Automatically execute a program when file is written

Post by WhatsHisName » 2011/06/07 17:40:28

I would think the simplest way would be to poll through cron for the presence of the file or for files newer than the previous check and start the program as needed.

If you need faster than 1 min. increments, then you could create a simple daemon to perform a similar task at shorter intervals.

But at times like this, I tend to get out my copies of "Classic Shell Scripting" and "Bash Cookbook" from O'Reilly and start thumbing through the pages. :-)

There may be other perl/python options, too.

foxb
Posts: 1927
Joined: 2006/04/20 19:03:33
Location: Montreal/QC

Re: Automatically execute a program when file is written

Post by foxb » 2011/06/07 19:30:44

:-)

Thanks for suggestions...

I got those in mind(and they got rejected), but the issue is much more complex...

It is even preferred not to have the file written to the disk since it contains sensitive information.

Maybe some sort of FUSE filesystem...

The solution for now is cron job + encrypted filesystem, but I wanted to see if anyone found something else.

User avatar
WhatsHisName
Posts: 1549
Joined: 2005/12/19 20:21:43
Location: /earth/usa/nj

Re: Automatically execute a program when file is written

Post by WhatsHisName » 2011/06/07 19:56:09

Yes, that sounds like a job for [url=http://en.wikipedia.org/wiki/Tmpfs]tmpfs[/url].

Based on your "client requirements", the issue seems to be more about volatile storage than timeliness of execution, which makes it easier to address.

foxb
Posts: 1927
Joined: 2006/04/20 19:03:33
Location: Montreal/QC

Re: Automatically execute a program when file is written

Post by foxb » 2011/06/07 21:14:35

This might be another option.

Just not sure about the size of the files... but is it worth considering.

Thanks,

lavinius
Posts: 31
Joined: 2011/03/28 06:37:11
Location: Brisbane, Australia

Re: Automatically execute a program when file is written

Post by lavinius » 2011/06/24 01:42:57

I would use auditd to monitor that folder for file creation then swatch to monitor the auditd log and trigger an event when something comes up

its a two step process but very configurable

rossnick
Posts: 7
Joined: 2011/04/22 10:54:45

Re: Automatically execute a program when file is written

Post by rossnick » 2011/06/24 02:24:06

You can use the inotify mecanism that can be setup to monitor files or directory...

Search for incrond or incrontab, can't remember he exact name. I use it to execute a script whenever a file is created or moved to a specific directory...

lavinius
Posts: 31
Joined: 2011/03/28 06:37:11
Location: Brisbane, Australia

Re: Automatically execute a program when file is written

Post by lavinius » 2011/06/24 03:02:09

[code]
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/inotify.h>
int main( )
{
int length, i = 0;
int fd;
int wd;
char buffer[EVENT_BUF_LEN];
fd = inotify_init();
if ( fd < 0 ) {
perror( "inotify_init" );
}
wd = inotify_add_watch( fd, "/YOUR/DIRECTORY", IN_CREATE | IN_DELETE );
length = read( fd, buffer, EVENT_BUF_LEN );
if ( length < 0 ) {
perror( "read" );
}
while ( i < length ) { struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ]; if ( event->len ) {
if ( event->mask & IN_CREATE ) {
if ( event->mask & IN_ISDIR ) {
printf( "New directory %s created.\n", event->name );
}
else {
printf( "New file %s created.\n", event->name );
}
}
else if ( event->mask & IN_DELETE ) {
if ( event->mask & IN_ISDIR ) {
printf( "Directory %s deleted.\n", event->name );
}
else {
printf( "File %s deleted.\n", event->name );
}
}
}
i += EVENT_SIZE + event->len;
}
inotify_rm_watch( fd, wd );
}
[/code]
Change /YOUR/DIRECTORY to the directory you want to monitor. Instead of printf you can do whatever, you can probably remove the delete option too.

With inotify you really need to write your own code, with auditd and swatch you don't.

[Moderator edited to insert [i]code[/i] tags to preserve the formatting.]

vargasmas
Posts: 15
Joined: 2011/05/10 13:11:38
Location: Hanover, PA, USA
Contact:

Re: Automatically execute a program when file is written

Post by vargasmas » 2011/06/24 13:06:09

If you want an example written in BASH, I run this script from a cron to monitor a directory for changes and email me when there is one. It will detect if anyone creates a file or touches an existing file. Schedule the script to run every $MYFREQUENCY minutes. All it's really doing is executing a find command to look for files that have their access time changed in the last 5 minutes, and if it finds one, use mutt to send an email. I'm sure there's many better/quicker/sexier ways to do this...

[code]
#!/bin/bash
# Description: This script monitors $MYDIR (checking once every $MYFREQUENCY minutes) for
# files that have recently been created or modified, and if it finds one, it sends a logger
# message to LOGHOST, and/or an email to $MYEMAIL.

MYDIR=/dir/to/monitor
MYEMAIL='username@domain.com'
MYFREQUENCY='-5'
MESSAGEFILE="message.txt"
MYDATE=$(date +%y-%m-%d)
MYTIME=$(date +%H:%M)
MAILER=$(which mutt)
MYNAME=$(hostname)
MYSUBJECT="Data Changed in $MYDIR directory on host ${MYNAME}"

if [[ ! -f ${MAILER} ]] ; then
echo "Program \"mutt\" is required, but is not available on this host. Please install mutt package and try again."
exit 1
fi

FILECOUNT="$(find ${MYDIR} -mmin ${MYFREQUENCY} -type f | wc -l)"

if [ ${FILECOUNT} -gt 0 ]
then
echo "Directory ${MYDIR} on host ${MYNAME} has been modified:" >> /tmp/${MESSAGEFILE}
echo "Filename : Timestamp : Size in bytes" >> /tmp/${MESSAGEFILE}
find $MYDIR -mmin ${MYFREQUENCY} -type f -printf '%p : %Ac : %s bytes *** ' >> /tmp/${MESSAGEFILE}
logger -p local0.info "CHANGE DETECTED: $(cat /tmp/${MESSAGEFILE})"
cat /tmp/${MESSAGEFILE} | mutt -s "CHANGED DETECTED in host ${MYNAME}" -a /tmp/${MESSAGEFILE} ${MYEMAIL}
/bin/rm -f /tmp/${MESSAGEFILE}
fi

exit 0
[/code]

[Moderator edited to insert [i]code[/i] tags to preserve the formatting.]

lavinius
Posts: 31
Joined: 2011/03/28 06:37:11
Location: Brisbane, Australia

Re: Automatically execute a program when file is written

Post by lavinius » 2011/06/26 23:22:44

That's neat but it's not instant, as in you can run it every minute but yeah, to get instant notification you can't beat auditd + swatch or inotify.

Post Reply