#!/usr/bin/perl -wT # # syncfiles # # usage: in a rc.sysinit or inittab run as # syncfiles clienthost [delay] # Designed to automatically check every 'delay' seconds whether certain files have # been modified and if modifications have been made, then push them to the # requested client host over a ssh connection. This script runs as a daemon by default. # Requires: # 1) run as root for /etc/files, so you can access the shadow file # 2) rsync and ssh must be available # 3) ssh access without a password to the client (ie .ssh/authorised_keys2 on remote hosts) # # written by David Bussenschutt Oct 5 2001 - free for everyone - no responsibily accepted. # It could be made bigger and better, but I like the KISS principle. use strict; # for syntax checking use POSIX; # for 'setsid' # files to update, and the initial ctime to use my %files = ('/etc/passwd' => '0', '/etc/shadow' => '0', '/etc/group' => '0',); # where are the rsync and ssh commands? # rsync should also be in the same place on the remote hosts as on the primary host # the path to these is hardcoded because this script runs as root my $rsync = '/usr/bin/rsync'; my $ssh = '/usr/bin/ssh'; # client name should be provided on command line, if it's not, the script won't run. my $client = $ARGV[0]; # how often do we check for changes to the ctime of the files? # should be provided as second command line option, or default to 10 seconds. my $delay = $ARGV[1]||10; # error checking die "rsync not found\n" unless defined $rsync; die "remote host not defined on command line\n" unless defined $client; chomp $rsync; # dissassociate from terminal? my $DAEMON=1; #--------------------------------- # are we going to run as a daemon? my $pid; if ($DAEMON == 1){ # only INT, TERM and HUP are REALLY needed. $SIG{TERM}=$SIG{INT}=$SIG{HUP}=\&signal_handler; #ignore $SIG{PIPE} as it's dangerous $SIG{PIPE}='IGNORE'; # turn stdio output off print "Dissosociating from terminal and running as a daemon\n"; # virtualise / to be in a 'safe' location #chroot("/var") or die " Couldn't chroot to /var: $!"; # fork a child and let the parent exit. $pid=fork; exit if $pid; die "Couldn't fork new process: $!" unless defined ($pid); # dissociate the process from the terminal and don't be part of # my old process 'group' POSIX::setsid() or die "Can't start a new session: $!"; } sub signal_handler { die "dying on signal"; } #--------------------------------- while (1) { #print "sleeping\n"; sleep $delay; foreach my $file (keys %files){ #if ctime of file is > than ctime in $ctimes then # do push., # update ctime into %files my $newctime; if (defined ( $newctime = (stat($file))[10] ) and $newctime > $files{$file}) { #system ("$rsync -ae '$ssh -x' --rsync-path='$rsync' $file root\@$client:$file"); print "$rsync -ae '$ssh -x' --rsync-path='$rsync' $file root\@$client:$file\n"; $files{$file} = $newctime; } elsif (!defined $newctime or $newctime<=1) { # file that should exist does not exist or other error die "error getting ctime of $file\n"; } # else no update of this file needed. } }