message and cleans up correctly.
* Rsync with whitespace and wildcard excludes fixed by replacing
argList with argList+ in config.pl.
* Fixed typo in bin/BackupPC_restore (XferLOG -> RestoreLOG).
* (Re)-fixed "Bad command" in log file when restore via tar or zip
file download is done.
* Added untaint to exec in Lib.pm to avoid tainted errors.
* Applied additional tweak to hilight patch from Tim Demarest.
* $Conf{CgiAdminUsers} = '*' now allows privileged even with REMOTE_USER
not set.
* Don't display RsyncdPasswd when displaying config.pl files.
* Replace pipe with socketpair in bin/BackupPC_dump and bin/BackupPC_restore,
which increases typical buffering from 4K to 16K-64K. This improves the
performance.
* Add check on $ENV{LANG} setting do configure.pl: if LANG includes utf
then a warning is printed.
# Version __VERSION__, __RELEASEDATE__
#------------------------------------------------------------------------
+* Several improvements to restore: cancel now reports the correct
+ message and cleans up correctly.
+
+* Rsync with whitespace and wildcard excludes fixed by replacing
+ argList with argList+ in config.pl.
+
+* Fixed typo in bin/BackupPC_restore (XferLOG -> RestoreLOG).
+
+* (Re)-fixed "Bad command" in log file when restore via tar or zip
+ file download is done.
+
+* Added untaint to exec in Lib.pm to avoid tainted errors.
+
+* Applied additional tweak to hilight patch from Tim Demarest.
+
+* $Conf{CgiAdminUsers} = '*' now allows privileged even with REMOTE_USER
+ not set.
+
+* Don't display RsyncdPasswd when displaying config.pl files.
+
+* Replace pipe with socketpair in bin/BackupPC_dump and bin/BackupPC_restore,
+ which increases typical buffering from 4K to 16K-64K. This improves the
+ performance.
+
+* Add check on $ENV{LANG} setting do configure.pl: if LANG includes utf
+ then a warning is printed.
+
+#------------------------------------------------------------------------
+# Version 2.0.0beta2, 11 May 2003
+#------------------------------------------------------------------------
+
* Added German translation, provided by Manfred Herrmann.
* Fixed large-file problem with rsync, reported by Manfred Herrmann.
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
$NextWakeup = 0;
} elsif ( $SigName ) {
print(LOG $bpc->timeStamp, "Got signal $SigName... cleaning up\n");
- foreach my $host ( keys(%Jobs) ) {
- kill(2, $Jobs{$host}{pid});
- }
+ if ( keys(%Jobs) ) {
+ foreach my $host ( keys(%Jobs) ) {
+ kill(2, $Jobs{$host}{pid});
+ }
+ sleep(1);
+ foreach my $host ( keys(%Jobs) ) {
+ kill(9, $Jobs{$host}{pid});
+ }
+ %Jobs = ();
+ }
StatusWrite();
unlink("$TopDir/log/BackupPC.pid");
exit(1);
delete($Status{$host}{errorTime});
$Status{$host}{endTime} = time;
} elsif ( $mesg =~ /^nothing to do/ ) {
- $Status{$host}{state} = "Status_idle";
- $Status{$host}{reason} = "Reason_nothing_to_do";
- $Status{$host}{startTime} = time;
+ if ( $Status{$host}{reason} ne "Reason_backup_failed"
+ && $Status{$host}{reason} ne "Reason_restore_failed" ) {
+ $Status{$host}{state} = "Status_idle";
+ $Status{$host}{reason} = "Reason_nothing_to_do";
+ $Status{$host}{startTime} = time;
+ }
$Status{$host}{dhcpCheckCnt}--
if ( $Status{$host}{dhcpCheckCnt} > 0 );
} elsif ( $mesg =~ /^no ping response/
$Status{$host}{error} = $1;
$Status{$host}{errorTime} = time;
$Status{$host}{endTime} = time;
- print(LOG $bpc->timeStamp, "backup failed on $host ($1)\n");
+ print(LOG $bpc->timeStamp, "Backup failed on $host ($1)\n");
+ } elsif ( $mesg =~ /^restore failed: (.*)/ ) {
+ $Status{$host}{state} = "Status_idle";
+ $Status{$host}{reason} = "Reason_restore_failed";
+ $Status{$host}{error} = $1;
+ $Status{$host}{errorTime} = time;
+ $Status{$host}{endTime} = time;
+ print(LOG $bpc->timeStamp, "Restore failed on $host ($1)\n");
} elsif ( $mesg =~ /^log\s+(.*)/ ) {
print(LOG $bpc->timeStamp, "$1\n");
} elsif ( $mesg =~ /^BackupPC_stats = (.*)/ ) {
if ( $CmdJob ne $host && defined($Status{$host})
&& defined($Jobs{$host}) ) {
print(LOG $bpc->timeStamp,
- "Stopping current backup of $host,"
+ "Stopping current $Jobs{$host}{type} of $host,"
. " request by $user (backoff=$backoff)\n");
kill(2, $Jobs{$host}{pid});
#
##close($Jobs{$host}{fh});
##delete($Jobs{$host});
- $Status{$host}{state} = "Status_idle";
- $Status{$host}{reason} = "Reason_backup_canceled_by_user";
+ $Status{$host}{state} = "Status_idle";
+ if ( $Jobs{$host}{type} eq "restore" ) {
+ $Status{$host}{reason}
+ = "Reason_restore_canceled_by_user";
+ } else {
+ $Status{$host}{reason}
+ = "Reason_backup_canceled_by_user";
+ }
$Status{$host}{activeJob} = 0;
$Status{$host}{startTime} = time;
- $reply = "ok: backup of $host cancelled";
+ $reply = "ok: $Jobs{$host}{type} of $host cancelled";
} elsif ( $BgQueueOn{$host} || $UserQueueOn{$host} ) {
print(LOG $bpc->timeStamp,
"Stopping pending backup of $host,"
print(LOG "Fatal error: unhandled signal $SigName\n");
unlink("$TopDir/log/BackupPC.pid");
confess("Got new signal $SigName... quitting\n");
+ } else {
+ $SigName = shift;
}
- $SigName = shift;
}
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
use BackupPC::Xfer::Smb;
use BackupPC::Xfer::Tar;
use BackupPC::Xfer::Rsync;
+use Socket;
use File::Path;
use Getopt::Std;
$Hosts = $bpc->HostInfoRead($client);
}
if ( !defined($Hosts->{$client}) ) {
- print("Exiting because host $client does not exist in the hosts file\n");
+ print("Exiting because host $client does not exist in the hosts file\n")
+ if ( $opts{v} );
exit(1)
}
# This xfer method outputs a tar format file, so we start a
# BackupPC_tarExtract to extract the data.
#
- # Create a pipe to connect the Xfer method to BackupPC_tarExtract
+ # Create a socketpair to connect the Xfer method to BackupPC_tarExtract
# WH is the write handle for writing, provided to the transport
- # program, and RH is the other end of the pipe for reading,
+ # program, and RH is the other end of the socket for reading,
# provided to BackupPC_tarExtract.
#
- pipe(RH, WH);
+ if ( socketpair(RH, WH, AF_UNIX, SOCK_STREAM, PF_UNSPEC) ) {
+ shutdown(RH, 1); # no writing to this socket
+ shutdown(WH, 0); # no reading from this socket
+ setsockopt(RH, SOL_SOCKET, SO_RCVBUF, 8 * 65536);
+ setsockopt(WH, SOL_SOCKET, SO_SNDBUF, 8 * 65536);
+ } else {
+ #
+ # Default to pipe() if socketpair() doesn't work.
+ #
+ pipe(RH, WH);
+ }
#
# fork a child for BackupPC_tarExtract. TAR is a file handle
# the transfer.
#
if ( my $errMsg = CorrectHostCheck($hostIP, $host) ) {
- $stat{hostError} = $errMsg;
+ $stat{hostError} = $errMsg if ( $stat{hostError} eq "" );
last SCAN;
}
}
my $fileExt = $Conf{CompressLevel} > 0 ? ".z" : "";
#
- # Ignore signals in children
+ # Children quit quietly on ALRM
+ #
+ exit(1) if ( $Pid != $$ && $signame eq "ALRM" );
+
+ #
+ # Ignore other signals in children
#
return if ( $Pid != $$ );
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
use BackupPC::Xfer::Smb;
use BackupPC::Xfer::Tar;
use BackupPC::Xfer::Rsync;
+use Socket;
use File::Path;
use Getopt::Std;
$SIG{INT} = \&catch_signal;
$SIG{ALRM} = \&catch_signal;
$SIG{TERM} = \&catch_signal;
+$SIG{PIPE} = \&catch_signal;
+$SIG{STOP} = \&catch_signal;
+$SIG{TSTP} = \&catch_signal;
+$SIG{TTIN} = \&catch_signal;
+my $Pid = $$;
mkpath($Dir, 0, 0777) if ( !-d $Dir );
if ( !-f "$Dir/LOCK" ) {
if ( $useTar ) {
#
- # Create a pipe to connect BackupPC_tarCreate to the transport program
- # (smbclient, tar, etc).
+ # Create a socketpair to connect BackupPC_tarCreate to the transport
+ # program (smbclient, tar, etc).
# WH is the write handle for writing, provided to BackupPC_tarCreate
# and RH is the other end of the pipe for reading provided to the
# transport program.
#
- pipe(RH, WH);
+ if ( socketpair(RH, WH, AF_UNIX, SOCK_STREAM, PF_UNSPEC) ) {
+ shutdown(RH, 1); # no writing to this socket
+ shutdown(WH, 0); # no reading from this socket
+ setsockopt(RH, SOL_SOCKET, SO_RCVBUF, 8 * 65536);
+ setsockopt(WH, SOL_SOCKET, SO_SNDBUF, 8 * 65536);
+ } else {
+ #
+ # Default to pipe() if socketpair() doesn't work.
+ #
+ pipe(RH, WH);
+ }
}
#
{
my $signame = shift;
+ #
+ # Children quit quietly on ALRM
+ #
+ exit(1) if ( $Pid != $$ && $signame eq "ALRM" );
+
+ #
+ # Ignore signals in children
+ #
+ return if ( $Pid != $$ );
+
#
# Note: needs to be tested for each kind of XferMethod
#
print(LOG $bpc->timeStamp, "cleaning up after signal $signame\n");
- if ( @xferPid ) {
- kill(2, @xferPid);
- sleep(1);
- kill(9, @xferPid);
- }
- if ( $tarPid > 0 ) {
- kill(2, $tarPid);
- sleep(1);
- kill(9, $tarPid);
- }
+ $SIG{$signame} = 'IGNORE';
+ $RestoreLOG->write(\"exiting after signal $signame\n");
$stat{xferOK} = 0;
- $stat{hostError} = "aborted by signal $signame";
+ if ( $signame eq "INT" ) {
+ $stat{hostError} = "aborted by user (signal=$signame)";
+ } else {
+ $stat{hostError} = "aborted by signal=$signame";
+ }
+ exit(RestoreCleanup($client));
}
#
#
UserCommandRun("RestorePostUserCmd") if ( $NeedPostCmd );
- $RestoreLOG->close() if ( defined($RestoreLOG) );
rename("$Dir/RestoreLOG$fileExt", "$Dir/RestoreLOG.$lastNum$fileExt");
rename("$Dir/$reqFileName", "$Dir/RestoreInfo.$lastNum");
my $endTime = time();
if ( $stat{hostAbort} && $stat{hostError} eq "" ) {
$stat{hostError} = "lost network connection during restore";
}
+ $RestoreLOG->write(\"Restore failed: $stat{hostError}\n")
+ if ( defined($RestoreLOG) );
}
+ $RestoreLOG->close() if ( defined($RestoreLOG) );
+
#
# Add the new restore information to the restore file
#
$bpc->RestoreInfoWrite($client, @Restores);
if ( !$stat{xferOK} ) {
- print(LOG $bpc->timeStamp, "Restore aborted ($stat{hostError})\n");
+ print(LOG $bpc->timeStamp, "Restore failed ($stat{hostError})\n");
print("restore failed: $stat{hostError}\n");
return 1;
} else {
my @pids = @xferPid;
push(@pids, $tarPid) if ( $tarPid > 0 );
my $str = join(",", @pids);
- $XferLOG->write(\"Xfer PIDs are now $str\n") if ( defined($XferLOG) );
+ $RestoreLOG->write(\"Xfer PIDs are now $str\n") if ( defined($RestoreLOG) );
print("xferPids $str\n");
}
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 11 May 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
$incrTot += $incrCnt;
$fullSize = sprintf("%.2f", $fullSize / 1000);
$incrAge = " " if ( $incrAge eq "" );
- $reasonHilite = $Conf{CgiStatusHilightColor}{$Status{$host}{reason}};
+ $reasonHilite = $Conf{CgiStatusHilightColor}{$Status{$host}{reason}}
+ || $Conf{CgiStatusHilightColor}{$Status{$host}{state}};
$reasonHilite = " bgcolor=\"$reasonHilite\"" if ( $reasonHilite ne "" );
if ( $Status{$host}{state} ne "Status_backup_in_progress"
&& $Status{$host}{state} ne "Status_restore_in_progress"
# remove any passwords and user names
s/(SmbSharePasswd.*=.*['"]).*(['"])/$1$2/ig;
s/(SmbShareUserName.*=.*['"]).*(['"])/$1$2/ig;
+ s/(RsyncdPasswd.*=.*['"]).*(['"])/$1$2/ig;
s/(ServerMesgSecret.*=.*['"]).*(['"])/$1$2/ig;
print ${EscHTML($_)};
}
if ( @fileListTrim > 10 ) {
@fileListTrim = (@fileListTrim[0..9], '...');
}
- $bpc->ServerMesg(eval("qq{$Lang->{log_User__User_downloaded_tar_archive_for__host}}"));
+ $bpc->ServerMesg("log User $User downloaded tar archive for $host,"
+ . " backup $num; files were: "
+ . join(", ", @fileListTrim));
my @pathOpts;
if ( $In{relative} ) {
if ( @fileListTrim > 10 ) {
@fileListTrim = (@fileListTrim[0..9], '...');
}
- $bpc->ServerMesg(eval("qq{$Lang->{log_User__User_downloaded_zip_archive_for__host}}"));
+ $bpc->ServerMesg("log User $User downloaded zip archive for $host,"
+ . " backup $num; files were: "
+ . join(", ", @fileListTrim));
my @pathOpts;
if ( $In{relative} ) {
}
foreach my $host ( sort(keys(%Status)) ) {
next if ( $Status{$host}{reason} ne "Reason_backup_failed"
+ && $Status{$host}{reason} ne "Reason_restore_failed"
&& (!$Status{$host}{userReq}
|| $Status{$host}{reason} ne "Reason_no_ping") );
my $startTime = timeStamp2($Status{$host}{startTime});
my($host) = @_;
my $Privileged = 0;
- return 0 if ( $User eq "" || ($host ne "" && !defined($Hosts->{$host})) );
+ return 0 if ( $User eq "" && $Conf{CgiAdminUsers} ne "*"
+ || $host ne "" && !defined($Hosts->{$host}) );
if ( $Conf{CgiAdminUserGroup} ne "" ) {
my($n,$p,$gid,$mem) = getgrnam($Conf{CgiAdminUserGroup});
$Privileged ||= ($mem =~ /\b$User\b/);
}
NavSectionTitle($Lang->{Hosts});
if ( defined($Hosts) && %$Hosts > 0 ) {
- NavSectionStart(0);
+ NavSectionStart(1);
foreach my $host ( GetUserHosts() ) {
NavLink("?host=${EscURI($host)}", $host);
}
{
my($padding) = @_;
- $padding = 2 if ( !defined($padding) );
+ $padding = 1 if ( !defined($padding) );
print <<EOF;
<table cellpadding="$padding" cellspacing="0" border="0" width="100%">
EOF
$Conf{SmbShareUserName} = '';
#
-# Smbclient share password. This is passed to smbclient via the PASSWD
+# Smbclient share password. This is passed to smbclient via its PASSWD
# environment variable. There are several ways you can tell BackupPC
# the smb share password. In each case you should be very careful about
# security. If you put the password here, make sure that this file is
# time taken for the backup, plus the granularity of $Conf{WakeupSchedule}
# will make the actual backup interval a bit longer.
#
+# There are two special values for $Conf{FullPeriod}:
+#
+# -1 Don't do any regular backups on this machine. Manually
+# requested backups (via the CGI interface) will still occur.
+#
+# -2 Don't do any backups on this machine. Manually requested
+# backups (via the CGI interface) will be ignored.
+#
+# These special settings are useful for a client that is no longer
+# being backed up (eg: a retired machine), but you wish to keep the
+# last backups available for browsing or restoring to other machines.
+#
+# Also, you might create a virtual client (by setting $Conf{ClientNameAlias})
+# for restoring to a DVD or permanent media and you would set
+# $Conf{FullPeriod} to -2 so that it is never backed up.
+#
$Conf{FullPeriod} = 6.97;
#
# $Conf{BackupFilesExclude} = {
# 'c' => ['/temp', '/winnt/tmp'], # these are for 'c' share
# 'd' => ['/junk', '/dont_back_this_up'], # these are for 'd' share
-# }
+# };
#
$Conf{BackupFilesExclude} = undef;
#
# This setting only matters if $Conf{XferMethod} = 'rsync'.
#
-$Conf{RsyncClientCmd} = '$sshPath -l root $host $rsyncPath $argList';
+$Conf{RsyncClientCmd} = '$sshPath -l root $host $rsyncPath $argList+';
#
# Full command to run rsync for restore on the client. The following
#
# This setting only matters if $Conf{XferMethod} = 'rsync'.
#
-$Conf{RsyncClientRestoreCmd} = '$sshPath -l root $host $rsyncPath $argList';
+$Conf{RsyncClientRestoreCmd} = '$sshPath -l root $host $rsyncPath $argList+';
#
# Share name to backup. For $Conf{XferMethod} = "rsync" this should
#
# NmbLookup command. Given a netbios name, finds that host by doing
-# a NetBios multicast. Several variables are substituted at run-time:
+# a NetBios lookup. Several variables are substituted at run-time:
#
# $nmbLookupPath path to nmblookup ($Conf{NmbLookupPath})
# $host NetBios name
#
# $Conf{NmbLookupFindHostCmd} = '$nmbLookupPath -B 192.168.1.255 $host';
#
+# If you use a WINS server and your machines don't respond to
+# multicast NetBios requests you can use this (replace 1.2.3.4
+# with the IP address of your WINS server):
+#
+# $Conf{NmbLookupFindHostCmd} = '$nmbLookupPath -R -U 1.2.3.4 $host';
+#
+# This is preferred over multicast since it minimizes network traffic.
+#
+# Experiment manually for your site to see what form of nmblookup command
+# works.
+#
$Conf{NmbLookupFindHostCmd} = '$nmbLookupPath $host';
#
Reason_backup_failed => '#ffcccc',
Reason_backup_done => '#ccffcc',
Reason_no_ping => '#ffff99',
- Reason_backup_in_progress => '#66cc99',
Reason_backup_canceled_by_user => '#ff9900',
+ Status_backup_in_progress => '#66cc99',
};
#
Enjoy!
EOF
+if ( $ENV{LANG} =~ /utf/i && $^V ge v5.8.0 ) {
+ print <<EOF;
+
+WARNING: Your LANG environment variable is set to $ENV{LANG}, which
+doesn't behave well with this version of perl. Please set the
+LANG environment variable to en_US before running BackupPC.
+
+On RH-8 this setting is in the file /etc/sysconfig/i18n, or you
+could set it in BackupPC's init.d script.
+EOF
+}
+
+exit(0);
+
###########################################################################
# Subroutines
###########################################################################
=item *
The http/cgi user interface has internationalization (i18n) support,
-currently providing English, French and Spanish.
+currently providing English, French, German and Spanish.
=item *
=item *
Perl version 5.6.0 or later. BackupPC has been tested with
-version 5.6.0 and 5.6.1. If you don't have perl, please see
-L<http://www.cpan.org>.
+version 5.6.0, 5.6.1 and 5.8.0. If you don't have perl, please
+see L<http://www.cpan.org>.
=item *
1.13.7 at a minimum, with version 1.13.20 or higher recommended. Use
"tar --version" to check your version. Various GNU mirrors have the newest
versions of tar, see for example L<http://www.funet.fi/pub/gnu/alpha/gnu/tar>.
-As of February 2003 the latest version is 1.13.25.
+As of June 2003 the latest version is 1.13.25.
=item *
For BackupPC to use Rsync you will also need to install the perl
File::RsyncP module, which is available from
-L<http://perlrsync.sourceforge.net>. Version 0.31 or later is required.
+L<http://perlrsync.sourceforge.net>. Version 0.41 or later is required.
=item *
To use rsync and rsyncd with BackupPC you will need to install File::RsyncP.
You can run "perldoc File::RsyncP" to see if this module is installed.
File::RsyncP is available from L<http://perlrsync.sourceforge.net>.
-Version 0.31 or later is required.
+Version 0.41 or later is required.
=back
</Location>
</IfModule>
-For Apache 2.x and perl 5.8.x
-
Apache 2.0.44 with Perl 5.8.0 on RedHat 7.1, Don Silvia reports that
this works:
require valid-user
</Location>
-If you want to defeat the user authentication you can force a
-particular user name by getting Apache to set REMOTE_USER, eg,
-to hardcode the user to www you could add this to httpd.conf:
+If you want to disable the user authentication you can set
+$Conf{CgiAdminUsers} to '*', which allows any user to have
+full access to all hosts and backups. In this case the REMOTE_USER
+environment variable does not have to be set by Apache.
+
+Alternatively, you can force a particular user name by getting Apache
+to set REMOTE_USER, eg, to hardcode the user to www you could add
+this to Apache's httpd.conf:
<Location /cgi-bin/BackupPC/BackupPC_Admin> # <--- change path as needed
Setenv REMOTE_USER www
up. You should make sure that $Conf{CgiImageDirURL} is the correct
URL for the image directory.
+See the section L<Debugging installation problems|debugging installation problems> for suggestions on debugging the Apache authentication setup.
+
=head2 How BackupPC Finds Hosts
Starting with v2.0.0 the way hosts are discovered has changed. In most
=over 4
+=item Removing a client
+
+If there is a machine that no longer needs to be backed up (eg: a retired
+machine) you have two choices. First, you can keep the backups accessible
+and browsable, but disable all new backups. Alternatively, you can
+completely remove the client and all its backups.
+
+To disable backups for a client there are two special values for
+$Conf{FullPeriod} in that client's per-PC config.pl file:
+
+=over 4
+
+=item -1
+
+Don't do any regular backups on this machine. Manually
+requested backups (via the CGI interface) will still occur.
+
+=item -2
+
+Don't do any backups on this machine. Manually requested
+backups (via the CGI interface) will be ignored.
+
+=back
+
+This will still allow that client's old backups to be browsable
+and restorable.
+
+To completely remove a client and all its backups, you should remove its
+entry in the conf/hosts file, and then delete the __TOPDIR__/pc/$host
+directory. Whenever you change the hosts file, you should send
+BackupPC a HUP (-1) signal so that it re-reads the hosts file.
+If you don't do this, BackupPC will automatically re-read the
+hosts file at the next regular wakeup.
+
+Note that when you remove a client's backups you won't initially recover
+a lot of disk space. That's because the client's files are still in
+the pool. Overnight, when BackupPC_nightly next runs, all the unused
+pool files will be deleted and this will recover the disk space used
+by the client's backups.
+
=item Copying the pool
If the pool disk requirements grow you might need to copy the entire
the config settings $Conf{CgiAdminUserGroup} and $Conf{CgiAdminUsers}
correctly specify the privileged administrator users.
+=item You cannot access per-host information in the CGI interface
+
+If you get the error
+
+ Only privileged users can view information about host xyz
+
+it means that BackupPC_Admin is unable to match the user's login
+name (supplied by Apache via the REMOTE_USER environment variable)
+with either that host's user name (in the conf/hosts file) or
+with the administrators specified in the $Conf{CgiAdminUsers}
+or $Conf{CgiAdminUserGroup} settings.
+
+The most common problem is that REMOTE_USER is not set because the
+Apache authentication is not correctly configured. In this case
+BackupPC_Admin will report this additional error:
+
+ Note: $ENV{REMOTE_USER} is not set, which could mean there is an
+ installation problem. BackupPC_Admin expects Apache to authenticate
+ the user and pass their user name into this script as the REMOTE_USER
+ environment variable. See the documentation.
+
+You should review the configuration instructions to setup Apache
+authentication correctly. To test if REMOTE_USER is being set
+correctly, there is a simple script called printenv that is
+included with Apache. This is a simple CGI script that prints
+out all the environment variables. Place this script in the
+same directory as BackupPC_Admin and run it with a URL like:
+
+ http://myHost/cgi-bin/BackupPC/printenv
+
+Check the value of the REMOTE_USER environment variable.
+Here's a copy of the printenv script:
+
+ #!/usr/bin/perl
+ ##
+ ## printenv -- demo CGI program which just prints its environment
+ ##
+
+ print "Content-type: text/plain\n\n";
+ foreach $var (sort(keys(%ENV))) {
+ $val = $ENV{$var};
+ $val =~ s|\n|\\n|g;
+ $val =~ s|"|\\"|g;
+ print "${var}=\"${val}\"\n";
+ }
+
=item Can't ping or find host
Please read the section L<How BackupPC Finds Hosts|how backuppc finds hosts>.
-You should also verify that nmblookup correctly returns the netbios name.
+The BackupPC_dump command now has a -v option, so the easiest way to
+debug backup problems on a specific host is to run BackupPC_dump
+manually as the BackupPC user:
+
+ su __BACKUPPCUSER__
+ __INSTALLDIR__/bin/BackupPC_dump -v -f hostName
+
+This will run a full dump on hostName (replace with your host name).
+It will show each command (eg: ping, nmblookup and the full dump
+commands) and the output from each command. Reading the output
+carefully should show you what the problem is.
+
+You can also verify that nmblookup correctly returns the netbios name.
This is essential for DHCP hosts, and depending upon the setting of
$Conf{FixedIPNetBiosNameCheck} might also be required for fixed IP
address hosts too. Run this command:
=item Transport method doesn't work
-The BackupPC_dump command now has a -v option, so the easiest way to
+The BackupPC_dump command has a -v option, so the easiest way to
debug backup problems on a specific host is to run BackupPC_dump
manually as the BackupPC user:
su __BACKUPPCUSER__
- __INSTALLDIR__/bin/BackupPC_zcat
+ __INSTALLDIR__/bin/BackupPC_dump -v -f hostName
+
+This will run a full dump on hostName (replace with your host name)
+and will print all the output from each command, including the log
+output.
The most likely problems will relate to connecting to the smb shares on
each host. On each failed backup, a file __TOPDIR__/pc/$host/XferLOG.bad.z
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
-#!/usr/bin/perl -T
+#!/bin/perl -T
#
# by Manfred Herrmann (V1.1) (some typo errors + 3 new strings)
# CVS-> Revision ???
$Lang{Backup_requested_on__host_by__User} = "Backup angefordert für \$host durch \$User";
$Lang{Backup_stopped_dequeued_on__host_by__User} = "Backup gestoppt/gelöscht für \$host durch \$User";
-$Lang{log_User__User_downloaded_tar_archive_for__host} = "LOG User \$User hat tar Archiv downgeloaded von \$host,"
- . " Backup \$num; folgende Dateien: "
- . " \${join(\", \", \@fileListTrim)}";
-
-$Lang{log_User__User_downloaded_zip_archive_for__host}= "LOG User \$User hat zip Archiv downgeloaded von \$host,"
- . " Backup \$num; folgende Dateien: "
- . "\${join(\", \", \@fileListTrim)}";
$Lang{Restore_requested_to_host__hostDest__backup___num} = "Restore beauftragt nach Computer \$hostDest, von Backup #\$num,"
. " durch User \$User von Client \$ENV{REMOTE_ADDR}";
# --------
$Lang{Last_error_is____EscHTML_StatusHost_error} = <<EOF;
-<li>Letzter Fehler ist \"\${EscHTML(\$StatusHost{error})}\"
+<li>Letzter Fehler ist \"\${EscHTML(\$StatusHost{error})}\".
EOF
# ------
$Lang{Reason_restore_done} = "Restore durchgeführt";
$Lang{Reason_nothing_to_do} = "kein Auftrag";
$Lang{Reason_backup_failed} = "Backup Fehler";
+$Lang{Reason_restore_failed} = "Restore Fehler";
$Lang{Reason_no_ping} = "nicht erreichbar";
$Lang{Reason_backup_canceled_by_user} = "Abbruch durch User";
+$Lang{Reason_restore_canceled_by_user} = "Abbruch durch User";
# ---------
# Email messages
$Lang{Backup_requested_on__host_by__User} = "Backup requested on \$host by \$User";
$Lang{Backup_stopped_dequeued_on__host_by__User} = "Backup stopped/dequeued on \$host by \$User";
-$Lang{log_User__User_downloaded_tar_archive_for__host} = "log User \$User downloaded tar archive for \$host,"
- . " backup \$num; files were: "
- . " \${join(\", \", \@fileListTrim)}";
-
-$Lang{log_User__User_downloaded_zip_archive_for__host}= "log User \$User downloaded zip archive for \$host,"
- . " backup \$num; files were: "
- . "\${join(\", \", \@fileListTrim)}";
$Lang{Restore_requested_to_host__hostDest__backup___num} = "Restore requested to host \$hostDest, backup #\$num,"
. " by \$User from \$ENV{REMOTE_ADDR}";
# --------
$Lang{Last_error_is____EscHTML_StatusHost_error} = <<EOF;
-<li>Last error is \"\${EscHTML(\$StatusHost{error})}\"
+<li>Last error is \"\${EscHTML(\$StatusHost{error})}\".
EOF
# ------
$Lang{Reason_restore_done} = "restore done";
$Lang{Reason_nothing_to_do} = "nothing to do";
$Lang{Reason_backup_failed} = "backup failed";
+$Lang{Reason_restore_failed} = "restore failed";
$Lang{Reason_no_ping} = "no ping";
$Lang{Reason_backup_canceled_by_user} = "backup canceled by user";
+$Lang{Reason_restore_canceled_by_user} = "restore canceled by user";
# ---------
# Email messages
$Lang{Backup_requested_on__host_by__User} = "Copia de seguridad solicitada en \$host por \$User";
$Lang{Backup_stopped_dequeued_on__host_by__User} = "Copia de seguridad detenida/desprogramada en \$host por \$User";
-$Lang{log_User__User_downloaded_tar_archive_for__host} = "El usuario del registro \$User ha descargado un archivo Tar para \$host,"
- . " copia de seguridad \$num; los archivos eran: "
- . " \${join(\", \", \@fileListTrim)}";
-
-$Lang{log_User__User_downloaded_zip_archive_for__host}= "El usuario del registro \$User ha descargado un archivo Zip para \$host,"
- . " copia de seguridad \$num; los archivos eran: "
- . "\${join(\", \", \@fileListTrim)}";
$Lang{Restore_requested_to_host__hostDest__backup___num} = "Restauración solicitada para el host \$hostDest, copia de seguridad #\$num,"
. " por \$User desde \$ENV{REMOTE_ADDR}";
# --------
$Lang{Last_error_is____EscHTML_StatusHost_error} = <<EOF;
-<li>El último error fué \"\${EscHTML(\$StatusHost{error})}\"
+<li>El último error fué \"\${EscHTML(\$StatusHost{error})}\".
EOF
# ------
$Lang{Reason_restore_done} = "restauración realizada";
$Lang{Reason_nothing_to_do} = "nada por hacer";
$Lang{Reason_backup_failed} = "copia de seguridad fallida";
+$Lang{Reason_restore_failed} = "restauración fallida";
$Lang{Reason_no_ping} = "no hay ping";
$Lang{Reason_backup_canceled_by_user} = "copia cancelada por el usuario";
+$Lang{Reason_restore_canceled_by_user} = "restauración cancelada por el usuario";
# ---------
# Email messages
$Lang{Backup_requested_on__host_by__User} = "Sauvegarde demandée sur \$host par \$User";
$Lang{Backup_stopped_dequeued_on__host_by__User} = "Sauvegarde Arrêtée/déprogrammée pour \$host par \$User";
-$Lang{log_User__User_downloaded_tar_archive_for__host} = "log L\'utilisateur \$User a téléchargé "
- . "l\'archive tar pour \$host,"
- . " sauvegarde \$num; Les fichiers étaient: "
- . " \${join(\", \", \@fileListTrim)}";
-$Lang{log_User__User_downloaded_zip_archive_for__host}= "log L\'utilisateur \$User a téléchargé "
- . "l\'archive zip pour \$host,"
- . " Sauvegarde \$num; Les fichiers étaient: "
- . "\${join(\", \", \@fileListTrim)}";
$Lang{Restore_requested_to_host__hostDest__backup___num} = "Restauration demandée pour l\'hôte \$hostDest, "
. "sauvegarde n° \$num,"
. " par \$User depuis \$ENV{REMOTE_ADDR}";
# --------
$Lang{Last_error_is____EscHTML_StatusHost_error} = <<EOF;
-<li>La dernière erreur est \"\${EscHTML(\$StatusHost{error})}\"
+<li>La dernière erreur est \"\${EscHTML(\$StatusHost{error})}\".
EOF
# ------
$Lang{Reason_restore_done} = "restauration terminée";
$Lang{Reason_nothing_to_do} = "rien à faire";
$Lang{Reason_backup_failed} = "la sauvegarde a échouée";
+$Lang{Reason_restore_failed} = "la restauration a échouée";
$Lang{Reason_no_ping} = "pas de ping";
$Lang{Reason_backup_canceled_by_user} = "sauvegarde annulée par l'utilisateur";
+$Lang{Reason_restore_canceled_by_user} = "restauration annulée par l'utilisateur";
# ---------
# Email messages
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
TopDir => $topDir || '/data/BackupPC',
BinDir => $installDir || '/usr/local/BackupPC',
LibDir => $installDir || '/usr/local/BackupPC',
- Version => '2.0.0beta2',
+ Version => '2.0.0beta3',
BackupFields => [qw(
num type startTime endTime
nFiles size nFilesExist sizeExist nFilesNew sizeNew
$arg =~ s{\$(\w+)(\+?)}{
exists($vars->{$1}) && ref($vars->{$1}) ne "ARRAY"
? ($2 eq "+" ? $bpc->shellEscape($vars->{$1}) : $vars->{$1})
- : "\$$1"
+ : "\$$1$2"
}eg;
#
# Now replicate any array arguments; this just works for just one
print("cmdExecOrEval: about to exec ",
$bpc->execCmd2ShellCmd(@$cmd), "\n")
if ( $bpc->{verbose} );
- exec(@$cmd);
+ exec(map { m/(.*)/ } @$cmd); # untaint
print(STDERR "Exec failed for @$cmd\n");
exit(1);
}
#
close(STDERR);
open(STDERR, ">&STDOUT");
- exec(@$cmd);
+ exec(map { m/(.*)/ } @$cmd); # untaint
print("Exec of @$cmd failed\n");
exit(1);
}
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
|| $type == BPC_FTYPE_BLOCKDEV
|| $type == BPC_FTYPE_SYMLINK ) {
my $fh = BackupPC::FileZIO->open($a->{fullPath}, 0, $a->{compress});
- my $str;
+ my($str, $rdSize);
if ( defined($fh) ) {
- if ( $fh->read(\$str, $a->{size} + 1) == $a->{size} ) {
- if ( $type == BPC_FTYPE_SYMLINK ) {
- #
- # Reconstruct symbolic link
- #
- $extraAttribs = { link => $str };
- } elsif ( $str =~ /(\d*),(\d*)/ ) {
- #
- # Reconstruct char or block special major/minor device num
- #
- $extraAttribs = { rdev => $1 * 256 + $2 };
- } else {
- $fio->log("$name: unexpected special file contents $str");
+ $rdSize = $fh->read(\$str, $a->{size} + 1024);
+ if ( $type == BPC_FTYPE_SYMLINK ) {
+ #
+ # Reconstruct symbolic link
+ #
+ $extraAttribs = { link => $str };
+ if ( $rdSize != $a->{size} ) {
+ # ERROR
+ $fio->log("$name: can't read exactly $a->{size} bytes");
$fio->{stats}{errorCnt}++;
}
+ } elsif ( $str =~ /(\d*),(\d*)/ ) {
+ #
+ # Reconstruct char or block special major/minor device num
+ #
+ # Note: char/block devices have $a->{size} = 0, so we
+ # can't do an error check on $rdSize.
+ #
+ $extraAttribs = { rdev => $1 * 256 + $2 };
} else {
- # ERROR
- $fio->log("$name: can't read exactly $a->{size} bytes");
+ $fio->log("$name: unexpected special file contents $str");
$fio->{stats}{errorCnt}++;
}
$fh->close;
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
#
#========================================================================
#
-# Version 2.0.0beta2, released 13 Apr 2003.
+# Version 2.0.0beta3, released 1 Jun 2003.
#
# See http://backuppc.sourceforge.net.
#
umask(0022);
-my $Version = "2.0.0beta2";
-my $ReleaseDate = "11 May 2003";
+my $Version = "2.0.0beta3";
+my $ReleaseDate = "1 Jun 2003";
my $DistDir = "dist/BackupPC-$Version";
my @PerlSrc = qw(