I was having some rare intermittent problems with Apache httpd talking to Tomcat.
I needed to determining if either the mod_jk in httpd or the Tomcat AJP connector was misbehaving. I did not easily find a script that performed an AJP ping. Therefore, I had to write one.
This is my first working version. The expected scalar is not used at this time. It is mainly there for documentation. Also, I probably won't remove the debug logging until it starts annoying me.
I stuck this on my tech blog, too.
http://it-nonwhizzos.blogspot.com/2009/05/ajp-ping-in-perl.html
Thanks.
#!/usr/bin/perl -w
use warnings;
use strict;
use Socket;
my ($remote, $port) = split /:/, shift @ARGV, 2;
if (! $remote) {
$remote = 'localhost';
}
print "remote = $remote\n";
if (! $port) {
$port = 8009;
}
print "port = $port\n";
my ($iaddr, $paddr, $proto);
# If the port has anything other than numbers, we're assuming it is an
# /etc/services name.
if ($port =~ /\D/) {
$port = getservbyname $port, 'tcp' ;
}
die "Bad port, stopped" unless $port;
print "port = $port\n";
$iaddr = inet_aton($remote) || die "No host: $remote, stopped";
print "iaddr = $iaddr\n";
$paddr = sockaddr_in($port, $iaddr) || die "sockaddr: $!, stopped";
print "paddr = $paddr\n";
# Grab the number for TCP out of /etc/protocols.
$proto = getprotobyname 'tcp' ;
print "proto = $proto\n";
my $sock;
# PF_INET and SOCK_STREAM are constants imported by the Socket module.
+ They
# are the same as what is defined in sys/socket.h.
socket $sock, PF_INET, SOCK_STREAM, $proto || die "socket: $!, stopped
+";
print "sock = $sock\n";
print "BEFORE CONNECT\n";
connect $sock, $paddr || die "connect: $!, stopped";
print "AFTER CONNECT\n";
# This is the ping packet. For detailed documentation, see
# http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
# I stole the exact byte sequence from
# http://sourceforge.net/project/shownotes.php?group_id=128058&release
+_id=438456
# instead of fully understanding the packet structure.
my $ping = pack 'C5' # Format template.
, 0x12, 0x34 # Magic number for server->container packets.
, 0x00, 0x01 # 2 byte int length of payload.
, 0x0A # Type of packet. 10 = CPing.
;
my @ping_values = unpack 'C5', $ping;
print "ping_values = " , join ' ', @ping_values , "\n";
# This is the expected pong packet. That is, this is what Tomcat send
+s back
# to indicate that it is operating OK.
my $expected = pack 'C5' # Format template.
, 0x41, 0x42 # Magic number for container->server packe
+ts.
, 0x00, 0x01 # 2 byte int length of payload.
, 0x09 # Type of packet. 9 = CPong reply.
;
syswrite $sock, $ping || die "syswrite: $!, stopped";
my $pong;
$pong = 'empty';
print "BEFORE READ\n";
sysread $sock, $pong, 5 || die "read: $!, stopped";
print "AFTER READ\n";
my @pong_values = unpack 'C5', $pong;
print "pong_values = " , join ' ', @pong_values , "\n";
close $sock || die "close: $!, stopped";
exit 0;
The following is an example of a good ping response.
me@mybox:~/ajp_ping
$ time ./ajp_ping.pl localhost:8009
remote = localhost
port = 8009
port = 8009
iaddr =
paddr =
proto = 6
sock = GLOB(0x506290)
BEFORE CONNECT
AFTER CONNECT
ping_values = 18 52 0 1 10
BEFORE READ
AFTER READ
pong_values = 65 66 0 1 9
real 0m0.028s
user 0m0.015s
sys 0m0.013s
In reply to AJP ping
by jffry
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.