i've made some modifications to your code to make it a bit safer, and to capture more output:
== your initial code didn't check for a valid set of commands, so someone could have run malicious code and sent you an email after the fact. i created a set of valid commands to prevent this
== i added error checking all around, including creation of mail object, io handles, etc.
== i seperated the output to STDERR and STDOUT into different streams, for better reporting
== i captured the exit code and process id, just to be complete
== i sent output to the screen as well as in an email.
see below.
#!/usr/local/bin/perl -w
use strict;
$|++;
use constant EMAIL => 'you@yourdomain.com';
use constant SERVER => 'mail.yourdomain.com';
use IO::Handle;
use IPC::Open3;
use Net::SMTP;
use Mail::Mailer;
# create list of valid commands (put your commands in here!)
# stop malicious usage!!!
my $valid_commands = "(backup_nt|backup_unix|backup_linux)";
my $n = "\n";
# get command from command line, display usage if error
my $cmd = shift
|| die("usage: $0 $valid_commands [opts]\n");
# verify command is valid
die "invalid command: $cmd"
unless($cmd =~ /$valid_commands/);
my $cmdopts = join ' ', @ARGV;
my $mail = Net::SMTP->new( SERVER )
|| die("cannot create mail server! $!");
$mail->to( EMAIL );
$mail->mail( 'root@yourdomain.com' );
$mail->data();
my (@output, $test, $pid, $exitcode);
# create local io handles, fail if open fails
my $OUTPUT = new IO::Handle; # create handle for STDOUT
my $OUTERR = new IO::Handle; # create handle for STDERR
my $IN = new IO::Handle; # create handle for STDIN
open( $OUTPUT, ">&STDOUT" ) or # duplicate STDOUT
die "Can't dup STDOUT to OUTPUT: $!$n";
open( $OUTERR, ">&STDERR" ) or # duplicate STDERR
die "Can't dup STDERR to OUTERR: $!$n";
open( $IN, "<&STDIN" ) or # duplicate STDIN
die "Can't dup STDIN to IN: $!$n";
$test = eval # execute $cmd, redirecting to new
+handles,
{ # and capture the process id
$pid = open3($IN, $OUTPUT, $OUTERR, "$cmd $cmdopts") or die($!);
my $junk = waitpid(-1,0); # don't care about return val
};
$exitcode = $? >>8; # $? is exitcode of $s ( from waitp
+id() )
# format output for mailing
push @output, " -> Result:" . $n;
push @output, $_ while(<$OUTPUT>);
push @output, " -> Errors:" . $n;
push @output, $_ while(<$OUTERR>);
push @output, " -> Exit Code: " . $exitcode . $n;
push @output, " -> Process ID: " . $pid . $n;
close $OUTPUT; # close OUTPUT handle
close $OUTERR; # close OUTERR handle
close $IN; # close IN handle
# send error if eval failed, otherwise send output
if ($@) {
$mail->datasend("command '$cmd $cmdopts' could not be executed: $@
+\n");
print "command '$cmd $cmdopts' could not be executed: $@\n";
} else {
$mail->datasend(
" -> Command: $cmd $cmdopts" , $n,
join('', @output), $n,
);
print(
" -> Command: $cmd $cmdopts" , $n,
join('', @output), $n,
);
}
$mail->datasend;
$mail->quit;
exit 0;
~Particle
|