package Watchdog; use strict; use warnings; use base 'Exporter'; our $VERSION = 0.01; our @EXPORT_OK = qw(sys sys_for_watchdog); use Storable; sub sys { my ( $cmd, $temp_out_fn ) = @_; my $output; $temp_out_fn = '.out' unless $temp_out_fn; open my $oldout, ">&STDOUT" or die "Can't dup STDOUT: $!"; open OLDERR, ">&", \*STDERR or die "Can't dup STDERR: $!"; open STDOUT, '>', $temp_out_fn or die "Can't redirect STDOUT to '$temp_out_fn': $! $@"; open STDERR, ">&STDOUT" or die "Can't dup STDOUT: $!"; select STDERR; $| = 1; # make unbuffered select STDOUT; $| = 1; # make unbuffered my $status = system($cmd); close STDOUT; close STDERR; open STDOUT, ">&", $oldout or die "Can't dup \$oldout: $!"; open STDERR, ">&OLDERR" or die "Can't dup OLDERR: $!"; unless ( open( FH_STDOUT, "<$temp_out_fn") ) { carp("File $temp_out_fn not open!"); unlink $temp_out_fn; next; } { local $/ = undef; $output = ; } close FH_STDOUT; return ( $status, $output ); } sub sys_for_watchdog { my ( $cmd, $log_fn, $timeout, $sleep ) = @_; die "cmd is mandatory" unless defined $cmd; $log_fn = $cmd . '.log' unless defined $log_fn; $timeout = 5*60 unless defined $timeout; my $ipc_fn = '../watchdog-setting.bin'; if ( -e $ipc_fn ) { print "found '$ipc_fn', probably already running\n"; # exit 0; } print "running '$cmd' ...\n"; my $info = { 'log_fn' => $log_fn, 'pid' => $$, 'cmd' => $cmd, 'timeout' => $timeout, }; $info->{'sleep'} = $sleep if defined $sleep; store( $info, $ipc_fn ) or die "store failed\n$!\n$@"; =head todo =pod sub catch_sig { my $signame = shift; print "captured $signame\n"; unlink $ipc_fn; exit; } foreach my $sig ( qw/QUIT KILL CHILD/ ) { $SIG{$sig} = \&catch_sig; } #print dump( \%SIG ); =cut my ( $status, $output ) = sys( $cmd, $log_fn ); unlink $ipc_fn; while ( -e $ipc_fn ) { print "trying to unlink $ipc_fn\n"; sleep 1; unlink $ipc_fn; } print ( ( $status ) ? "finished, but exit code is $status\n" : "finished ok\n" ); return ( $status, $output ); } 1;