aboutsummaryrefslogtreecommitdiff
path: root/contrib/mrtgext.pl
blob: b9e9f6b9799e23157a91dbab323d35e876a80365 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
#!/usr/bin/perl -w
#
#  mrtgext.pl  v0.3
#    (c)2000 Cliff Woolley, Washington and Lee University
#    jwoolley@wlu.edu
#
#  A UNIX counterpart to Jim Drews' MRTG Extension for netware servers
#  Mimics output of mrtgext.nlm using output of various standard UNIX
#  programs (df, uptime, and uname)
#
#  Dependencies:  I make some assumptions about the output format of
#  your df and uptime commands.  If you have nonstandard outputs for
#  any of these, either pick a different command that gives more
#  standard output or modify the script below.  Example: use /usr/bin/bdf
#  on HP-UX instead of /usr/bin/df, because bdf follows the output format
#  I expect while df does not.  This was written on Linux and tested on
#  HP-UX 10.20 (with changes to the subroutines at the bottom of the
#  program to reflect HP's command parameters); similar tweaking could
#  well be required to port this to other platforms.  If you get it
#  working on your platform, please send me any changes you had to
#  make so I can try to incorporate them.
#
#
#  Following is what I expect the programs' outputs to look like:
#  
#  ======= df ========
#  Filesystem           1k-blocks      Used Available Use% Mounted on
#  /dev/sda1              1014696    352708    609612  37% /
#  /dev/sda2              2262544    586712   1559048  27% /apps
#  /dev/sda3              4062912    566544   3286604  15% /share
#  /dev/sr0                651758    651758         0 100% /cdrom
#  ===================
#
#  ===== uptime ======
#  3:17pm  up 15 days,  4:40,  5 users,  load average: 0.12, 0.26, 0.33
#  ===================
#

###############################################################
#  Configuration section
###############################################################

$dfcmd          = "/bin/df 2>/dev/null";
$uptimecmd      = "/usr/bin/uptime";
%customcmds     = ( "PROCS"    => "numprocesses",
                    "ZOMBIES"  => "numzombies",
                    "MEMFREE"  => "memfree",
                    "SWAPUSED" => "swapused",
                    "TCPCONNS" => "tcpconns",
                    "CLIENTS"  => "ipclients" );
                           # These are functions that you can
                           # define and customize for your system.
                           # You probably need to change the provided
                           # subroutines to work on your system (if
                           # not Linux).

$rootfsnickname = "root";  # this is necessary as a kludge to
                           # better match the netware behavior.
                           # if you already have a _filesystem_
                           # mounted as /root, then you'll need
                           # to change this to something else
$DEBUG          = 0;
$recvtimeout    = 30;


###############################################################
#  Program section
###############################################################

require 5.004;

use Sys::Hostname;


$DEBUG = $ARGV[0] unless ($DEBUG);
$SIG{'ALRM'} = sub { exit 1; };

# some things never change
$hostname = hostname;


if ( $DEBUG ) {
    $| = 1;
    print scalar localtime,": mrtgext.pl started\n";
}

# timeout period 
alarm($recvtimeout);
my $items = <STDIN>;
alarm(0);

$items =~ s/[\r\n]//g;
( $DEBUG ) && print scalar localtime,": request: \"$items\"\n";
my @items = split (/\s+/,"$items");
( $DEBUG ) && print scalar localtime,": ",scalar @items," item(s) to process\n";

