add example for tr7432
[upsgraph] / upsgraph.pl
1 #!/usr/bin/perl -w
2
3 #Due to memory leak in Debian squeeze (Bug #545519)
4 my $use_rrds = 0;
5 my $rrd_result = 0;
6
7 if ((@ARGV != 1) && (@ARGV != 2)) {
8 print STDERR "Syntax: ${0} configfile [uid]\n";
9 exit(1);
10 }
11
12 use Net::SNMP;
13 use IO::Socket::INET;
14 use IO::Select;
15 use RRDs;
16 use File::Copy;
17 use Data::Dumper;
18 use LWP::UserAgent;
19 use JSON;
20
21 $UPSGRAPH::outdir = "";
22 $UPSGRAPH::daysCovered = 370;
23 $UPSGRAPH::step = 60;
24 $UPSGRAPH::stepsPerHour = (60 * 60) / $UPSGRAPH::step;
25 $UPSGRAPH::keep = ($UPSGRAPH::daysCovered*24*60*60)/$UPSGRAPH::step;
26 $UPSGRAPH::keepHours = ($UPSGRAPH::daysCovered*24*60*60)/$UPSGRAPH::stepsPerHour/$UPSGRAPH::step;
27 $UPSGRAPH::hosts = ();
28 $UPSGRAPH::regenerateOnStart = 1; #when set, regenerate graphs on script startup
29
30 do $ARGV[0] or die "can't read config: $!";
31
32 my $outdir = $UPSGRAPH::outdir;
33 my $step = $UPSGRAPH::step;
34 my $stepsPerHour = $UPSGRAPH::stepsPerHour;
35 my $keep = $UPSGRAPH::keep;
36 my $keepHours = $UPSGRAPH::keepHours;
37 my $hosts = $UPSGRAPH::hosts;
38
39 sub rrd_update(@) {
40 my @args = @_;
41
42 if ($use_rrds == 1) {
43 RRDs::update(@args);
44 $rrd_result = RRDs::error;
45 } else {
46 $rrd_result = system("rrdtool", "update", @args);
47 }
48 }
49
50 sub rrd_graph(@) {
51 my @args = @_;
52 my @rrd_out = ();
53
54 if ($use_rrds == 1) {
55 @rrd_out = RRDs::graph(@args);
56 $rrd_result = RRDs::error;
57 } else {
58 my $rrd_stdout;
59
60 open(RRDFD, '-|', 'rrdtool', 'graph', @args);
61 while(<RRDFD>) {
62 chomp;
63 $rrd_stdout = $_;
64 }
65 close(RRDFD);
66 $rrd_result = $?;
67 if ($rrd_result == 0) {
68 push @rrd_out, 0;
69 push @rrd_out, split(/x/, $rrd_stdout);
70 }
71 }
72
73 return @rrd_out;
74 }
75
76 sub rrdcreate(@) {
77 my $newrrd = shift;
78 my $field = shift;
79 my $vars = shift;
80 my $start = shift;
81
82 my @cmd = ("${newrrd}", "--step=${step}");
83
84 if (defined($start)) {
85 push @cmd, "--start=${start}";
86 }
87
88 push @cmd, "DS:${field}:GAUGE:600:" .
89 $vars->{$field}->{'min'} . ":" .
90 $vars->{$field}->{'max'};
91
92 push @cmd, "RRA:AVERAGE:0.5:1:${keep}";
93 push @cmd, "RRA:MIN:0.4:${stepsPerHour}:${keepHours}";
94 push @cmd, "RRA:MAX:0.4:${stepsPerHour}:${keepHours}";
95 push @cmd, "RRA:AVERAGE:0.5:${stepsPerHour}:${keepHours}";
96
97 RRDs::create(@cmd);
98 if (RRDs::error) {
99 print "Error while creating: " . RRDs::error . "\n";
100 exit 1;
101 }
102 }
103
104 sub fetch_snmp(@) {
105 my $address = shift;
106 my $community = shift;
107 my $oid = shift;
108
109 (my $session, my $error) = Net::SNMP->session(Hostname => $address,
110 Community => $community);
111
112 if (!$session) {
113 print STDERR "session error: $error";
114 return undef;
115 }
116
117 $session->translate(0);
118
119 my $result = $session->get_request($oid);
120
121 $session->close;
122
123 return undef if (!defined($result));
124
125 $result->{$oid};
126 }
127
128 sub fetch_tcp(@) {
129 my $address = shift;
130 my $port = shift;
131
132 my $sock = IO::Socket::INET->new(PeerAddr => $address,
133 PeerPort => $port,
134 Proto => 'tcp',
135 Timeout => 1);
136
137 return undef if (!$sock);
138
139 my $select = IO::Select->new($sock);
140
141 my $value = undef;
142
143 if ($select->can_read(1)) {
144 chomp($value) if (sysread($sock, $value, 4096) > 0);
145 }
146
147 close($sock);
148
149 if (!$value) {
150 return undef;
151 }
152
153 $value=~ s/\s//g;
154
155 $value;
156 }
157
158 sub fetch_tcp_multi(@) {
159 my $address = shift;
160 my $port = shift;
161 my $delimiter = shift;
162 my %values;
163
164 my $sock = IO::Socket::INET->new(PeerAddr => $address,
165 PeerPort => $port,
166 Proto => 'tcp',
167 Timeout => 1);
168
169 return undef if (!$sock);
170
171 my $select = IO::Select->new($sock);
172
173 while($select->can_read(1)) {
174 if (sysread($sock, my $buf, 16384) > 0) {
175 $buf=~s/\r//g;
176 foreach my $line (split(/\n/, $buf)) {
177 (my $key, my $value) = split(/${delimiter}/, $line);
178 $value=~ s/\s//g;
179 $values{$key} = $value;
180 }
181 } else {
182 last;
183 }
184 }
185
186 close($sock);
187
188 %values;
189 }
190
191 sub fetch_iotcore(@) {
192 my $host = shift;
193 my $adr = shift;
194 my $mask = shift;
195
196 my $ua = LWP::UserAgent->new;
197 $ua->timeout(1);
198
199 my $iotcore_req = {
200 cid => 1,
201 code => 10,
202 adr => $adr,
203 };
204
205 my $req = HTTP::Request->new(POST => "http://${host}");
206 $req->content_type('application/json');
207 $req->content(encode_json($iotcore_req));
208
209 my $resp = $ua->request($req);
210 return undef if (!$resp->is_success);
211
212 my $pdin = decode_json($resp->decoded_content);
213 return undef if (!defined($pdin));
214
215 my $value = hex($pdin->{'data'}->{'value'});
216
217 if (defined($mask)) {
218 $value = $value & $mask;
219 }
220
221 $value;
222 }
223
224 sub dayGraphFunc {
225 my $dataSrc = shift;
226 my $mode = shift;
227 my $color = shift;
228 my $label = shift;
229 my $dataPoints = shift;
230 my @args = ();
231 push @args, "CDEF:prev${mode}1=PREV(${dataSrc})";
232 for (my $i = 1; $i < $dataPoints - 1; ++$i) {
233 my $prev = $i;
234 my $next = $i+1;
235 push @args, "CDEF:prev${mode}${next}=PREV(prev${mode}${prev})";
236 }
237 my $dayCons = '';
238 my $consFunc = '';
239 if ($mode ne 'AVG') {
240 for (my $i = 1; $i < $dataPoints; ++$i) {
241 $dayCons .= "prev${mode}${i},";
242 $consFunc .= ",${mode}";
243 }
244 } else {
245 for (my $i = 1; $i < $dataPoints; ++$i) {
246 $dayCons .= "prev${mode}${i},";
247 }
248 $consFunc = ",${dataPoints},${mode}";
249 }
250 push @args, "CDEF:day${mode}=${dayCons}${dataSrc}${consFunc}";
251 push @args, "CDEF:fillCalDay${mode}0=COUNT,${dataPoints},%,0,EQ,day${mode},UNKN,IF";
252 for (my $i = 1; $i < $dataPoints; ++$i) {
253 my $prev = $i-1;
254 my $next = $i;
255 push @args, "CDEF:fillCalDay${mode}${next}=PREV(fillCalDay${mode}${prev})";
256 }
257 my $fillPoint = '';
258 my $if = '';
259 for (my $i = 0; $i < $dataPoints; ++$i) {
260 $fillPoint .= "COUNT,${dataPoints},%,${i},EQ,fillCalDay${mode}${i},";
261 $if .= ",IF";
262 }
263 push @args, "CDEF:${mode}Curve=${fillPoint}UNKN${if}";
264 my $forwardShift = (24*60*60) * ($dataPoints - 1) / $dataPoints;
265 push @args, "SHIFT:${mode}Curve:-${forwardShift}";
266 push @args, "LINE1:${mode}Curve#${color}:${label}";
267 return \@args;
268 }
269
270 sub cfgToGraphDef {
271 my $cfg = shift;
272 my $varname = shift;
273 my $dpPerDay= shift;
274 my @graphDef = ();
275 foreach my $subGraph (@$cfg) {
276 if ($subGraph eq 'avg') {
277 push @graphDef, "LINE1:${varname}-avg#FF0000";
278 } elsif ($subGraph eq 'day-min') {
279 push @graphDef, @{dayGraphFunc("${varname}-min", 'MIN', '0000ff', 'Day Minimum Temperature', $dpPerDay)};
280 } elsif ($subGraph eq 'day-max') {
281 push @graphDef, @{dayGraphFunc("${varname}-max", 'MAX', '00ff00', 'Day Maximum Temperature', $dpPerDay)};
282 } elsif ($subGraph eq 'day-avg') {
283 push @graphDef, @{dayGraphFunc("${varname}-houravg", 'AVG', 'ff0000', 'Day Average Temperature', $dpPerDay)};
284 }
285 }
286 return \@graphDef;
287 }
288
289 if ($> == 0) {
290 if (@ARGV != 2) {
291 print STDERR "Running as root, please provide UID as 2th argument!\n";
292 exit(1);
293 }
294
295 print "Running as root, switching to ".$ARGV[1]."\n";
296 $< = $> = $ARGV[1];
297 }
298
299 foreach my $host (@$hosts) {
300 my $rrdfile = $host->{'rrdfile'};
301
302 foreach my $var (keys(%{$host->{'vars'}})) {
303 $host->{'vars'}->{$var}->{'min'} = 'U' if (!defined($host->{'vars'}->{$var}->{'min'}));
304 $host->{'vars'}->{$var}->{'max'} = 'U' if (!defined($host->{'vars'}->{$var}->{'max'}));
305 }
306
307 if (-e "${rrdfile}") {
308 print "Reading old ${rrdfile} to preserve data...\n";
309
310 my $rrdinfo = RRDs::info("${rrdfile}");
311 if (RRDs::error) {
312 print "Error while getting info: " . RRDs::error . "\n";
313 exit 1;
314 }
315
316 (my $start, my $ostep, my $names, my $data) =
317 RRDs::fetch("${rrdfile}",
318 "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})),
319 "AVERAGE");
320
321 if (RRDs::error) {
322 print "Error while fetching data: " . RRDs::error . "\n";
323 exit 1;
324 }
325
326 foreach my $field (@$names) {
327 if (! -e "${rrdfile}.${field}") {
328 rrdcreate("${rrdfile}.${field}",
329 "${field}",
330 $host->{'vars'},
331 (${start}-${ostep}));
332 }
333 }
334
335 my $pos = $start;
336 foreach my $line (@$data) {
337 foreach my $field (@$names) {
338 my $val = shift (@$line);
339 $val = 'U' if (!defined($val));
340
341 RRDs::update("${rrdfile}.${field}", "${pos}:${val}");
342 if (RRDs::error) {
343 print "Can't insert data: " . RRDs::error . "\n";
344 exit 1;
345 }
346
347 }
348
349 $pos += $ostep;
350
351 if ((($pos-$start)/$ostep) == $#$data) {
352 last;
353 }
354 }
355
356 rename("${rrdfile}", "${rrdfile}.old") or die "Can't rename old file: $!\n";
357 }
358
359 foreach my $field (@{$host->{'fields'}}) {
360 if (! -e "${rrdfile}.${field}") {
361 print "Creating ${rrdfile}.${field}...\n";
362 rrdcreate("${rrdfile}.${field}",
363 "${field}",
364 $host->{'vars'});
365 }
366
367 my $rrdinfo = RRDs::info("${rrdfile}.${field}");
368 if (RRDs::error) {
369 print "Error while getting info: " . RRDs::error . "\n";
370 exit 1;
371 }
372
373 my $limitsChanged = 0;
374 if (defined($rrdinfo->{"ds[${field}].min"})) {
375 if ($rrdinfo->{"ds[${field}].min"} ne $host->{'vars'}->{$field}->{'min'}) {
376 $limitsChanged = 1;
377 RRDs::tune("${rrdfile}.${field}","-i",$field.":".$host->{'vars'}->{$field}->{'min'});
378 }
379 } else {
380 if ($host->{'vars'}->{$field}->{'min'} ne 'U') {
381 $limitsChanged = 1;
382 RRDs::tune("${rrdfile}.${field}","-i",$field.":".$host->{'vars'}->{$field}->{'min'});
383 }
384 }
385
386 if (RRDs::error) {
387 print "Error while setting min: " . RRDs::error . "\n";
388 exit 1;
389 }
390
391 if (defined($rrdinfo->{"ds[${field}].max"})) {
392 if ($rrdinfo->{"ds[${field}].max"} ne $host->{'vars'}->{$field}->{'max'}) {
393 $limitsChanged = 1;
394 RRDs::tune("${rrdfile}.${field}","-a",$field.":".$host->{'vars'}->{$field}->{'max'});
395 }
396 } else {
397 if ($host->{'vars'}->{$field}->{'max'} ne 'U') {
398 $limitsChanged = 1;
399 RRDs::tune("${rrdfile}.${field}","-a",$field.":".$host->{'vars'}->{$field}->{'max'});
400 }
401 }
402
403 if (RRDs::error) {
404 print "Error while setting max: " . RRDs::error . "\n";
405 exit 1;
406 }
407
408 if ($rrdinfo->{'rra[0].rows'} != $keep ||
409 !defined($rrdinfo->{'rra[3].rows'}) || $rrdinfo->{'rra[3].rows'} != $keepHours ||
410 $limitsChanged == 1) {
411
412 print "Resizing ${rrdfile}.${field} from " . $rrdinfo->{'rra[0].rows'} .
413 " to ${keep} samples.\n";
414
415 (my $start, my $ostep, my $names, my $data) =
416 RRDs::fetch("${rrdfile}.${field}",
417 "-s " . (time() - ($rrdinfo->{'rra[0].rows'} * $rrdinfo->{'step'})),
418 "AVERAGE");
419
420 if (RRDs::error) {
421 print "Error while fetching data: " . RRDs::error . "\n";
422 exit 1;
423 }
424
425 rrdcreate("${rrdfile}.${field}.new",
426 "${field}",
427 $host->{'vars'},
428 (${start}-${ostep}));
429
430 print "Preserving data in file ${rrdfile}.${field} since " . localtime($start) . "\n";
431
432 my $pos = $start;
433 foreach my $line (@$data) {
434 my $vline = "${pos}";
435
436 foreach my $val (@$line) {
437 $val = 'U' if (!defined($val));
438 $vline .= ":${val}";
439 }
440 RRDs::update("${rrdfile}.${field}.new", $vline) or die "Can't insert data\n";
441
442 if (RRDs::error) {
443 print "Error while updating: " . RRDs::error . "\n";
444 exit 1;
445 }
446 $pos += $ostep;
447
448 if ((($pos-$start)/$ostep) == $#$data) {
449 last;
450 }
451 }
452
453 rename("${rrdfile}.${field}", "${rrdfile}.${field}.old") or die "Can't rename old file: $!\n";
454 rename("${rrdfile}.${field}.new", "${rrdfile}.${field}") or die "Can't rename new file: $!\n";
455
456 $rrdinfo = RRDs::info("${rrdfile}.${field}");
457 if (RRDs::error) {
458 print "Error while getting info: " . RRDs::error . "\n";
459 exit 1;
460 }
461
462 if ($rrdinfo->{'rra[0].rows'} != $keep) {
463 print "Failed!\n";
464 exit 1;
465 }
466 }
467 }
468 }
469
470 my $child = fork();
471
472 die "fork failed!" if (!defined($child));
473
474 exit 0 if ($child != 0);
475
476 my $first = $UPSGRAPH::regenerateOnStart;
477 while(1) {
478 open(HTML, ">${outdir}/index.html.new");
479
480 print HTML '<html><head><meta http-equiv="refresh" content="60"/><meta http-equiv="cache-control" content="no-cache"/><meta http-equiv="pragma" content="no-cache"/><meta http_equiv="expires" content="Sat, 26 Jul 1997 05:00:00 GMT"/><title>Status</title></head>';
481 print HTML '<body bgcolor="#ffffff">';
482
483 foreach my $host (@$hosts) {
484 print HTML "[<a href=\"#".${host}->{'name'}."\">".${host}->{'name'}."</a>]&nbsp;";
485 }
486 print HTML "<br>\n";
487
488 foreach my $host (@$hosts) {
489 print HTML "<br>\n";
490 print HTML "<a name=\"".${host}->{'name'}."\"></a>\n";
491 my $vars = $host->{'vars'};
492 my $rrdfile = $host->{'rrdfile'};
493 my $hostname = $host->{'name'};
494 my %multi_values = ();
495
496 foreach my $var (@{$host->{'fields'}}) {
497 delete $vars->{$var}->{'value'};
498
499 my $result;
500
501 if ((!defined($vars->{$var}->{'proto'})) ||
502 ($vars->{$var}->{'proto'} eq '') ||
503 ($vars->{$var}->{'proto'} eq 'snmp')) {
504 $result = fetch_snmp($host->{'address'}, $host->{'community'}, $vars->{$var}->{'oid'});
505 } elsif ($vars->{$var}->{'proto'} eq 'tcp') {
506 $result = fetch_tcp($host->{'address'}, $vars->{$var}->{'port'});
507 } elsif ($vars->{$var}->{'proto'} eq 'tcp_multi') {
508 if (defined($multi_values{$vars->{$var}->{'multi_id'}})) {
509 $result = $multi_values{$vars->{$var}->{'multi_id'}}
510 } else {
511 my %values = fetch_tcp_multi($host->{'address'}, $vars->{$var}->{'port'}, $vars->{$var}->{'multi_delimiter'});
512 @multi_values{keys %values} = values %values;
513 $result = $multi_values{$vars->{$var}->{'multi_id'}};
514 }
515 } elsif ($vars->{$var}->{'proto'} eq 'iotcore') {
516 $result = fetch_iotcore($host->{'address'}, $vars->{$var}->{'adr'}, $vars->{$var}->{'mask'});
517 }
518
519 next unless (defined $result);
520
521 $vars->{$var}->{'value'} = $result;
522 if (defined($vars->{$var}->{'factor'})) {
523 $vars->{$var}->{'value'} *= $vars->{$var}->{'factor'};
524 }
525 }
526
527 foreach my $var (@{$host->{'fields'}}) {
528 if (!(defined($vars->{$var}->{'value'}))) {
529 $vars->{$var}->{'value'} = 'U';
530 }
531 rrd_update("${rrdfile}.${var}", "N:" . $vars->{$var}->{'value'});
532 }
533 if ($rrd_result) {
534 print "Error while updating: " . $rrd_result . "\n";
535 }
536
537 foreach my $var (@{$host->{'fields'}}) {
538 my $graphWidth = 365 * 3;
539 my $graphConfig;
540 if (defined $vars->{$var}->{'graph'}) {
541 $graphConfig = $vars->{$var}->{'graph'};
542 foreach my $subGraph (qw(day week year)) {
543 if (!defined($graphConfig->{$subGraph})) {
544 $graphConfig->{$subGraph} = [ 'avg'];
545 }
546 }
547 } else {
548 $graphConfig = {
549 'day' => [ 'avg' ],
550 'week' => [ 'avg' ],
551 'year' => [ 'avg' ],
552 };
553 }
554
555 my @graphdef = ('-P', "-A", "-t", $hostname." - ".$vars->{$var}->{'name'});
556 push @graphdef, "--lazy" if !$first;
557
558 push @graphdef, "DEF:${var}-avg=${rrdfile}.${var}:${var}:AVERAGE";
559 push @graphdef, "DEF:${var}-min=${rrdfile}.${var}:${var}:MIN";
560 push @graphdef, "DEF:${var}-max=${rrdfile}.${var}:${var}:MAX";
561 push @graphdef, "DEF:${var}-houravg=${rrdfile}.${var}:${var}:AVERAGE:step=3600";
562 push @graphdef, "LINE1:${var}-avg#FF0000";
563 push @graphdef, "VDEF:cur=${var}-avg,LAST";
564 push @graphdef, 'GPRINT:cur:Current\\: <span foreground="#FF0000">%.2lf</span>\\r';
565
566 my $mtime;
567 $mtime=(stat("${outdir}/${hostname}.${var}.png.work"))[9];
568
569 (my $averages, my $width, my $height) =
570 rrd_graph("${outdir}/${hostname}.${var}.png.work",
571 "-w", "720", @graphdef);
572
573 pop @graphdef;
574 pop @graphdef;
575 pop @graphdef;
576
577 if ($rrd_result) {
578 print "Error while graphing: " . $rrd_result . "\n";
579 } else {
580 my $newmtime=(stat("${outdir}/${hostname}.${var}.png.work"))[9];
581 if ((!defined($mtime)) || ($newmtime != $mtime)) {
582 copy("${outdir}/${hostname}.${var}.png.work", "${outdir}/${hostname}.${var}.png.new");
583 rename("${outdir}/${hostname}.${var}.png.new", "${outdir}/${hostname}.${var}.png");
584 }
585 }
586
587 print HTML "<a href=\"${hostname}.${var}.html\"><img src=\"${hostname}.${var}.png\" width=\"${width}\" height=\"${height}\" border=\"0\"></a><br>\n";
588
589 open (HTML2, ">${outdir}/${hostname}.${var}.html.new");
590 print HTML2 '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="refresh" content="60"/><meta http-equiv="cache-control" content="no-cache"/><meta http-equiv="pragma" content="no-cache"/><meta http_equiv="expires" content="Sat, 26 Jul 1997 05:00:00 GMT"/><title>' . $vars->{$var}->{'name'} . '</title></head>';
591 print HTML2 '<body bgcolor="#ffffff">';
592
593 push @graphdef, "VDEF:min=${var}-min,MINIMUM";
594 push @graphdef, "GPRINT:min:Minimum\\: %.2lf";
595
596 push @graphdef, "VDEF:avg=${var}-avg,AVERAGE";
597 push @graphdef, "GPRINT:avg:Average\\: %.2lf";
598
599 push @graphdef, "VDEF:max=${var}-max,MAXIMUM";
600 push @graphdef, "GPRINT:max:Maximum\\: %.2lf";
601
602 push @graphdef, "VDEF:cur=${var}-avg,LAST";
603 push @graphdef, "GPRINT:cur:Current\\: %.2lf";
604
605 my @dayGraphDef = @graphdef;
606 push @dayGraphDef, @{cfgToGraphDef($graphConfig->{'day'}, ${var}, 24)};
607
608 $mtime=(stat("${outdir}/${hostname}.${var}.long.png.work"))[9];
609 ($averages, $width, $height) =
610 rrd_graph("${outdir}/${hostname}.${var}.long.png.work",
611 "-w", $graphWidth, @dayGraphDef);
612
613 if ($rrd_result) {
614 print "Error while graphing: " . $rrd_result . "\n";
615 } else {
616 my $newmtime=(stat("${outdir}/${hostname}.${var}.long.png.work"))[9];
617 if ((!defined($mtime)) || ($newmtime != $mtime)) {
618 copy("${outdir}/${hostname}.${var}.long.png.work", "${outdir}/${hostname}.${var}.long.png.new");
619 rename("${outdir}/${hostname}.${var}.long.png.new", "${outdir}/${hostname}.${var}.long.png");
620 }
621 }
622
623 print HTML2 "<img src=\"${hostname}.${var}.long.png\" width=\"${width}\" height=\"${height}\"><br>\n";
624
625 $mtime=(stat("${outdir}/${hostname}.${var}.week.png.work"))[9];
626
627 my @weekGraphDef = @graphdef;
628 push @weekGraphDef, @{cfgToGraphDef($graphConfig->{'week'}, ${var}, 24)};
629
630 ($averages, $width, $height) =
631 rrd_graph("${outdir}/${hostname}.${var}.week.png.work",
632 "-w", "$graphWidth", "-e", "now", "-s", "00:00-8d", @weekGraphDef);
633
634 if ($rrd_result) {
635 print "Error while graphing: " . $rrd_result . "\n";
636 } else {
637 my $newmtime=(stat("${outdir}/${hostname}.${var}.week.png.work"))[9];
638 if ((!defined($mtime)) || ($newmtime != $mtime)) {
639 copy("${outdir}/${hostname}.${var}.week.png.work", "${outdir}/${hostname}.${var}.week.png.new");
640 rename("${outdir}/${hostname}.${var}.week.png.new", "${outdir}/${hostname}.${var}.week.png");
641 }
642 }
643
644 print HTML2 "<img src=\"${hostname}.${var}.week.png\" width=\"${width}\" height=\"${height}\"><br>\n";
645
646 $mtime=(stat("${outdir}/${hostname}.${var}.year.png.work"))[9];
647
648 my @yearGraphDef = @graphdef;
649 push @yearGraphDef, @{cfgToGraphDef($graphConfig->{'year'}, ${var}, 3)};
650
651 ($averages, $width, $height) =
652 rrd_graph("${outdir}/${hostname}.${var}.year.png.work",
653 "-w", "$graphWidth", "-e", "00:00", "-s", "end-365d", @yearGraphDef);
654
655 if ($rrd_result) {
656 print "Error while graphing: " . $rrd_result . "\n";
657 } else {
658 my $newmtime=(stat("${outdir}/${hostname}.${var}.year.png.work"))[9];
659 if ((!defined($mtime)) || ($newmtime != $mtime)) {
660 copy("${outdir}/${hostname}.${var}.year.png.work", "${outdir}/${hostname}.${var}.year.png.new");
661 rename("${outdir}/${hostname}.${var}.year.png.new", "${outdir}/${hostname}.${var}.year.png");
662 }
663 }
664
665 print HTML2 "<img src=\"${hostname}.${var}.year.png\" width=\"${width}\" height=\"${height}\"><br>\n";
666
667 print HTML2 "</body></html>\n";
668 close(HTML2);
669 rename("${outdir}/${hostname}.${var}.html.new", "${outdir}/${hostname}.${var}.html");
670 }
671 }
672
673 print HTML "</body></html>\n";
674 print HTML "<br>Generated on: " . localtime(time());
675 print HTML ' by <a href="http://git.zerfleddert.de/cgi-bin/gitweb.cgi/upsgraph">upsgraph</a>.';
676
677 close(HTML);
678
679 rename("${outdir}/index.html.new", "${outdir}/index.html");
680
681 sleep(${step}/2);
682 $first = 0;
683 }
Impressum, Datenschutz