#!/usr/bin/perl -w # ------------- HEADER --------------# #------------------------------------# # Replicacao ZFS Filesystems 1.0 # # # # --ChangeLog-- # # Author: Leal # # Version: 1.0 # # Date: 03/set/2008 # #------------------------------------# # perl's configs use POSIX; use Fcntl qw(:DEFAULT :flock); use Getopt::Std; # procedures.. sub log_print { my($now) = strftime "%Y%m%d-%H%M%S", localtime; my($texto) = @_; $ERROR = 0; print STDERR "${LOG_PROGNAME}[$$] $now: @_\n"; if (($texto =~ /START - Replica/) || ($texto =~ /END - Replica/)) { $ERROR = system "$ECMD \"${LOG_PROGNAME}[$$] $now: @_\" >> /var/log/backup/zfs-replicate.$DATE.log 2>&1"; if ($ERROR) { printf "->could not write to the zfs-replicate log - ERROR code: $ERROR"; } } } sub log_die { &log_print; cleanup(); die("\n"); # was: exit 1; # die is catchable in an "eval". } sub open_log { my($logfile) = @_; $LOGPIPE = 0; if (-t STDOUT) { # guess interactive shell.. if (open(LOGPIPE, "| tee -a $logfile") && open(STDOUT, ">&LOGPIPE")) { $LOGPIPE = 1; } } unless ($LOGPIPE) { open(STDOUT, ">> $logfile") or log_die "$MESSAGE_FILE $logfile: $!"; } open(STDERR, ">&STDOUT") or log_die "Could not DUP stdout -> stderr: $!"; } sub lock { my($pidfile) = @_; sysopen PIDFILE, $pidfile, O_WRONLY | O_CREAT or log_die "$MESSAGE_FILE $pidfile: $!"; flock PIDFILE, LOCK_EX | LOCK_NB or log_die "$MESSAGE_LOCK pidfile: $pidfile: $!"; truncate PIDFILE, 0; syswrite PIDFILE, "$$\n"; } sub usage() { printf "We must receive informations...\n"; # printf "Something like: -M -R -H -N ...\n"; printf "Something like: -M -R -H ...\n"; die("\n"); } sub run_command { my($command, $args) = @_; $ERROR = 0; log_print "running: $command $args"; $ERROR = system "$command $args >> /var/log/backup/zfs-replicate.$DATE.log 2>&1"; if ($ERROR) { log_die "->command execution error: $command $args - ERROR code: $ERROR"; } else { log_print "command executed OK"; } } sub cleanup { unlink("$DIR_CONTROL/$LOG_PROGNAME.pid"); if ($LOGPIPE) { close STDOUT; close STDERR; close LOGPIPE; } } # some variables.. $REQUIRED_UID = "0"; $MESSAGE_FILE = "Could not open file"; $MESSAGE_LOCK = "Could not aquire exclusive lock"; $MESSAGE_DIR = "Could not access diretory"; $DIR_LOGS = "/var/log/backup"; $DIR_CONTROL = "/var/backup/run"; # commands, and options... $ECMD = "/usr/bin/echo"; $RCMD = "/usr/local/bin/zfs-replicate"; $ROPT1 = "-Fv"; $ZCMD = "/usr/sbin/zfs"; $ZOPT = "list -Ht filesystem -o name"; # THE GAME... # better than nothing... if ($REQUIRED_UID != $>) { printf "You must be root to run this program.."; die("\n"); } # Date and time for logging... $DATE = strftime("%Y%m%d", localtime); # User interaction... %options=(); $options = getopts('M:R:H:N:', \%options); usage() unless ($options{M} && $options{R}); if ($options{H}) { $ROPT2 = "-r"; } # Who we are? $LOG_PROGNAME = "replica" . "-" . "$options{M}"; # initializing logging... unless (-d $DIR_LOGS) { printf "$MESSAGE_DIR: \"$DIR_LOGS/\""; die("\n");} open_log("$DIR_LOGS/$LOG_PROGNAME.$DATE.log"); unless (-d $DIR_CONTROL) { printf "$MESSAGE_DIR: \"$DIR_CONTROL/\""; die("\n");} lock("$DIR_CONTROL/$LOG_PROGNAME.pid"); log_print "START - Replica - v1.0"; @TEXTO = `$ZCMD $ZOPT`; foreach $FS (@TEXTO) { chomp($FS); if ($FS =~ /^$options{M}\//){ if ($options{H}) { run_command ("$RCMD $ROPT1 $ROPT2 $options{H} $FS", "$options{R}"); } else { run_command ("$RCMD $ROPT1 $FS", "$options{R}"); } } } log_print "END - Replica - v1.0"; cleanup(); exit 0;