I am trying to create a bash script that can generate a file which contains a full list of domains - from Apache's configuration file - that a web server hosts.

It actually seems quite easy. From what I see ServerName and ServerAlias are the key directives those will be necessary to generate this list.

What confuses me is the possibility of having multiple number of Aliases.

An example entry.

<VirtualHost IP_ADDR:PORT>
    ServerName domain-1.tld
    ServerAlias www.domain-1.tld
    DocumentRoot /home/domain-1.tld/public_html
    ServerAdmin webmaster@domain-1.tld
    UseCanonicalName Off
    CustomLog /usr/local/apache/domlogs/domain-1.tld combined
    CustomLog /usr/local/apache/domlogs/domain-1.tld-bytes_log "%{%s}t %I .\n%{%s}t %O ."

A second entry.

<VirtualHost IP_ADDR:PORT>
    ServerName domain-2.tld
    ServerAlias www.domain-2.tld some-other-domain.tld another-domain.tld
    DocumentRoot /home/domain-2.tld/public_html
    ServerAdmin webmaster@domain-2.tld
    UseCanonicalName Off
    CustomLog /usr/local/apache/domlogs/domain-2.tld combined
    CustomLog /usr/local/apache/domlogs/domain-2.tld-bytes_log "%{%s}t %I .\n%{%s}t %O ."

What would be the best approach in bash - to generation of this list?


I think you are going the wrong way about it. Instead of a shell script that parse VirtualHost's files (which, BTW, can be anywhere) you should use apache own tools to do this. One of them is apache2ctl status.

  • Thank you for the input. In this particular case httpd.conf is the only file that contains vhost definitions. There also is a reason why I am going with parsing the file because I will be monitoring the changes in the file. – compixtr May 5 '14 at 15:41

The Perl module Config::General can parse Apache conf files, so you might do

use strict;
use warnings;
use Config::General;

my %conf = Config::General->new('/path/to/config.conf')->getall();

for my $ip_port (keys %{$conf{VirtualHost}}) { 
    for my $vh (@{$conf{VirtualHost}{$ip_port}}) {
        if (exists $vh->{ServerName} and exists $vh->{ServerAlias}) {
            my $aliases = ref $vh->{ServerAlias} eq 'ARRAY'
                              ? join(",", @{$vh->{ServerAlias}}) 
                              : $vh->{ServerAlias};
            print $ip_port, "\t", $vh->{ServerName}, "\t", $aliases, "\n";

This code is a bit ugly. With combining sed and awk, you can use extract domain from ServerAlias lines into several lines with one domain per line

# echo '                         ServerAlias         www.domain-2.tld         some-other-domain.tld  another-domain.tld' | awk '{print substr($0, index($0, $2))}'  | sed -e 's/\s\+/\n/g'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.