diff options
Diffstat (limited to 'scripts/watch_a_file.perl')
-rwxr-xr-x | scripts/watch_a_file.perl | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/scripts/watch_a_file.perl b/scripts/watch_a_file.perl new file mode 100755 index 0000000..c1cd782 --- /dev/null +++ b/scripts/watch_a_file.perl @@ -0,0 +1,94 @@ +#!/usr/local/bin/perl +# +# watch_a_file.perl -- use lsof -F output to watch a specific file +# (or file system) +# +# usage: watch_a_file.perl file_name + +## Interrupt handler + +sub interrupt { wait; print "\n"; exit 0; } + + +## Start main program + +$Pn = "watch_a_file"; +# Check file argument. + +if ($#ARGV != 0) { print "$#ARGV\n"; die "$Pn usage: file_name\n"; } +$fnm = $ARGV[0]; +if (! -r $fnm) { die "$Pn: can't read $fnm\n"; } + +# Do setup. + +$RPT = 15; # lsof repeat time +$| = 1; # unbuffer output +$SIG{'INT'} = 'interrupt'; # catch interrupt + +# Set path to lsof. + +if (($LSOF = &isexec("../lsof")) eq "") { # Try .. first + if (($LSOF = &isexec("lsof")) eq "") { # Then try . and $PATH + print "can't execute $LSOF\n"; exit 1 + } +} + +# Read lsof -nPF output from a pipe and gather the PIDs of the processes +# and file descriptors to watch. + +open(P, "$LSOF -nPFpf $fnm|") || die "$Pn: can't pipe to $LSOF\n"; + +$curpid = -1; +$pids = ""; +while (<P>) { + chop; + if (/^p(.*)/) { $curpid = $1; next; } # Identify process. + if (/^f/) { + if ($curpid > 0) { + if ($pids eq "") { $pids = $curpid; } + else { $pids = $pids . "," . $curpid; } + $curpid = -1; + } + } +} +close(P); +wait; +if ($pids eq "") { die "$Pn: no processes using $fnm located.\n"; } +print "watch_file: $fnm being used by processes:\n\t$pids\n\n"; + +# Read repeated lsof output from a pipe and display. + +$pipe = "$LSOF -ap $pids -r $RPT $fnm"; +open(P, "$pipe|") || die "$Pn: can't pipe: $pipe\n"; + +while (<P>) { print $_; } +close(P); +print "$Pn: unexpected EOF from \"$pipe\"\n"; +exit 1; + + +## isexec($path) -- is $path executable +# +# $path = absolute or relative path to file to test for executabiity. +# Paths that begin with neither '/' nor '.' that arent't found as +# simple references are also tested with the path prefixes of the +# PATH environment variable. + +sub +isexec { + my ($path) = @_; + my ($i, @P, $PATH); + + $path =~ s/^\s+|\s+$//g; + if ($path eq "") { return(""); } + if (($path =~ m#^[\/\.]#)) { + if (-x $path) { return($path); } + return(""); + } + $PATH = $ENV{PATH}; + @P = split(":", $PATH); + for ($i = 0; $i <= $#P; $i++) { + if (-x "$P[$i]/$path") { return("$P[$i]/$path"); } + } + return(""); +} |