2 # /\ \ From the mind of
4 # / /\ \ \_____ Lee Eakin <LEakin@Nostrum.COM>
5 # / \ \ \______\ or <Lee@Eakin.ORG>
7 # \ \ \ \____\/ / Wrapper module for the rsync program
8 # \ \ \/____ / rsync can be found at http://rsync.samba.org/rsync/
16 use IPC::Open3 qw(open3);
23 Rsync - perl module interface to B<rsync> http://rsync.samba.org/rsync/
29 $obj = Rsync->new(qw(-az C<-e> /usr/local/bin/ssh
30 --rsync-path /usr/local/bin/rsync));
32 $obj->exec(qw(localdir rhost:remdir))
33 or warn "rsync failed\n";
37 Perl Convenience wrapper for B<rsync> program. Written for B<rsync> 2.3.1 but
38 should perform properly with most versions.
42 # options from the rsync man pae
43 ###### Boolean flags ######
44 # -h, --help show this help screen
45 # -v, --verbose increase verbosity
46 # -q, --quiet decrease verbosity
47 # -c, --checksum always checksum
48 # -a, --archive archive mode
49 # -r, --recursive recurse into directories
50 # -R, --relative use relative path names
51 # -b, --backup make backups (default ~ suffix)
52 # -u, --update update only (don't overwrite newer files)
53 # -l, --links preserve soft links
54 # -L, --copy-links treat soft links like regular files
55 # --copy-unsafe-links copy links outside the source tree
56 # --safe-links ignore links outside the destination tree
57 # -H, --hard-links preserve hard links
58 # -p, --perms preserve permissions
59 # -o, --owner preserve owner (root only)
60 # -g, --group preserve group
61 # -D, --devices preserve devices (root only)
62 # -t, --times preserve times
63 # -S, --sparse handle sparse files efficiently
64 # -n, --dry-run show what would have been transferred
65 # -W, --whole-file copy whole files, no incremental checks
66 # -x, --one-file-system don't cross filesystem boundaries
67 # -C, --cvs-exclude auto ignore files in the same way CVS does
68 # RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS
69 # .make.state .nse_depinfo *~ #* .#* ,* *.old *.bak
70 # *.BAK *.orig *.rej .del-* *.a *.o *.obj *.so *.Z
72 # --delete delete files that don't exist on the sending side
73 # --delete-excluded also delete excluded files on the receiving side
74 # --partial keep partially transferred files
75 # --force force deletion of directories even if not empty
76 # --numeric-ids don't map uid/gid values by user/group name
77 # -I, --ignore-times don't exclude files that match length and time
78 # --size-only only use file size when determining if a file
79 # should be transferred
80 # -z, --compress compress file data
81 # --version print version number
82 # --daemon run as a rsync daemon
83 # --stats give some file transfer stats
84 # --progress show progress during transfer
85 ###### scalar values ######
86 # --csum-length=LENGTH <=16 bit md4 checksum size
87 # -B, --block-size=SIZE checksum blocking size (default 700)
88 # --timeout=TIME set IO timeout in seconds
89 # --port=PORT specify alternate rsyncd port number
90 # -e, --rsh=COMMAND specify rsh replacement
91 # -T, --temp-dir=DIR create temporary files in directory DIR
92 # --compare-dest=DIR also compare destination files relative to DIR
93 # --exclude-from=FILE exclude patterns listed in FILE
94 # --include-from=FILE don't exclude patterns listed in FILE
95 # --config=FILE specify alternate rsyncd.conf file
96 # --password-file=FILE get password from FILE
97 # --log-format=FORMAT log file transfers using specified format
98 # --suffix=SUFFIX override backup suffix
99 # --rsync-path=PATH specify path to rsync on the remote machine
100 ###### array values ######
101 # --exclude=PATTERN exclude files matching PATTERN
102 # --include=PATTERN don't exclude files matching PATTERN
117 $obj = Rsync->new(@options);
121 Create an Rsync object. Any options passed at creation are stored in
122 the object as defaults for all future exec call on that object. Options
123 are the same as those in L<rsync> with the addition of
124 --path-to-rsync which can be used to override the hardcoded default of
125 /usr/local/bin/rsync, and --debug which causes the module functions to
126 print some debugging information to STDERR.
133 # seed the options hash, booleans, scalars, excludes, data,
134 # status, stderr/stdout storage for last exec
136 # the full path name to the rsync binary
137 'path-to-rsync' => '/usr/local/bin/rsync',
138 # these are the boolean flags to rsync, all default off, including them
139 # in the args list turns them on
141 --archive 0 --backup 0 --checksum 0
142 --compress 0 --copy-links 0 --copy-unsafe-links 0
143 --cvs-exclude 0 --daemon 0 --delete 0
144 --delete-excluded 0 --devices 0 --dry-run 0
145 --force 0 --group 0 --hard-links 0
146 --help 0 --ignore-times 0 --links 0
147 --numeric-ids 0 --one-file-system 0 --owner 0
148 --partial 0 --perms 0 --progress 0
149 --quiet 0 --recursive 0 --relative 0
150 --safe-links 0 --size-only 0 --sparse 0
151 --stats 0 --times 0 --update 0
152 --verbose 0 --version 0 --whole-file 0
154 # these have simple scalar args we cannot easily check
156 --block-size 0 --compare-dest 0 --config 0
157 --csum-length 0 --exclude-from 0 --include-from 0
158 --log-format 0 --password-file 0 --port 0
159 --rsh 0 --rsync-path 0 --suffix 0
160 --temp-dir 0 --timeout 0
162 # these can be specified multiple times and are additive, the doc also
163 # specifies that it is an ordered list so we must preserve that order
165 # source/destination path names and hostnames
167 # return status from last exec
170 # whether or not to print debug statements
172 # stderr from last exec in array format (messages from remote rsync proc)
174 # stdout from last exec in array format (messages from local rsync proc)
178 &defopts($self,@_) or return undef;
187 defopts $obj @options;
191 $obj->defopts(@options);
195 Set default options for future exec calls for the object. See L<rsync>
196 for a complete list of valid options. This is really the internal
197 function that B<new> calls but you can use it too. Presently there is no way
198 to turn off the boolean options short of creating another object, but if it is
199 needed and the B<rsync> guys don't use it, I may add hooks to let + and ++ or a
200 leading no- toggle it back off similar to B<Getopt::Long> (the GNU way).
208 # need a conversion table in case someone uses the short options
210 -B --block-size -C --cvs-exclude -D --devices -H --hard-links
211 -I --ignore-times -L --copy-links -R --relative -T --temp-dir
212 -W --whole-file -a --archive -b --backup -c --checksum
213 -e --rsh -g --group -h --help -l --links
214 -n --dry-run -o --owner -p --perms -q --quiet
215 -r --recursive -s --sparse -t --times -u --update
216 -v --verbose -x --one-file-system -z --compress
218 while (my $opt=shift @opts) {
220 print(STDERR "setting debug flag\n"),$self->{debug}=1,next
221 if $opt eq '--debug';
222 print STDERR "processing option: $opt\n" if $self->{debug};
224 # handle short opts first
225 if ($opt=~/^-(\w+)$/) {
226 foreach (split '',$1) {
227 print STDERR "short option: -$_\n" if $self->{debug};
228 if (exists $short{'-'.$_}) {
230 # convert it to the long form
231 $opt=$short{$opt} if exists $short{$opt};
232 # handle the 3 short opts that require args
233 $self->{scalar}{$opt}=shift(@opts),next if (/^[BeT]$/);
235 $self->{flag}{$opt}=1,next if exists $self->{flag}{$opt};
237 carp "$opt - unknown option\n";
241 # handle long opts with = args
242 if ($opt=~/^(--\w+[\w-]*)=(.*)$/) {
243 print STDERR "splitting longopt: $opt ($1 $2)\n" if $self->{debug};
246 # handle boolean flags
247 $self->{flag}{$opt}=1,next if exists $self->{flag}{$opt};
248 # handle simple scalars
249 $self->{scalar}{$opt}=($arg || shift @opts),next
250 if exists $self->{scalar}{$opt};
252 if ($opt eq '--exclude') {
254 # if they sent a reset, we will too
255 $self->{exclude}=[],next if $arg eq '!';
256 # otherwise add it to the list
257 push @{$self->{exclude}},$arg;
260 # to preserve order we store both includes and excludes in the same
261 # array. We use the leading '+ ' (plus space) trick from the man
262 # page to accomplish this.
263 if ($opt eq '--include') {
265 # first check to see if this is really an exclude
266 push(@{$self->{exclude}},$arg),next if $arg=~s/^- //;
267 # next see if they sent a reset, if they did, we will too
268 $self->{exclude}=[],next if $arg eq '!';
269 # if it really is an include, fix it first, since we use exclude
270 $arg='+ '.$arg unless $arg=~/^\+ /;
271 push @{$self->{exclude}},$arg;
274 # handle our special case to override hard-coded path to rsync
275 $self->{'path-to-rsync'}=($arg || shift @opts),next
276 if $opt eq '--path-to-rsync';
277 # if we get this far nothing matched so it must be an error
278 carp "$opt - unknown option\n";
280 } else { # must be data (source/destination info)
281 print STDERR "adding to data array: $opt\n" if $self->{debug};
282 push(@{$self->{data}},$opt);
292 exec $obj @options or warn "rsync failed\n";
296 $obj->exec(@options) or warn "rsync failed\n";
300 This is the function that does the real work. Any options passed to this
301 routine are appended to any pre-set options and are not saved. They effect
302 the current execution of B<rsync> only. It returns 1 if the return status was
303 zero (or true), if the B<rsync> return status was non-zero it returns undef and
304 stores the return status. You can examine the return status from rsync and
305 any output to stdout and stderr with the functions listed below.
311 my @cmd=($self->{'path-to-rsync'});
313 foreach (sort keys %{$self->{flag}}) {
314 push @cmd,$_ if $self->{flag}{$_};
316 foreach (sort keys %{$self->{scalar}}) {
317 push @cmd,$_.'='.$self->{scalar}{$_} if $self->{scalar}{$_};
319 foreach (@{$self->{exclude}}) {
320 push @cmd,'--exclude='.$_;
322 foreach (@{$self->{data}}) {
326 print STDERR "exec: @cmd\n" if $self->{debug};
327 my $in=FileHandle->new; my $out=FileHandle->new; my $err=FileHandle->new;
328 my $pid=eval{ open3 $in,$out,$err,@cmd };
330 $self->{realstatus}=0;
332 $self->{err}=[$@,"Execution of rsync failed.\n"];
335 $in->close; # we don't use it and neither should rsync (at least not yet)
336 $self->{err}=[ $err->getlines ];
337 $self->{out}=[ $out->getlines ];
341 $self->{realstatus}=$?;
342 $self->{status}=$?>>8;
343 return undef if $self->{status};
355 $rval = $obj->status;
359 Returns the status from last B<exec> call right shifted 8 bits.
365 return $self->{status};
370 =item Rsync::realstatus
372 $rval = realstatus $obj;
376 $rval = $obj->realstatus;
380 Returns the real status from last B<exec> call (not right shifted).
386 return $self->{realstatus};
401 Returns an array or a reference to the array containing all output to stderr
402 from the last B<exec> call. B<rsync> sends all messages from the remote
403 B<rsync> process to stderr. This functions purpose is to make it easier for
404 you to parse that output for appropriate information.
410 return(wantarray ? @{$self->{err}} : $self->{err});
425 Similar to the B<err> function, this returns an array or a reference to the
426 array containing all output to stdout from the last B<exec> call. B<rsync>
427 sends all messages from the local B<rsync> process to stdout.
433 return(wantarray ? @{$self->{out}} : $self->{out});
438 Lee Eakin E<lt>leakin@nostrum.comE<gt>
442 Gerard Hickey C<PGP::Pipe>
444 Russ Allbery C<PGP::Sign>
446 Graham Barr C<Net::*>
448 Andrew Tridgell and Paul Mackerras C<rsync(1)>
450 John Steele E<lt>steele@nostrum.comE<gt>
452 Philip Kizer E<lt>pckizer@nostrum.comE<gt>
454 Larry Wall C<perl(1)>
456 I borrowed many clues on wrapping an external program from the PGP modules,
457 and I would not have had such a useful tool to wrap except for the great work
458 of the B<rsync> authors. Thanks also to Graham Barr, the author of the libnet
459 modules and many others, for looking over this code. Of course I must mention
460 the other half of my brain, John Steele, and his good friend Philip Kizer for
461 finding B<rsync> and bringing it to my attention. And I would not have been
462 able to enjoy writing useful tools if not for the creator of the B<perl>
467 Copyleft (l) 1999, by Lee Eakin