3
# Script to update the RRD-files with current information.
5
# $Id: munin-update.in,v 1.8 2004/05/09 21:11:16 jimmyo Exp $
7
# $Log: munin-update.in,v $
8
# Revision 1.8 2004/05/09 21:11:16 jimmyo
9
# New plugin (pm3users) and a bunch of patches from Jacques Caruso.
11
# Revision 1.7 2004/02/10 19:27:02 jimmyo
12
# Munin-update now properly ignores nodes with "update no".
14
# Revision 1.6 2004/01/30 14:28:19 jimmyo
15
# More timeouts in munin-update (Deb#222674).
17
# Revision 1.5 2004/01/29 18:19:58 jimmyo
18
# Made Munin compatible with perl 5.005_03 (patch by Lupe Christoph) (SF#884622)
20
# Revision 1.4 2004/01/29 17:40:10 jimmyo
21
# Fixed pod typos patched by Lupe Christoph (SF#884092)
23
# Revision 1.3 2004/01/29 17:34:06 jimmyo
24
# Updated copyright information
26
# Revision 1.2 2004/01/15 15:20:01 jimmyo
27
# Making things workable after name change. Upping for test verwion.
29
# Revision 1.1 2004/01/02 18:50:01 jimmyo
30
# Renamed occurrances of lrrd -> munin
32
# Revision 1.1.1.1 2004/01/02 15:18:08 jimmyo
33
# Import of LRRD CVS tree after renaming to Munin
35
# Revision 1.35 2003/12/19 20:53:17 jimmyo
38
# Revision 1.34 2003/12/12 21:40:34 jimmyo
41
# Revision 1.33 2003/12/12 19:23:59 jimmyo
42
# Fix bug with timeout handling of children.
44
# Revision 1.32 2003/12/06 20:21:53 jimmyo
45
# Removed forgotten debug info
47
# Revision 1.31 2003/12/06 20:09:17 jimmyo
48
# Better handling of dying children and timeouts. (Deb#222674)
50
# Revision 1.30 2003/12/06 19:12:57 jimmyo
51
# Added max_processes config variable. Also, removed zombie-generation code. :-P
53
# Revision 1.29 2003/11/15 11:10:29 jimmyo
56
# Revision 1.28 2003/11/12 12:04:45 jimmyo
57
# Make sure extinfo comes accross
59
# Revision 1.27 2003/11/07 23:39:09 jimmyo
60
# Filter out illegal chars
62
# Revision 1.26 2003/11/07 22:10:13 jimmyo
63
# Changed use_default_name -> use_node_name. Better name.
65
# Revision 1.25 2003/11/07 21:02:24 jimmyo
66
# Bugfix when a new node is unreachable.
68
# Revision 1.24 2003/11/07 20:46:12 jimmyo
69
# Only require Config::General if using old config format.
71
# Revision 1.23 2003/11/07 17:43:16 jimmyo
72
# Cleanups and log entries
84
use POSIX qw(strftime);
85
use POSIX ":sys_wait_h";
86
use Storable qw(fd_retrieve nstore_fd);
89
my $VERSION="@@VERSION@@";
90
my $serversocket = "munin-server-socket.$$";
91
my $conffile = "@@CONFDIR@@/munin.conf";
95
my @limit_services = ();
96
my $update_time= Time::HiRes::time;
102
my $print_stdout = 0;
106
GetOptions ( "host=s" => \@limit_hosts,
107
"force-root!" => \$force_root,
108
"service=s" => \@limit_services,
109
"config=s" => \$conffile,
111
"version!" => \$do_version,
112
"fork!" => \$cli_do_fork,
113
"timeout=i" => \$cli_timeout,
114
"stdout!" => \$print_stdout,
115
"help" => \$do_usage );
119
print "Usage: $0 [options]
122
--[no]force-root Force running, even as root. [--noforce-root]
123
--version View version information.
124
--help View this message.
125
--service <service> Limit graphed services to <service>. Multiple --service
126
options may be supplied.
127
--host <host> Limit graphed hosts to <host>. Multiple --host options
129
--config <file> Use <file> as configuration file.
130
[@@CONFDIR@@/munin.conf]
131
--[no]debug View debug messages. [--nodebug]
132
--[no]fork Don't fork one instance for each host. [--fork]
133
--[no]stdout Print log messages to stdout as well. [--nostdout]
134
--timeout=<seconds> TCP timeout when talking to clients. [$timeout]
142
print "munin-update version $VERSION.\n";
143
print "Written by Audun Ytterdal, Jimmy Olsen, Tore Anderson / Linpro AS\n";
145
print "Copyright (C) 2002-2004\n";
146
print "This is free software released under the GNU Public License. There is NO\n";
147
print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
151
if ($> == 0 and !$force_root)
153
print "You are running this program as root, which is neither smart nor necessary.
154
If you really want to run it as root, use the --force-root option. Else, run
155
it as the user \"munin\". Aborting.\n\n";
159
my $config= &munin_readconfig ($conffile);
163
if (-e "$config->{dbdir}/datafile") {
164
$oldconfig= &munin_readconfig("$config->{dbdir}/datafile", 1, 1);
167
# CLI parameters override the configuration file.
168
if (defined $cli_timeout)
170
$timeout = $cli_timeout;
172
elsif (exists $config->{'timeout'})
174
$timeout = $config->{'timeout'};
176
if (defined $cli_do_fork)
178
$do_fork = $cli_do_fork;
180
elsif (exists $config->{'fork'})
182
$do_fork = ($config->{'fork'} =~ /yes/i ? 1 : 0);
185
if (! -d $config->{rundir})
187
mkdir ($config->{rundir}, 0700);
189
munin_runlock("$config->{rundir}/munin-update.lock");
191
open (LOG,">>$config->{logdir}/munin-update.log") or die "Unable to open $config->{logdir}/munin-update.log\n";
193
open (STATS,">$config->{dbdir}/munin-update.stats.tmp") or logger("Unable to open $config->{datadir}/munin-update.stats");
202
$uaddr = sockaddr_un("$config->{rundir}/$serversocket");
203
socket (Server, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
204
unlink ("$config->{'rundir'}/$serversocket");
205
bind (Server, $uaddr);
206
chmod (0700, "$config->{rundir}/$serversocket");
207
listen (Server, SOMAXCONN);
210
logger("Starting munin-update");
213
for my $key (keys %{$config->{domain}}) {
214
my $domain_time = Time::HiRes::time;
215
logger ("Processing domain: $key");
216
process_domain($key);
217
$domain_time = sprintf ("%.2f",(Time::HiRes::time - $domain_time));
218
print STATS "UD|$key|$domain_time\n";
219
logger ("Processed domain: $key ($domain_time sec)");
225
# while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
226
# logger ("reaped $waitedpid" . ($? ? " with exit $?" : ''));
228
# $SIG{CHLD} = \&REAPER; # loathe sysV
231
#$SIG{CHLD} = \&REAPER;
235
$SIG{ALRM} = sub { die "Timed out waiting for children. $!\n"};
238
for (;(%children - $bad_procs > 0);)
242
foreach my $key (keys %children)
244
if (waitpid ($key, WNOHANG) != 0)
246
my $domain = $children{$key}->[0];
247
my $name = $children{$key}->[1];
248
my $oldnode = $children{$key}->[3];
250
logger ("Child has unexpectedly died: $domain -> $name.");
251
delete $children{$key};
252
use_old_config ($domain, $name, $oldnode);
259
accept (Client, Server);
264
if (@queue and defined $config->{max_processes} and
265
$config->{max_processes})
267
while (keys %children < ($config->{max_processes}-1-$bad_procs))
269
my $args = pop @queue;
270
logger ("de-queueing new connection: $args->[1]");
271
do_node($args->[0], $args->[1], $args->[2], $args->[3]);
277
open (STDIN, "<&Client") || die "can't dup client to stdin";
284
$tmpref = fd_retrieve (\*STDIN);
289
logger ("Error communicating with process: $@");
293
($pid, $domain, $name) = ($tmpref->[0], $tmpref->[1], $tmpref->[2]);
294
logger ("connection from $domain -> $name ($pid)");
297
$config->{domain}->{$domain}->{node}->{$name} = fd_retrieve (\*STDIN);
301
logger ("Error during fd_retrieve of config: $@");
303
my $domain = $children{$pid}->[0];
304
my $name = $children{$pid}->[1];
305
my $oldnode = $children{$pid}->[3];
307
use_old_config ($domain, $name, $oldnode);
309
delete $children{$pid};
311
logger ("connection from $domain -> $name ($pid) closed");
313
if (@queue and defined $config->{max_processes} and
314
$config->{max_processes} and
315
keys %children < ($config->{max_processes}-1-$bad_procs))
317
my $args = pop @queue;
318
logger ("de-queueing new connection: $args->[1]");
319
do_node($args->[0], $args->[1], $args->[2], $args->[3]);
326
if ($bad_procs) # Use old configuration for killed children
328
foreach my $key (keys %children)
330
my $domain = $children{$key}->[0];
331
my $name = $children{$key}->[1];
332
my $node = $children{$key}->[2];
333
my $oldnode = $children{$key}->[3];
335
use_old_config ($domain, $name, $oldnode);
336
logger ("Attempting to use old configuration for $domain -> $name.");
340
unlink ("$config->{rundir}/$serversocket");
342
my $overwrite = &munin_readconfig($conffile);
343
$config = &munin_overwrite($config,$overwrite);
345
if (&munin_getlock("$config->{rundir}/munin-datafile.lock"))
347
&munin_writeconfig("$config->{dbdir}/datafile",$config);
351
warn "Could not create lockfile \"$config->{rundir}/munin-update.lock\"";
354
$update_time = sprintf ("%.2f",(Time::HiRes::time - $update_time));
355
print STATS "UT|$update_time\n";
357
rename ("$config->{dbdir}/munin-update.stats.tmp", "$config->{dbdir}/munin-update.stats");
359
logger("Munin-update finished ($update_time sec)");
364
for my $key ( keys %{$config->{domain}->{$domain}->{node}}) {
365
if (@limit_hosts and !grep (/^$key$/, @limit_hosts))
367
print "Skipping host \"$key\" - not in hostlist\n" if $DEBUG;
370
if (defined $config->{max_processes} and $config->{max_processes} and
371
($config->{max_processes}-1-$bad_procs) < keys %children)
373
push (@queue, [$domain, $key, $config->{domain}->{$domain}->{node}->{$key},$oldconfig->{domain}->{$domain}->{node}->{$key}]);
377
do_node($domain,$key ,$config->{domain}->{$domain}->{node}->{$key},$oldconfig->{domain}->{$domain}->{node}->{$key});
383
my ($domain, $name, $config, $oldconfig) = @_;
384
my $node_time = Time::HiRes::time;
385
logger("Processing node: $name");
386
process_node($domain,$name ,$config,$oldconfig);
387
$node_time = sprintf ("%.2f",(Time::HiRes::time - $node_time));
388
print STATS "UN|$domain|$name|$node_time\n";
389
logger ("Processed node: $name ($node_time sec)");
393
my ($domain,$name,$node,$oldnode) = @_;
394
return if (exists ($node->{fetch_data}) and !$node->{fetch_data});
395
return if (exists ($node->{update}) and $node->{update} ne "yes");
402
{ # Something went wrong
403
warn "cannot fork: $!";
407
$children{$pid} = [$domain, $name, $node, $oldnode];
409
} # else I'm the child -- go spawn
414
# First we get lock...
415
unless (&munin_getlock("$config->{rundir}/munin-$domain-$name.lock"))
417
logger ("Could not get lock for $node -> $name. Skipping node.");
419
{ # Send the old config to the server before we die
420
socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
421
connect (SOCK, sockaddr_un ("$config->{rundir}/$serversocket")) || die "connect: $!";
423
$config->{domain}->{$domain}->{node}->{$name} = $oldnode;
424
alarm (0); # Don't want to interrupt this.
425
my @tmp = ($$, $domain, $name);
426
nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!";
427
nstore_fd \%{$config->{domain}->{$domain}->{node}->{$name}}, \*SOCK;
438
my $socket = new IO::Socket::INET ('PeerAddr' => "$node->{address}:".
439
($node->{port} || $config->{domain}->{$domain}->{port} ||
440
$config->{port} || "4949"),
441
'Proto' => "tcp", "Timeout" => $timeout);
442
my $err = ($socket ? "" : $!);
446
$SIG{ALRM} = sub { close $socket; die "$!\n"};
449
my @tmp = ($$, $domain, $name);
452
logger ("Could not connect to $name($node->{address}): $err - Attempting to use old configuration");
453
# If we can't reach the client. Using old Configuration.
455
$config->{domain}->{$domain}->{node}->{$name} = $oldnode;
456
alarm (0); # Don't want to interrupt this.
457
socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
458
connect (SOCK, sockaddr_un ("$config->{rundir}/$serversocket")) || die "connect: $!";
459
nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!";
460
nstore_fd \%{$config->{domain}->{$domain}->{node}->{$name}}, \*SOCK;
465
{ # Well, we'll have to give _something_ to the server, or it'll time out.
466
socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
467
connect (SOCK, sockaddr_un ("$config->{rundir}/$serversocket")) || die "connect: $!";
468
nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!";
469
nstore_fd ({}, \*SOCK);
472
if (!&config_node($domain,$name,$node,$oldnode,$socket))
474
$config->{domain}->{$domain}->{node}->{$name} = $oldnode;
475
socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
476
connect (SOCK, sockaddr_un ("$config->{rundir}/$serversocket")) || die "connect: $!";
477
nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!";
478
nstore_fd \%{$config->{domain}->{$domain}->{node}->{$name}}, \*SOCK;
482
&fetch_node($domain,$name,$node,$socket);
484
alarm (0); # Don't want to interrupt this.
485
socket (SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
486
connect (SOCK, sockaddr_un ("$config->{rundir}/$serversocket")) || die "connect: $!";
487
nstore_fd \@tmp, \*SOCK || die "Could not nstore_fd: $!";
488
nstore_fd \%{$config->{domain}->{$domain}->{node}->{$name}}, \*SOCK;
498
logger ("Could not connect to $name($node->{address}): $err\nAttempting to use old configuration");
499
# If we can't reach the client. Using old Configuration.
501
$config->{domain}->{$domain}->{node}->{$name} = $oldnode;
504
next unless (&config_node($domain,$name,$node,$oldnode,$socket));
505
&fetch_node($domain,$name,$node,$socket);
512
sub read_socket_single {
517
local $SIG{ALRM} = sub { $timed_out=1; close $socket; die "$!\n"};
525
logger ("Socket read timed out: $@\n");
537
local $SIG{ALRM} = sub { $timed_out=1; close $socket; die "$!\n"};
548
logger ("Socket read timed out: $@\n");
555
my ($domain,$name,$node,$oldnode,$socket) = @_;
556
my $clientdomain = read_socket_single ($socket);
558
chomp($clientdomain) if $clientdomain;
559
if (!$clientdomain) {
560
logger("Got unknown reply from client: '$clientdomain' skipping");
563
$clientdomain =~ s/\#.*(?:lrrd|munins) (?:client|node) at //;
564
if (exists $node->{'use_node_name'} and $node->{'use_node_name'} =~ /^\s*y(?:es)\s*$/i)
566
$fetchdomain = $clientdomain;
568
elsif (exists $node->{'use_default_name'} and $node->{'use_default_name'} =~ /^\s*y(?:es)\s*$/i)
570
$fetchdomain = $clientdomain;
574
$fetchdomain = $name;
576
my $nodeconf_time = Time::HiRes::time;
577
logger("Configuring node: $name") if $DEBUG;
580
local $SIG{ALRM} = sub { die "Could not run list on $name ($fetchdomain): $!\n"};
581
alarm 5; # Should be enough to check the list
582
print $socket "list $fetchdomain\n";
583
my $list = <$socket>;
585
@services = split / /,$list;
589
die unless ($@ =~ m/Could not run list/);
590
logger ("Could not get list from $node->{address}: $!\nAttempting to use old configuration");
592
$config->{domain}->{$domain}->{node}->{$name} = $oldnode;
597
for my $service (@services) {
598
my $servname = $service;
599
$servname =~ s/\W/_/g;
600
next if (exists ($node->{client}->{$servname}->{fetch_data}) and
601
$node->{client}->{$servname}->{fetch_data} == 0);
602
next if (exists ($node->{client}->{$servname}->{update}) and
603
!$node->{client}->{$servname}->{update} eq "yes");
604
next if (@limit_services and !grep (/^$servname$/, @limit_services));
605
my @graph_order = (exists $node->{client}->{$servname}->{graph_order} ?
606
split (/\s+/, $node->{client}->{$servname}->{graph_order}) : ());
607
my $serviceconf_time = Time::HiRes::time;
608
if ($servname ne $service)
610
$node->{client}->{$servname}->{realservname} = $service;
612
logger("Configuring service: $name->$servname") if $DEBUG;
613
print $socket "config $service\n";
614
my @lines = read_socket($socket);
615
return unless $socket;
616
next unless (@lines);
619
logger("Client reported timeout in configuration of $servname");
620
if ($oldnode->{client}->{$servname}) {
621
logger("Attempting to use old configuration");
622
$config->{domain}->{$domain}->{node}->{$name}->{client}->{$servname} = $oldnode->{client}->{$servname};
624
logger("Skipping configuration of $servname");
625
delete $node->{client}->{$servname};
628
elsif (/^(\w+)\.(\w+)\s+(.+)/) {
629
my ($client,$type,$value) = ($1,$2,$3);
630
$client = substr ($client,-18);
631
$node->{client}->{$servname}->{$client.".".$type} = "$value";
632
logger ("config: $name->$client.$type = $value") if $DEBUG;
633
if ($type eq "label") {
634
push (@graph_order,$client)
635
unless grep (/^$client$/, @graph_order);
637
} elsif (/(^[^\s\#]+)\s+(.+)/) {
640
$node->{client}->{$servname}->{$keyword} = $value;
641
logger ("Config: $keyword = $value") if $DEBUG;
642
if ($keyword eq "graph_order") {
643
@graph_order = split (/\s+/, $node->{client}->{$servname}->{graph_order});
647
for my $subservice (keys %{$node->{client}->{$servname}}) {
648
my ($client,$type) = split /\./,$subservice;
649
my ($value) = $node->{client}->{$servname}->{$subservice};
650
if ($type eq "label") {
651
my $fname = "$config->{dbdir}/$domain/$name-$servname-$client-" .
652
lc substr (($node->{client}->{$servname}->{"$client.type"}||"GAUGE"),0,1).
655
logger ("creating rrd-file for $servname->$subservice");
656
mkdir "$config->{dbdir}/$domain/",0777;
657
RRDs::create ("$fname",
658
"DS:42:".($node->{client}->{$servname}->{"$client.type"} || "GAUGE").":600:".
659
(defined $node->{client}->{$servname}->{"$client.min"} ?
660
$node->{client}->{$servname}->{"$client.min"} :
661
"U") . ":" . ($node->{client}->{$servname}->{"$client.max"} || "U"),
662
"RRA:AVERAGE:0.5:1:576",
665
"RRA:AVERAGE:0.5:6:432", # 9 days
668
"RRA:AVERAGE:0.5:24:540", # 45 days
669
"RRA:MIN:0.5:24:540",
670
"RRA:MAX:0.5:24:540",
671
"RRA:AVERAGE:0.5:288:450", # 450 days
672
"RRA:MIN:0.5:288:450",
673
"RRA:MAX:0.5:288:450");
674
if (my $ERROR = RRDs::error) {
675
logger ("Unable to create \"$fname\": $ERROR");
679
$node->{client}->{$servname}->{graph_order} = join(' ',@graph_order);
681
$serviceconf_time = sprintf ("%.2f",(Time::HiRes::time - $serviceconf_time));
682
print STATS "CS|$domain|$name|$servname|$serviceconf_time\n";
683
logger ("Configured service: $name -> $servname ($serviceconf_time sec)");
685
$nodeconf_time = sprintf ("%.2f",(Time::HiRes::time - $nodeconf_time));
686
print STATS "CN|$domain|$name|$nodeconf_time\n";
687
logger("Configured node: $name ($nodeconf_time sec)");
692
my ($domain,$name,$node,$socket) = @_;
693
my $nodefetch_time = Time::HiRes::time;
694
logger("Fetching node: $name") if $DEBUG;
695
for my $service (keys %{$node->{client}}) {
696
my $servicefetch_time = Time::HiRes::time;
697
logger("Fetching service: $name->$service") if $DEBUG;
698
next if (exists ($node->{client}->{$service}->{fetch_data}) and
699
$node->{client}->{$service}->{fetch_data} == 0);
700
next if (exists ($node->{client}->{$service}->{update}) and
701
!$node->{client}->{$service}->{update} eq "yes");
702
next if (@limit_services and !grep (/^$service$/, @limit_services));
703
my $realservname = $node->{client}->{$service}->{realservname} || $service;
704
delete $node->{client}->{$service}->{realservname}
705
if exists $node->{client}->{$service}->{realservname};
706
print $socket "fetch $realservname\n";
707
my @lines = &read_socket($socket);
708
return unless $socket;
711
logger("Client reported timeout in fetching of $service");
713
elsif (/(\w+)\.value\s+(.+)/) {
717
$key = substr($key,-18);
718
my $fname = "$config->{dbdir}/$domain/$name-$service-$key-".
719
lc substr (($node->{client}->{$service}->{$key.".type"}||"GAUGE"),0,1).
721
logger("Updating $fname with $value") if $DEBUG;
722
RRDs::update ("$fname", "N:$value");
723
if (my $ERROR = RRDs::error) {
724
logger ("Unable to update $fname: $ERROR");
727
elsif (/(\w+)\.extinfo\s+(.+)/) {
728
$config->{domain}->{$domain}->{node}->{$name}->{client}->{$service}->{$1.".extinfo"} = $2;
731
$servicefetch_time = sprintf ("%.2f",(Time::HiRes::time - $servicefetch_time));
732
logger ("Fetched service: $name -> $service ($servicefetch_time sec)");
733
print STATS "FS|$domain|$name|$service|$servicefetch_time\n";
735
$nodefetch_time = sprintf ("%.2f",(Time::HiRes::time - $nodefetch_time));
736
logger ("Fetched node: $name ($nodefetch_time sec)");
737
print STATS "FN|$domain|$name|$nodefetch_time\n";
746
$config->{domain}->{$domain}->{node}->{$name} = $oldnode;
747
logger ("Attempting to use old configuration for $domain -> $name.");
754
my $now = strftime "%b %d %H:%M:%S", localtime;
755
print ("$now - $$: $comment\n") if $print_stdout;
756
print LOG ("$now - $$: $comment\n");
766
munin-update - A program to gather data from machines running munin-node
770
munin-update [options]
776
=item B<< --[no]force-root >>
778
Force running as root (stupid and unnecessary). [--noforce-root]
780
=item B<< --service <service> >>
782
Limit fetched data to those of E<lt>serviceE<gt>. Multiple --service options may be supplied. [unset]
784
=item B<< --host <host> >>
786
Limit fetched data to those from E<lt>host<gt>. Multiple --host options may be supplied. [unset]
788
=item B<< --config <file> >>
790
Use E<lt>fileE<gt> as configuration file. [@@CONFDIR@@/munin.conf]
796
=item B<< --[no]debug >>
798
If set, view debug messages. [--nodebug]
800
=item B<< --[no]fork >>
802
If set, will fork off one process for each host. [--fork]
804
=item B<< --[no]stdout >>
806
If set, will print log messages to stdout as well as syslog. [--nostdout]
808
=item B<< --timeout <seconds> >>
810
Set the network timeout to <seconds>. [180]
816
Munin-update is a part of the package Munin, which is used in
817
combination with Munin's node. Munin is a group of programs to gather
818
data from Munin's nodes, graph them, create html-pages, and optionally
819
warn Nagios about any off-limit values.
821
Munin-update does the gathering. It is usually only used from within
824
It contacts each host's munin-node in turn, gathers data from it, and
825
stores them in .rrd-files. If necessary, it will create the rrd-files
826
and the directories to store them in.
830
@@CONFDIR@@/munin.conf
832
@@LOGDIR@@/munin-update
837
This is munin-update version @@VERSION@@
841
Audun Ytterdal and Jimmy Olsen.
845
munin-update does, as of now, not check the syntax of the configuration file.
847
Please report other bugs in the bug tracker at L<http://munin.sf.net/>.
851
Copyright � 2002-2004 Audun Ytterdal, Jimmy Olsen, and Tore Anderson / Linpro AS.
853
This is free software; see the source for copying conditions. There is
854
NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
857
This program is released under the GNU General Public License