#!/usr/bin/perl # # Does basic round-robin like loadbalancing between some webservers # Questions? < poelwijk[at]mac.com > # # Specify the list of webservers to balance between @SERVERS = qw/webserver1.domain.ext webserver2.domain.ext webserver3.domain.ext/; use IO::Socket; $SIG{CHLD} = sub { wait() }; $ENV{'PATH'}='/bin:/usr/bin'; chomp($hostname = `/bin/hostname`); # Listen on port 80 $sock = IO::Socket::INET->new(Listen => 5, LocalPort => 80, LocalAddr => $hostname, Reuse => 1, Proto => 'tcp'); # First become "nobody" $nobody = (getpwnam('nobody'))[2] || die "nobody does not exist!"; $nogroup = (getgrnam('nogroup'))[2] || die "can't grok nogroup"; ($< ,$() = ($>,$)) = ($nobody,$nogroup); # lose root privileges ($\,$/) = ("\r\n","\r\n\r\n"); # CR/LF on output/input # Go into server mode close STDIN; close STDOUT; close STDERR; # Prefork fork() && fork() && fork() && fork() && exit 0; # Accept connections on the specified port while (my $s = $sock->accept()) { do { $s->close; next; } if fork(); my $incomingrequest = < $s>; redirect($1,$s) if $incomingrequest=~/(?:GET|POST|HEAD|PUT)\s+(\S+)/; $s->flush; undef $s; exit 0; } sub redirect { my ($url,$s) = @_; my $redirecthost = $SERVERS[rand(@SERVERS)]; print $s "HTTP/1.0 301 Moved Temporarily"; print $s "Server: Your loadbalancing service/1.0"; print $s "Location: http://${redirecthost}${url}"; print $s ""; }