/[BackupPC]/trunk/bin/BackupPC_sendEmail
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/bin/BackupPC_sendEmail

Parent Directory Parent Directory | Revision Log Revision Log


Revision 316 - (show annotations)
Mon Jan 30 13:37:17 2006 UTC (18 years, 3 months ago) by dpavlin
File size: 11429 byte(s)
 r9152@llin:  dpavlin | 2006-01-30 14:11:45 +0100
 update to upstream 2.1.2

1 #!/bin/perl
2 #============================================================= -*-perl-*-
3 #
4 # BackupPC_sendEmail: send status emails to users and admins
5 #
6 # DESCRIPTION
7 #
8 # BackupPC_sendEmail: send status emails to users and admins.
9 # BackupPC_sendEmail is run by BackupPC_nightly, so it runs
10 # once every night.
11 #
12 # AUTHOR
13 # Craig Barratt <cbarratt@users.sourceforge.net>
14 #
15 # COPYRIGHT
16 # Copyright (C) 2001-2003 Craig Barratt
17 #
18 # This program is free software; you can redistribute it and/or modify
19 # it under the terms of the GNU General Public License as published by
20 # the Free Software Foundation; either version 2 of the License, or
21 # (at your option) any later version.
22 #
23 # This program is distributed in the hope that it will be useful,
24 # but WITHOUT ANY WARRANTY; without even the implied warranty of
25 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 # GNU General Public License for more details.
27 #
28 # You should have received a copy of the GNU General Public License
29 # along with this program; if not, write to the Free Software
30 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #
32 #========================================================================
33 #
34 # Version 2.1.2, released 5 Sep 2005.
35 #
36 # See http://backuppc.sourceforge.net.
37 #
38 #========================================================================
39
40 use strict;
41 no utf8;
42 use lib "__INSTALLDIR__/lib";
43 use BackupPC::Lib;
44 use BackupPC::FileZIO;
45
46 use Data::Dumper;
47 use Getopt::Std;
48 use DirHandle ();
49 use vars qw($Lang $TopDir $BinDir %Conf);
50
51 die("BackupPC::Lib->new failed\n") if ( !(my $bpc = BackupPC::Lib->new) );
52 $TopDir = $bpc->TopDir();
53 $BinDir = $bpc->BinDir();
54 %Conf = $bpc->Conf();
55 $Lang = $bpc->Lang();
56
57 $bpc->ChildInit();
58
59 use vars qw(%UserEmailInfo);
60 do "$TopDir/log/UserEmailInfo.pl";
61
62 my %opts;
63 if ( !getopts("t", \%opts) || @ARGV != 0 ) {
64 print("usage: $0 [-t]\n");
65 exit(1);
66 }
67
68 my $err = $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort});
69 if ( $err ) {
70 print("Can't connect to server ($err)\n");
71 exit(1);
72 }
73 my $reply = $bpc->ServerMesg("status hosts");
74 $reply = $1 if ( $reply =~ /(.*)/s );
75 my(%Status, %Info, %Jobs, @BgQueue, @UserQueue, @CmdQueue);
76 eval($reply);
77
78 ###########################################################################
79 # Generate sysadmin warning messages
80 ###########################################################################
81 my $mesg = "";
82
83 my @badHosts = ();
84 foreach my $host ( sort(keys(%Status)) ) {
85 next if ( ($Status{$host}{reason} ne "Reason_backup_failed"
86 && $Status{$host}{reason} ne "Reason_restore_failed")
87 || $Status{$host}{error} =~ /^lost network connection to host/ );
88 push(@badHosts, "$host ($Status{$host}{error})");
89 }
90 if ( @badHosts ) {
91 my $badHosts = join("\n - ", sort(@badHosts));
92 $mesg .= <<EOF;
93 The following hosts had an error that is probably caused by a
94 misconfiguration. Please fix these hosts:
95 - $badHosts
96
97 EOF
98 }
99
100 #
101 # Report if we skipped backups because the disk was too full
102 #
103 if ( $Info{DUDailySkipHostCntPrev} > 0 ) {
104 my $n = $Info{DUDailySkipHostCntPrev};
105 my $m = $Conf{DfMaxUsagePct};
106 $mesg .= <<EOF;
107 Yesterday $n hosts were skipped because the file system containing
108 $TopDir was too full. The threshold in the
109 configuration file is $m%, while yesterday the file system was
110 up to $Info{DUDailyMaxPrev}% full. Please find more space on the file system,
111 or reduce the number of full or incremental backups that we keep.
112
113 EOF
114 }
115
116 #
117 # Check for bogus directories (probably PCs that are no longer
118 # on the backup list)
119 #
120 my $d = DirHandle->new("$TopDir/pc") or die("Can't read $TopDir/pc: $!");
121 my @oldDirs = ();
122 my @files = $d->read;
123 $d->close;
124 foreach my $host ( @files ) {
125 next if ( $host =~ /^\./ || defined($Status{$host}) );
126 push(@oldDirs, "$TopDir/pc/$host");
127 }
128 if ( @oldDirs ) {
129 my $oldDirs = join("\n - ", sort(@oldDirs));
130 $mesg .= <<EOF;
131 The following directories are bogus and are not being used by
132 BackupPC. This typically happens when PCs are removed from the
133 backup list. If you don't need any old backups from these PCs you
134 should remove these directories. If there are machines on this
135 list that should be backed up then there is a problem with the
136 hosts file:
137 - $oldDirs
138
139 EOF
140 }
141
142 if ( $mesg ne "" && $Conf{EMailAdminUserName} ne "" ) {
143 $mesg = <<EOF;
144 To: $Conf{EMailAdminUserName}
145 Subject: BackupPC administrative attention needed
146
147 ${mesg}Regards,
148 PC Backup Genie
149 EOF
150 if ( $opts{t} ) {
151 print("#" x 75, "\n");
152 print $mesg;
153 } else {
154 SendMail($mesg);
155 }
156 }
157
158 ###########################################################################
159 # Generate per-host warning messages sent to each user
160 ###########################################################################
161 my $Hosts = $bpc->HostInfoRead();
162
163 foreach my $host ( sort(keys(%Status)) ) {
164 next if ( $Hosts->{$host}{user} eq "" );
165 #
166 # read any per-PC config settings (allowing per-PC email settings)
167 #
168 $bpc->ConfigRead($host);
169 %Conf = $bpc->Conf();
170 my $user = $Hosts->{$host}{user};
171 next if ( time - $UserEmailInfo{$user}{lastTime}
172 < $Conf{EMailNotifyMinDays} * 24*3600 );
173 next if ($Conf{XferMethod} eq "archive" );
174 my @Backups = $bpc->BackupInfoRead($host);
175 my $numBackups = @Backups;
176 if ( $numBackups == 0 ) {
177 my $subj = defined($Conf{EMailNoBackupEverSubj})
178 ? $Conf{EMailNoBackupEverSubj}
179 : $Lang->{EMailNoBackupEverSubj};
180 my $mesg = defined($Conf{EMailNoBackupEverMesg})
181 ? $Conf{EMailNoBackupEverMesg}
182 : $Lang->{EMailNoBackupEverMesg};
183 sendUserEmail($user, $host, $mesg, $subj, {
184 userName => user2name($user)
185 }) if ( !defined($Jobs{$host}) );
186 next;
187 }
188 my $last = my $lastFull = my $lastIncr = 0;
189 my $lastGoodOutlook = 0;
190 my $lastNum = -1;
191 my $numBadOutlook = 0;
192 for ( my $i = 0 ; $i < @Backups ; $i++ ) {
193 my $fh;
194 $lastNum = $Backups[$i]{num} if ( $lastNum < $Backups[$i]{num} );
195 if ( $Backups[$i]{type} eq "full" ) {
196 $lastFull = $Backups[$i]{startTime}
197 if ( $lastFull < $Backups[$i]{startTime} );
198 } else {
199 $lastIncr = $Backups[$i]{startTime}
200 if ( $lastIncr < $Backups[$i]{startTime} );
201 }
202 $last = $Backups[$i]{startTime}
203 if ( $last < $Backups[$i]{startTime} );
204 my $badOutlook = 0;
205 my $file = "$TopDir/pc/$host/SmbLOG.$Backups[$i]{num}";
206 my $comp = 0;
207 if ( !-f $file ) {
208 $file = "$TopDir/pc/$host/XferLOG.$Backups[$i]{num}";
209 if ( !-f $file ) {
210 $comp = 1;
211 $file = "$TopDir/pc/$host/SmbLOG.$Backups[$i]{num}.z";
212 $file = "$TopDir/pc/$host/XferLOG.$Backups[$i]{num}.z"
213 if ( !-f $file );
214 }
215 }
216 next if ( !defined($fh = BackupPC::FileZIO->open($file, 0, $comp)) );
217 while ( 1 ) {
218 my $s = $fh->readLine();
219 last if ( $s eq "" );
220 if ( $s =~ /^\s*Error reading file.*\.pst : (ERRDOS - ERRlock|NT_STATUS_FILE_LOCK_CONFLICT)/
221 || $s =~ /^\s*Error reading file.*\.pst\. Got 0 bytes/ ) {
222 $badOutlook = 1;
223 last;
224 }
225 }
226 $fh->close();
227 $numBadOutlook += $badOutlook;
228 if ( !$badOutlook ) {
229 $lastGoodOutlook = $Backups[$i]{startTime}
230 if ( $lastGoodOutlook < $Backups[$i]{startTime} );
231 }
232 }
233 if ( time - $last > $Conf{EMailNotifyOldBackupDays} * 24*3600 ) {
234 my $subj = defined($Conf{EMailNoBackupRecentSubj})
235 ? $Conf{EMailNoBackupRecentSubj}
236 : $Lang->{EMailNoBackupRecentSubj};
237 my $mesg = defined($Conf{EMailNoBackupRecentMesg})
238 ? $Conf{EMailNoBackupRecentMesg}
239 : $Lang->{EMailNoBackupRecentMesg};
240 my $firstTime = sprintf("%.1f",
241 (time - $Backups[0]{startTime}) / (24*3600));
242 my $days = sprintf("%.1f", (time - $last) / (24 * 3600));
243 sendUserEmail($user, $host, $mesg, $subj, {
244 firstTime => $firstTime,
245 days => $days,
246 userName => user2name($user),
247 numBackups => $numBackups,
248 }) if ( !defined($Jobs{$host}) );
249 next;
250 }
251 if ( $numBadOutlook > 0
252 && time - $lastGoodOutlook > $Conf{EMailNotifyOldOutlookDays}
253 * 24 * 3600 ) {
254 my($days, $howLong);
255 if ( $lastGoodOutlook == 0 ) {
256 $howLong = eval("qq{$Lang->{howLong_not_been_backed_up}}");
257 } else {
258 $days = sprintf("%.1f", (time - $lastGoodOutlook) / (24*3600));
259 $howLong = eval("qq{$Lang->{howLong_not_been_backed_up_for_days_days}}");
260 }
261 my $subj = defined($Conf{EMailOutlookBackupSubj})
262 ? $Conf{EMailOutlookBackupSubj}
263 : $Lang->{EMailOutlookBackupSubj};
264 my $mesg = defined($Conf{EMailOutlookBackupMesg})
265 ? $Conf{EMailOutlookBackupMesg}
266 : $Lang->{EMailOutlookBackupMesg};
267 my $firstTime = sprintf("%.1f",
268 (time - $Backups[0]{startTime}) / (24*3600));
269 my $lastTime = sprintf("%.1f",
270 (time - $Backups[$#Backups]{startTime}) / (24*3600));
271 sendUserEmail($user, $host, $mesg, $subj, {
272 days => $days,
273 firstTime => $firstTime,
274 lastTime => $lastTime,
275 numBackups => $numBackups,
276 userName => user2name($user),
277 howLong => $howLong,
278 serverHost => $Conf{ServerHost},
279 }) if ( !defined($Jobs{$host}) );
280 }
281 }
282 if ( !$opts{t} ) {
283 $Data::Dumper::Indent = 1;
284 my $dumpStr = Data::Dumper->Dump(
285 [\%UserEmailInfo],
286 [qw(*UserEmailInfo)]);
287 if ( open(HOST, ">", "$TopDir/log/UserEmailInfo.pl") ) {
288 binmode(HOST);
289 print(HOST $dumpStr);
290 close(HOST);
291 }
292 }
293
294 sub user2name
295 {
296 my($user) = @_;
297 my($name) = (getpwnam($user))[6];
298 $name =~ s/\s.*//;
299 $name = $user if ( $name eq "" );
300 return $name;
301 }
302
303 sub sendUserEmail
304 {
305 my($user, $host, $mesg, $subj, $vars) = @_;
306 $vars->{user} = $user;
307 $vars->{host} = $host;
308 $vars->{domain} = $Conf{EMailUserDestDomain};
309 $vars->{CgiURL} = $Conf{CgiURL};
310 $subj =~ s/\$(\w+)/defined($vars->{$1}) ? $vars->{$1} : "\$$1"/eg;
311 $vars->{subj} = $subj;
312 $mesg =~ s/\$(\w+)/defined($vars->{$1}) ? $vars->{$1} : "\$$1"/eg;
313 if ( $opts{t} ) {
314 print("#" x 75, "\n");
315 print $mesg;
316 } else {
317 SendMail($mesg);
318 }
319 $UserEmailInfo{$user}{lastTime} = time;
320 $UserEmailInfo{$user}{lastSubj} = $subj;
321 $UserEmailInfo{$user}{lastHost} = $host;
322 }
323
324 sub SendMail
325 {
326 my($mesg) = @_;
327 my($from) = $Conf{EMailFromUserName};
328 local(*MAIL);
329
330 $from = "-f $from" if ( $from ne "" );
331 if ( !open(MAIL, "|$Conf{SendmailPath} -t $from") ) {
332 printf("Can't run sendmail ($Conf{SendmailPath}): $!\n");
333 return;
334 }
335 print MAIL $mesg;
336 close(MAIL);
337 }

Properties

Name Value
svn:executable

  ViewVC Help
Powered by ViewVC 1.1.26