Last active
August 10, 2022 15:15
-
-
Save dexterbt1/3770410673480402ab0e34e312bd9343 to your computer and use it in GitHub Desktop.
tail -f file with strftime filename path pattern + watch for new files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -T | |
use strict; | |
use POSIX qw/strftime/; | |
my $DEBUG = defined($ENV{TAILFTS_DEBUG}) ? $ENV{TAILFTS_DEBUG} : 1; | |
my $LOGGER = sub { $DEBUG && print STDERR strftime("%Y-%m-%dT%H:%M:%S ", localtime(time())), @_; }; | |
my $parent = $$; | |
my $USAGE = "USAGE: $0 <path/to/filename_pattern>\n"; | |
my ($fname_pattern_raw) = @ARGV; | |
## quick and dirty taint checks | |
## -- | |
$ENV{'PATH'} = '/bin:/usr/bin'; | |
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; | |
$fname_pattern_raw =~ /^([\/\.\w\%\\]+)$/g; | |
my $fname_pattern = $1; | |
my $fname; | |
if (length $fname_pattern <= 0) { | |
die $USAGE; | |
} | |
my $reset = 0; | |
my $tail_pid; | |
my $reset_check = sub { | |
my $fname_now = strftime($fname_pattern, localtime(time())); | |
if ($fname_now ne $fname) { | |
$fname = $fname_now; | |
$reset++; | |
kill 9, "-$tail_pid"; | |
die "doreset\n"; | |
} | |
alarm 1; | |
}; | |
local $SIG{ALRM} = $reset_check; | |
local $SIG{INT} = sub { kill 9, "-$tail_pid"; exit 2; }; | |
local $SIG{CHLD} = 'IGNORE'; | |
while (1) { | |
$fname = strftime($fname_pattern, localtime(time())); | |
if (($reset<=0) && !(-f $fname)) { | |
die "ERROR: file not found: $fname\n"; | |
} | |
$LOGGER->("$$: about to tail $fname\n"); | |
eval { | |
my $lines = "10"; | |
if ($reset <= 0) { | |
# first try | |
alarm 1; # prime mover | |
} | |
else { | |
# succeeding | |
$lines = "+1"; | |
} | |
$tail_pid = fork(); | |
if ($tail_pid == 0) { | |
# forked child | |
setpgrp(0, 0); | |
my $warned_wait = 0; | |
while (1) { | |
my $fname_now = strftime($fname_pattern, localtime(time())); | |
if ($fname_now ne $fname) { | |
$LOGGER->("$$: child-of($parent): time reset detected, giving up waiting for $fname ...\n"); | |
exit 1; | |
} | |
if (-f $fname) { | |
last; | |
} | |
if (!$warned_wait) { | |
$LOGGER->("$$: child-of($parent): waiting for missing file: $fname ...\n"); | |
$warned_wait = 1; | |
} | |
sleep 1; | |
} | |
if ($warned_wait) { | |
$LOGGER->("$$: child-of($parent): detected new file: $fname, starting tail\n"); | |
} | |
exec("tail -n $lines -f $fname") | |
or die $!; | |
} | |
elsif (!defined $tail_pid) { | |
die "ERROR: fork error\n"; | |
} | |
while (wait() != -1) {} | |
}; | |
if ($@) { | |
die unless $@ eq "doreset\n"; # propagate unexpected errors | |
# did reset! | |
$LOGGER->("$$: resetting based on time change\n"); | |
alarm 1; # prime mover | |
} | |
} | |
__END__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment