Mrtg Config And Perl Script To Monitor Player Coun
Bytor
Join Date: 2002-11-19 Member: 9323Members
Hey all ... I decided I wanted to graph the number of players on my NS server, mainly so I could compare against a graph of CPU load. I know there are other scripts and applications out there to do this, but I tend to enjoy writing stuff myself, and I wanted to keep this really simple. Here's the perl script that spits out current/max players:
<!--c1--></span><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
#!/usr/bin/perl
$| ++;
use strict;
use IO::Socket;
use Fcntl;
## Create new socket object.
my $socket = new IO::Socket::INET (
PeerAddr => '207.44.156.107',
PeerPort => 27015,
Proto => 'udp',
);
die "Could not create socket!\n" if (! $socket);
## Make reads non-blocking.
my $flags = '';
fcntl ($socket, F_GETFL, $flags) or die ("Couldn't get flags for HANDLE: $!\n");
$flags |= O_NONBLOCK;
fcntl ($socket, F_SETFL, $flags) or die ("Couldn't set flags for HANDLE: $!\n");
$socket->send ("\xFF\xFF\xFF\xFFinfo");
my ($buffer, @parts);
while (1) {
sysread ($socket, $buffer, 1024);
if ($buffer) {
@parts = split (//, $buffer);
print ord($parts[-3]);
print "\n";
print ord($parts[-2]);
print "\n";
exit;
}
}
<!--c2--></td></tr></table><span class='postcolor'><!--ec2-->
(Obviously, replace my server IP with yours.
And here's the MRTG config block to create the graph:
<!--c1--></span><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
Target[nsplayers]: `/usr/local/mrtg-2/bin/nsplayers.pl`
MaxBytes[nsplayers]: 100
Title[nsplayers]: # of Players - Server Name Here
YLegend[nsplayers]: Players
Legend1[nsplayers]: Current Players
Legend2[nsplayers]: Maximum Players
LegendI[nsplayers]: Curr:
LegendO[nsplayers]: Max:
Options[nsplayers]: integer,gauge,growright,nobanner,nopercent
ShortLegend[nsplayers]:
<!--c2--></td></tr></table><span class='postcolor'><!--ec2-->
<!--c1--></span><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
#!/usr/bin/perl
$| ++;
use strict;
use IO::Socket;
use Fcntl;
## Create new socket object.
my $socket = new IO::Socket::INET (
PeerAddr => '207.44.156.107',
PeerPort => 27015,
Proto => 'udp',
);
die "Could not create socket!\n" if (! $socket);
## Make reads non-blocking.
my $flags = '';
fcntl ($socket, F_GETFL, $flags) or die ("Couldn't get flags for HANDLE: $!\n");
$flags |= O_NONBLOCK;
fcntl ($socket, F_SETFL, $flags) or die ("Couldn't set flags for HANDLE: $!\n");
$socket->send ("\xFF\xFF\xFF\xFFinfo");
my ($buffer, @parts);
while (1) {
sysread ($socket, $buffer, 1024);
if ($buffer) {
@parts = split (//, $buffer);
print ord($parts[-3]);
print "\n";
print ord($parts[-2]);
print "\n";
exit;
}
}
<!--c2--></td></tr></table><span class='postcolor'><!--ec2-->
(Obviously, replace my server IP with yours.
And here's the MRTG config block to create the graph:
<!--c1--></span><table border='0' align='center' width='95%' cellpadding='3' cellspacing='1'><tr><td><b>CODE</b> </td></tr><tr><td id='CODE'><!--ec1-->
Target[nsplayers]: `/usr/local/mrtg-2/bin/nsplayers.pl`
MaxBytes[nsplayers]: 100
Title[nsplayers]: # of Players - Server Name Here
YLegend[nsplayers]: Players
Legend1[nsplayers]: Current Players
Legend2[nsplayers]: Maximum Players
LegendI[nsplayers]: Curr:
LegendO[nsplayers]: Max:
Options[nsplayers]: integer,gauge,growright,nobanner,nopercent
ShortLegend[nsplayers]:
<!--c2--></td></tr></table><span class='postcolor'><!--ec2-->
Comments
my $flags = '';
<!--c2--></td></tr></table><span class='postcolor'><!--ec2-->
<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
Ya sure that's one quote there and not two? Looks like you're trying to init the variable (an exercise in futility in Perl, really) with an empty string.
Also would this code work for CS or any HL mod for that matter?
Finally, STICKY!
my $flags = '';
<!--c2--></td></tr></table><span class='postcolor'><!--ec2-->
<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
Ya sure that's one quote there and not two? Looks like you're trying to init the variable (an exercise in futility in Perl, really) with an empty string.
Also would this code work for CS or any HL mod for that matter?
Finally, STICKY!<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
That's two single quotes. Without need for variable interpolation, using single quotes is marginally more efficient.
And in perl, you do need to initialize variables if you want to avoid warnings about the use of uninitialized values if you have compiler warnings turned on. It doesn't apply here, but it's a good habit, especially because someone other than the author who is reading the code can tell immediately what the value of the variable is, without having to dig.
And yes, this *should* work with any half-life mod, unless the mod changes the way the basic server info is queried and returned, which I doubt. I've only tested it on an NS server though.
Ah, ok. I know abot interpolation in Perl, just didn't see that it was two singles. As for the initializaton it's just funky for me to see my() used to declare a global variable. For the life of me, though, I cannot remember how to do it properly. Gah, almost 4 months off the job and I'm already forgetting things. :/
Also about 200 times more complex to setup. Took a look at it and for basic things that MRTG can handle (IE, 1-2 stats on a graph) it is far easier to just use MRTG.
BTW, please tell me that isn't some nekkid fat guy holding a knife and a gun slung across his back as your avatar.
ROFL! That is a famous blonde kitten. We know what you think about! <!--emo&:)--><img src='http://www.unknownworlds.com/forums/html/emoticons/smile.gif' border='0' valign='absmiddle' alt='smile.gif'><!--endemo-->
Ah, ok. I know abot interpolation in Perl, just didn't see that it was two singles. As for the initializaton it's just funky for me to see my() used to declare a global variable. For the life of me, though, I cannot remember how to do it properly. Gah, almost 4 months off the job and I'm already forgetting things. :/<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
You can't remember how to do what properly?
my() is used for locally scoped vars. If you want a true global, you can use the "use vars ('whatever')" pragma.
Nope, I haven't played with RRDTool yet ... I've skimmed some of the docs, but that was a while ago. I use MRTG to monitor various things on various servers, so I'm already quite familiar with it. Does RRDTool offer anything that MRTG doesn't, in terms of graphing data series?
my() is used for locally scoped vars. If you want a true global, you can use the "use vars ('whatever')" pragma.<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
Use vars, that's it. I was trying vars. Bleh, far too long.
$flags, $buffer and @parts are all in global space. Of course if you moved $buffer and @parts inside the while() it would have some scope to be local to. <!--emo&:)--><img src='http://www.unknownworlds.com/forums/html/emoticons/smile.gif' border='0' valign='absmiddle' alt='smile.gif'><!--endemo-->
Anyway, it's neither this nor that. Like I said, my perl's rusty as it is and this is all academic anyway. If it works, it works. TIMTOWTDI and all that.
Nope, I haven't played with RRDTool yet ... I've skimmed some of the docs, but that was a while ago. I use MRTG to monitor various things on various servers, so I'm already quite familiar with it. Does RRDTool offer anything that MRTG doesn't, in terms of graphing data series?<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
Last time I checked RRDTool was much more advanced and better configurable. MRTG was intended solely for router traffic, although it can be abused for other things. RRDTool really lets you plot arbitrary graphs. But if MRTG is working, use what works <!--emo&;)--><img src='http://www.unknownworlds.com/forums/html/emoticons/wink.gif' border='0' valign='absmiddle' alt='wink.gif'><!--endemo-->
my() is used for locally scoped vars. If you want a true global, you can use the "use vars ('whatever')" pragma.<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
Use vars, that's it. I was trying vars. Bleh, far too long.
$flags, $buffer and @parts are all in global space. Of course if you moved $buffer and @parts inside the while() it would have some scope to be local to. <!--emo&:)--><img src='http://www.unknownworlds.com/forums/html/emoticons/smile.gif' border='0' valign='absmiddle' alt='smile.gif'><!--endemo-->
Anyway, it's neither this nor that. Like I said, my perl's rusty as it is and this is all academic anyway. If it works, it works. TIMTOWTDI and all that.<!--QuoteEnd--></td></tr></table><span class='postcolor'><!--QuoteEEnd-->
Actually, they aren't global. my() creates a local variable. Because this script is stand-alone and there just isn't much to it, then they are essentially the same as globals. However, if this code was cut-and-pasted to a subroutine, or placed in it's own package, or used in a mod-perl type environment, then the distinction becomes important. (mod-perl wraps it's scripts into subroutines, so proper scoping becomes VERY important.)
True globally-scoped vars are created using explicit package names such as $main::buffer or with the "use vars" pragma. Of course, you'll probably find some perl-purists that would debate that statement as well.
But again, for this script, it's all the same. Poetaytoe, puhtahtoe. <!--emo&:)--><img src='http://www.unknownworlds.com/forums/html/emoticons/smile.gif' border='0' valign='absmiddle' alt='smile.gif'><!--endemo-->
(Edit: damn typos.)
/me thinks PJ washes his car with sandpaper. (Right tool for the job, and all that.)
-------------------------------------------------------------------
Feature Summary:
-Supports Windows 95, NT, Linux, and most Unixes
-Comes with C source code and a binary for Windows
-Supports old Quake (NetQuake), QuakeWorld, Hexen II, HexenWorld, Quake II, Unreal/UT, Turok2, Sin, Half-Life, Shogo, Tribes, Tribes 2, Quake III, BFRIS, Kingpin, Heretic II servers, Soldier of Fortune, and lots more
-Can display all available statistics, including player info and server rules
-Output templates for automatic HTML generation
-Raw display mode for integration with custom server browsers
-Built-in host name cache
-Sort by ping time, game, or both
-More options than you can wiggle a mouse at
--------------------------------------------------------------------
And Its used by many other server reporting aplications. So its worth the install regardless of use. But thats what I use for mrtg players connection graphing. Useing the following mrtg line. Plus a small file.
mrtg line:
Target[players]: `/usr/bin/./qstat -Ts /etc/mrtg/playersT -hls 209.135.103.40:27015 -P`
playersT file:
$(IF:UP)$\
$TOTALPLAYERS
$TOTALPLAYERS
0
0
$(ENDIF)$\
$(IF:DOWN)$\
0
0
0
0
$(ENDIF)$\
EDIT:
Ops, forgot to add its page url . <a href='http://www.qstat.org/' target='_blank'>http://www.qstat.org/</a>
I won't even go into why halfd is overkill ... it's obvious.
And Darien, you know from our conversation that I'm not installing halfd because I don't like installing third party apps. I use lots of third party apps, including qstat (to drive a server monitoring program I made for Tribes 2.) I'm not installing halfd at this time because I don't need it.