This is what I have now. Not completely as I want it, but didn't want to have you wait any longer
This is the sample virtual hosts configuration file I used:
Code:
$cat virt_orig.txt
# start of virtual hosts
<VirtualHost 11.11.11.11:80>
ServerName kpn.com
ServerAlias www.kpn.com
</VirtualHost>
# a remark preceded by an empty line
<VirtualHost 22.22.22.22:80>
# ServerName fish.org
ServerName gorilla.org
ServerAlias www.gorilla.org
</VirtualHost>
# another remark followed by an empty line
<VirtualHost 33.33.33.33:8080>
# --- home of the monkeys
ServerName monkey.org
ServerAlias www.monkey.org
ServerAdmin webmaster@monkey.org
</VirtualHost>
<VirtualHost 4.4.4.4:8080>
#
# Our forum
#
ServerName daemonforums.org
ServerAlias www.daemonforum.org
ServerAdmin webmaster@monkey.org
</VirtualHost>
You first run the
dig-them script (see my previous posts) to extract the servernames and lookup the corresponding IP address
Code:
$ ./dig-them virt_orig.txt
kpn.com=145.7.192.133
gorilla.org=128.121.215.221
monkey.org=152.160.49.201
daemonforums.org=67.205.67.40
This produces the current domain -> IP address mappings.
The perl script, I called it 'virt-update', will read a file called 'domain-addr.txt' and expects this format. To create this file
Code:
$ ./dig-them virt_orig.txt >domain-addr.txt
The name 'domain-addr.txt' is still hard-coded in the 'virt-update' perl script, but that could be changed
Now you can run the following perl script:
Code:
#!/usr/bin/perl -w
# $Id: virt-update,v 1.4 2008/11/24 01:47:17 j65nko Exp $
# Copyright (c) 2008 J65nko <Administrator daemonforums.org>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
use strict ;
my @section ; # <VirtualHost> ... </VirtualHost> section
my %address ; # hash with domain -> IP mappings
my $debug ;
sub parse ;
sub process_section ;
sub show ;
sub get_ServerName ;
sub write_section ;
sub write_rejects ;
sub parse {
my $i = -1 ; # first element of array is array[0], and we use ++$i
while (<>) {
if ( /^\s*<VirtualHost/ .. /^\s*<\/VirtualHost>/ ) {
$section[++$i] = $_ ; # store line in array @section
#print "Storing: $_" ;
if ( /^\s*<\/VirtualHost>/ ) { # complete section stored?
process_section ;
$#section = 0 ; # empty @section array
$i = -1 ; # init index
}
next ;
}
#print "\nPassing through unprocessed: $_" ;
print RESULT ; # simply pass through non-section lines
} # end while
} # end sub
sub process_section {
my $domain ;
my $ip ;
my $port ;
$domain = get_ServerName ; # scan @section for Servername
if ( $domain eq "" ) { die 'Panic: No ServerName directive' ; }
# we didn't die so there is life after a Servername ...
print " (Extracted domain name = [$domain] )" ;
if ( not exists $address{$domain} ) { # domain -> addr mapping?
print "\nNo IP address known for $domain\n" .
"Following section rejected" ;
show ;
unshift @section, "# NOT UPDATED because of unresolvable domain name\n" ;
write_rejects ; # write section to rejected file
write_section ; # but still write to output file
return ;
}
# $section[0] is first element of opening '<Virtualhost 1.2.3.4:80>'
if ( $section[0] =~ m/^\s*<VirtualHost\s+(\d+\.\d+\.\d+.\d+)(:\d+)?\s*>/ ) {
$ip = $1 ;
$port = $2 ;
if ( $debug == 1 ) {
print "\nProcessing: $section[0]" ;
print " ( Extracted IP number: $ip )" ;
print " Port number = $port " ;
}
if ( $ip eq $address{$domain} ) {
if ( $debug == 1 ) {
print "\n======= No change for $domain at $ip ======" ;
#show ;
#print "\n======= end of unchanged section ==========" ;
}
write_section ;
return ;
}
else {
print "\nChanging $ip -> $address{$domain}" ;
$section[0] =~ s/\d+\.\d+\.\d+\.\d+(:\d+)?/$address{$domain}$port/ ;
print "\nResult: $section[0]" ;
write_section ;
}
} else { die "Panic: Aborting processing ... No <VirtualHost> entry found!" ; }
} # end sub process_section
# scan @section array for ServerName directive
sub get_ServerName {
if ( $debug == 1 ) { print "\nScanning section for ServerName\n" ; }
for (@section) {
print "$_" ;
if ( /^\s*ServerName\s+(\S+)$/ ) {
if ($debug == 1 ) { print "Processing : $_" ; }
return $1 ;
}
}
}
# --- read "domain -> IPaddr" mappings file and store in hash table %address
sub get_mapping {
my ($domain, $ip ) ;
my $file = 'domain-addr.txt' ;
open ( FILE, "< $file" ) or die "Cannot open $file" ;
while ( <FILE> ) {
chomp ; # get rid of LF
($domain, $ip) = split /=/ ;
#print "\nDomain: [$domain] IP: [$ip]" ;
if ( $ip eq "" ) {
print "\nDomain $domain has no IP address. Skipping $domain ..." ;
next ;
}
$address{$domain} = $ip ;
}
}
sub show {
for (@section) {
print "\n--$_" ;
}
}
sub write_section {
for (@section) {
print RESULT ; # print implied $_
}
}
sub write_rejects {
for (@section) {
print REJECT ; # print implied $_
}
}
# --- main
get_mapping ; # read file 'domain-addr.txt' into %address hash
open ( RESULT, "> virt_updated.txt" ) or die "Cannot open updated.txt!" ;
open ( REJECT, "> virt_rejects.txt" ) or die "Cannot open updated.txt!" ;
# output (only to see synchronized debugging messages)
$debug = 1 ;
if ( $debug == 1 ) {
$| = 1 ; # enable autoflush for synced debugging stuff
}
parse ;
print <<EOF ;
---- Message
Updated file : virt_updated.txt
A copy of unmodified sections because of unknown IP address : virt_rejects.txt
To see the differences run
diff -u name_of_original_file virt_updated.txt
--- End of message
EOF
END { close RESULT ; close REJECT ; }
You have to tell it, which virtual host config file to use. It will not modify this file at all. It will produce a modified version in the file "virt-updated.txt'.
The domains for which the 'domain-addr.txt' has found no IP address, the virtual hosts sections will be copied to the file "virt-updated.txt'.
An extra copy will be written to the file 'virt_rejects.txt'.
So here we go:
Code:
$ ./virt-update virt_orig.txt
The debugging code will show this for the last section
Code:
Scanning section for ServerName
<VirtualHost 4.4.4.4:8080>
#
# Our forum
#
ServerName daemonforums.org
Processing : ServerName daemonforums.org
(Extracted domain name = [daemonforums.org] )
Processing: <VirtualHost 4.4.4.4:8080>
( Extracted IP number: 4.4.4.4 ) Port number = :8080
Changing 4.4.4.4 -> 67.205.67.40
Result: <VirtualHost 67.205.67.40:8080>
To see the changes you can run
diff to compare the new file with the original
Code:
$ diff -u virt_orig.txt virt_updated.txt
--- virt_orig.txt Mon Nov 24 02:41:22 2008
+++ virt_updated.txt Mon Nov 24 03:19:52 2008
@@ -1,25 +1,25 @@
# start of virtual hosts
-<VirtualHost 11.11.11.11:80>
+<VirtualHost 145.7.192.133:80>
ServerName kpn.com
ServerAlias www.kpn.com
</VirtualHost>
# a remark preceded by an empty line
-<VirtualHost 22.22.22.22:80>
+<VirtualHost 128.121.215.221:80>
# ServerName fish.org
ServerName gorilla.org
ServerAlias www.gorilla.org
</VirtualHost>
# another remark followed by an empty line
-<VirtualHost 33.33.33.33:8080>
+<VirtualHost 152.160.49.201:8080>
# --- home of the monkeys
ServerName monkey.org
ServerAlias www.monkey.org
ServerAdmin webmaster@monkey.org
</VirtualHost>
-<VirtualHost 4.4.4.4:8080>
+<VirtualHost 67.205.67.40:8080>
#
# Our forum
#
In this case there were no rejects
Code:
$ ls -l virt*txt
-rw-r--r-- 1 j65nko j65nko 680 Nov 24 02:41 virt_orig.txt
-rw-r--r-- 1 j65nko j65nko 0 Nov 24 03:19 virt_rejects.txt
-rw-r--r-- 1 j65nko j65nko 694 Nov 24 03:19 virt_updated.txt
To uncompress the attached file
Code:
$ tar xvzf virt-updater.tgz