my $uptime = `$uptimecmd`;
my @df     = grep {/^\//} `$dfcmd`;

my $processed = 1;

foreach $_ (@items) {
    ( $DEBUG ) && print scalar localtime,": processing item #$processed: \"$_\"\n";
    $_ = uc; #convert $_ to upper case
    if    ( /^UTIL1$/ ) {
        $uptime =~ /load average: ([^,]+),/;
        print $1 * 100,"\n";
    }
    elsif ( /^UTIL5$/ ) {
        $uptime =~ /load average: [^,]+, ([^,]+)/;
        print $1 * 100,"\n";
    }
    elsif ( /^UTIL15$/ ) {
        $uptime =~ /load average: [^,]+, [^,]+, ([^,]+)/;
        print $1 * 100,"\n";
    }
    elsif ( /^CONNECT$/ ) {
        $uptime =~ /(\d+) users?,/;
        print "$1\n";
    }
    elsif ( /^NAME$/ ) {
        print "$hostname\n";
    }
    elsif ( /^UPTIME$/ ) {
        $uptime =~ /up (.*),\s+\d+\s+users?,/;
        print "$1\n";
    }
    elsif ( /^VOLUMES$/ ) {
        foreach $dfline (@df) {
            my $volname = (split(/\s+/, "$dfline"))[5];
            $volname =~ s/^\/$/$rootfsnickname/;
            $volname =~ s/^\///;
            $volname =~ s/\//_/g;
            print "$volname\n";
        }
    }
    elsif ( /^VF(\w*)$/ ) {
        my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1";
        foreach $dfline (@df) {
            my @dfline = split(/\s+/, "$dfline");
            if ($dfline[5] =~ /^\/?$volname$/i ) {
                print (($dfline[1]-$dfline[2]) * 1024,"\n");
                goto done;
            }
        }
        ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n";
        print "-1\n";
    }
    elsif ( /^VU(\w*)$/ ) {
        my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1";
        foreach $dfline (@df) {
            my @dfline = split(/\s+/, "$dfline");
            if ($dfline[5] =~ /^\/?$volname$/i ) {
                print ($dfline[2] * 1024,"\n");
                goto done;
            }
        }
        ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n";
        print "-1\n";
    }
    elsif ( /^VS(\w*)$/ ) {
        my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1";
        foreach $dfline (@df) {
            my @dfline = split(/\s+/, "$dfline");
            if ($dfline[5] =~ /^\/?$volname$/i ) {
                print ($dfline[1] * 1024,"\n");
                goto done;
            }
        }
        ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n";
        print "-1\n";
    }
    elsif ( /^VKF(\w*)$/ ) {
        my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1";
        foreach $dfline (@df) {
            my @dfline = split(/\s+/, "$dfline");
            if ($dfline[5] =~ /^\/?$volname$/i ) {
                print (($dfline[1]-$dfline[2]),"\n");
                goto done;
            }
        }
        ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n";
        print "-1\n";
    }
    elsif ( /^VKU(\w*)$/ ) {
        my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1";
        foreach $dfline (@df) {
            my @dfline = split(/\s+/, "$dfline");
            if ($dfline[5] =~ /^\/?$volname$/i ) {
                print ($dfline[2],"\n");
                goto done;
            }
        }
        ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n";
        print "-1\n";
    }
    elsif ( /^VKS(\w*)$/ ) {
        my $volname = ("$1" eq uc("$rootfsnickname")) ? "/" : "$1";
        foreach $dfline (@df) {
            my @dfline = split(/\s+/, "$dfline");
            if ($dfline[5] =~ /^\/?$volname$/i ) {
                print ($dfline[1],"\n");
                goto done;
            }
        }
        ( $DEBUG ) && print scalar localtime,": ERROR: volume not found.\n";
        print "-1\n";
    }
    elsif ( /^ZERO$/ ) {
        print "0\n";
    }
    elsif (exists( $customcmds{"$_"} )) {
        my $cmdsub = "$customcmds{$_}";
        print &$cmdsub."\n";
    }
    else {
        print "-1\n";
    }
    done: $processed++;
}
( $DEBUG ) && print scalar localtime,": done.\n";


###############################################################
#  CUSTOMIZED PROCEDURES
###############################################################

sub numprocesses {

    my $num = `/bin/ps -eaf | /usr/bin/tail -n +2 | /usr/bin/wc -l`;
    chomp ($num);
    $num =~ s/\s+//g;

    $num;
}

sub numzombies {

    my $num = `/bin/ps -afx | /usr/bin/awk '{print \$3}' | /usr/bin/grep Z | /usr/bin/tail -n +2 | /usr/bin/wc -l`;
    chomp ($num);
    $num =~ s/\s+//g;

    $num;
}

sub tcpconns {

    my $num = `/bin/netstat -nt | /usr/bin/tail -n +3 | /usr/bin/wc -l`;
    chomp ($num);
    $num =~ s/\s+//g;

    $num;
}

sub ipclients {

    my $num = `/bin/netstat -nt | /usr/bin/tail -n +3 | /usr/bin/awk '{print \$5}' | /bin/cut -d : -f 1 | /usr/bin/sort -nu | /usr/bin/wc -l`;
    chomp ($num);
    $num =~ s/\s+//g;

    $num;
}

sub memfree {

    open( FP, "/proc/meminfo" );
    my @meminfo = <FP>;
    close(FP);

    #         total:    used:    free:  shared: buffers:  cached:
    # Mem:  994615296 592801792 401813504 91193344 423313408 93118464
    # Swap: 204791808        0 204791808
    my ($total,$free,$buffers,$cache) = (split(/ +/,$meminfo[1]))[1,3,5,6];
    
    int(($free+$buffers+$cache)/$total*100);
}

sub swapused {

    open( FP, "/proc/meminfo" );
    my @meminfo = <FP>;
    close(FP);

    #         total:    used:    free:  shared: buffers:  cached:
    # Mem:  994615296 592424960 402190336 89821184 423313408 93077504
    # Swap: 204791808        0 204791808

    my ($total,$used) = (split(/ +/,$meminfo[2]))[1,2];
    
    int($used/$total*100);
}