Wednesday, September 15, 2010

Web Scraping Nagios

I have not been web scape for quite a while. Recently I need to rearrange and summarise Nagios data so as to present the monitoring info into some form of management dashboard.

With Tcl and it's tdom extension, I am able to web scrape with ease. However, one of the challenges is that I need to summarise all the disk partitions utilisation criticality as a single service. My initial XPath is to go through all 26 partitions (Disks A to Z)

$branch selectNodes {td/a[@class='statusCRITICAL'][
    text()='WINDISK-A' or text()='WINDISK-B' or text()='WINDISK-C' or
    text()='WINDISK-D' or text()='WINDISK-E' or text()='WINDISK-F' or
    text()='WINDISK-G' or text()='WINDISK-H' or text()='WINDISK-I' or
    text()='WINDISK-J' or text()='WINDISK-K' or text()='WINDISK-L' or
    text()='WINDISK-M' or text()='WINDISK-N' or text()='WINDISK-O' or
    text()='WINDISK-P' or text()='WINDISK-Q' or text()='WINDISK-R' or
    text()='WINDISK-S' or text()='WINDISK-T' or text()='WINDISK-U' or
    text()='WINDISK-V' or text()='WINDISK-W' or text()='WINDISK-X' or
    text()='WINDISK-Y' or text()='WINDISK-Z'
]}

If you read the XPath specification, you will find the starts-with() function can be used in this scenario. With a single function, I can avoid all the above messy syntax.

$branch selectNodes {td/a[@class='statusCRITICAL'][starts-with(.,'WINDISK-')]}

Labels: , ,

Wednesday, October 17, 2007

Table^10

If you watch TV often enough, you will probably come across this ad about the new web site, Mocca.com (MediaCorp Online Communities and Classified Advertising).

The above site looks pretty good on my Firefox with a response time of about 3 seconds for 121 requests (413KB in total). The result is based on the Firefox Add-on, Firebug. 100+ requests is considered quite a lot.

What I normally do when I find the site "interesting" is to look at the HTML code. Guess what, I realised that there is a lot issues with the HTML source.

  • The redirection is not done properly. Normally it will be redirected to the location via the Location or Content-Location header to avoid additional overhead from browser to render the HTML code. Also, the HTML is definitely ill-formed and not complete.
    $ curl --dump-header /dev/tty http://mocca.com/
    HTTP/1.1 200 OK
    Content-Length: 61
    Content-Type: text/html
    Content-Location: http://mocca.com/index.htm
    Last-Modified: Wed, 26 Sep 2007 09:30:19 GMT
    Accept-Ranges: bytes
    ETag: "b8a39eda1f0c81:17de"
    X-Powered-By: ASP.NET
    Date: Tue, 16 Oct 2007 08:46:21 GMT
    Server: Concealed by Juniper Networks DX
    Via: 1.1 MC-LB1 (Juniper Networks Application Acceleration Platform - DX 5.2.5 0)
    Set-Cookie: rl-sticky-key=caacb80750; path=/; expires=Tue, 16 Oct 2007 09:31:03GMT
    
    <META HTTP-EQUIV="Refresh" CONTENT="1; URL=/portal/site/cas">
    
  • When I fetched the home page http://mocca.com/portal/site/cas, I realised that the HTML code has the <title> node before the <html> node. If you were to convert the HTML to a DOM tree, you may likely get 1 node in the tree. Also, I submitted the URL to W3C HTML Validation Service, and it reported 218 Errors.
    $ curl --silent http://mocca.com/portal/site/cas 2>&1 | awk '$0!~/^$/{print}' | head -10
    
    <title>MediaCorp Mocca </title>
    <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
    
    <link href="/vgn-ext-templating/common/styles/vgn-ext-templating.css" rel="stylesheet" type="text/css"></link>
              <script language="JavaScript" src="/portal/jslib/form_state_manager.js"></script>
              <noscript>In order to bring you the best possible user experience, this site uses Javascript. If you are seeing this message, it is likely that the Javascript option in your browser is disabled. For optimal viewing of this site, p
    lease ensure that Javascript is enabled for your browser.
              </noscript>
                    <base target="_top">
    
  • I realised there is a lot of table within table within table. Hey, that's interesting. At the back of my mind I was wondering how deep is this nesting of tables going to be. A Tcl program with tDOM extension should do the job. Of course I have to remove the first <title> before the parsing, otherwise I will end up with 1 node in the tree.
    package require tdom
    
    proc howdeep { node } {
     set l [split [$node toXPath] /]
     set n [llength $l]
     set count 0
     for { set i 0 } { $i < $n } { incr i } {
      if { [string match -nocase "table*" [lindex $l $i]] } {
       incr count
      }
     }
     return $count
    }
    
    set html index.html-modified
    set doc [dom parse -html [tDOM::xmlReadFile $html]]
    set root [$doc documentElement]
    
    set max 0
    set maxnode {}
    foreach table [$root selectNodes {//table}] {
     set level [howdeep $table]
     if { $level > $max } {
      set max $level
      set maxnode $table
     }
    }
    puts $max
    puts [llength [$root selectNodes {//table}]]
    puts [$maxnode toXPath]
    
    Output of this program:
    10
    144
    /html/body/table/tr[2]/td[2]/table/tr[2]/td/table/tr/td[3]/table/tr/td/table/tr/td/table[1]/tr/td[1]/table/tr[2]/td[2]/table/tr/td[1]/table/tr[1]/td/table
    

Wow, we are talking about a nesting of 10 levels of <table> and a total of 144 tables, that's a lot! So, what's the conclusion.

  • Modern browsers are so forgiving and they normally do a very good job to render complex and even ill-formed HTML code
  • With such a deep nesting of tables and 100+ requests, the browser is able to render the content in seconds. That is amusing.

Labels: , , ,

Thursday, August 23, 2007

File Logging in Solaris, the NFS way (almost) and the BSM way

One of my potential customers wanted to implement grid computing with their existing servers. Two issues they would like us to address.
  1. Each design team can only access their own design files
  2. All access of files from the central storage have to be captured to ensure design is kept within the team.

Item 1 is pretty easy to address with the standard ACL in Solaris, or any other flavours of UNIX

Item 2. Two possible solutions to this issue. First approach, NFS logging. I know Solaris NFS comes with the capability of logging all the NFS access. All we need is to share out the directory path with logging enable (share -o log=global /some/directory). The nfslog.conf will tell where the log file will go, default /var/nfs

# more /etc/nfs/nfslog.conf

#ident  "@(#)nfslog.conf        1.5     99/02/21 SMI"
#
# Copyright (c) 1999 by Sun Microsystems, Inc.
# All rights reserved.
#
# NFS server log configuration file.
#
# <tag> [ defaultdir=<dir_path> ] \
#       [ log=<logfile_path> ] [ fhtable=<table_path> ] \
#       [ buffer=<bufferfile_path> ] [ logformat=basic|extended ]
#

global  defaultdir=/var/nfs \
    log=nfslog fhtable=fhtable buffer=nfslog_workbuffer

There is a catch. In the man page of nfslogd, it say NFS logging is not supported for NFS version 4.

# man nfslogd

System Administration Commands                        nfslogd(1M)

NAME
 nfslogd - nfs logging daemon

SYNOPSIS
 /usr/lib/nfs/nfslogd

DESCRIPTION
 The nfslogd  daemon  provides  operational  logging  to  the
 Solaris  NFS  server. It is the nfslogd daemon's job to gen-
 erate the activity log by analyzing the RPC operations  pro-
 cessed  by  the  NFS server.  The log will only be generated
 for file systems exported  with  logging  enabled.  This  is
 specified  at  file  system  export  time  by  means  of the
 share_nfs(1M) command.

 NFS server logging is not supported on Solaris machines that
 are using NFS Version 4.

...
OK, I can still fall back to NFS version 3. However, when I enable nfs server (/etc/init.d/nfs.server or svcadm enable svc:/network/nfs/server:default) and have another server to mount using nfsv3 (mount -o vers=3 ...), I can see files in the /var/nfs directory are growing, but most of them are binary files not ascii
# ls -l /var/nfs
total 13502
-rw-r-----   1 root     root           0 Aug 23 11:25 fhtable.0000000000000000.dir
-rw-r-----   1 root     root        1024 Aug 23 11:25 fhtable.0000000000000000.pag
-rw-r-----   1 root     root        4096 Aug 23 11:57 fhtable.0154002000000002.dir
-rw-r-----   1 root     root     8368128 Aug 23 17:31 fhtable.0154002000000002.pag
-rw-r-----   1 root     root           0 Aug 23 11:25 nfslog
-rw-------   1 root     root     2309148 Aug 23 17:44 nfslog_workbuffer_log_in_process
drwxr-xr-x   2 daemon   daemon       512 Mar 21 10:21 v4_oldstate
drwxr-xr-x   2 daemon   daemon       512 Aug 23 11:30 v4_state

# file /var/nfs/*
/var/nfs/fhtable.0000000000000000.dir:  empty file
/var/nfs/fhtable.0000000000000000.pag:  data
/var/nfs/fhtable.0154002000000002.dir:  data
/var/nfs/fhtable.0154002000000002.pag:  data
/var/nfs/nfslog:        empty file
/var/nfs/nfslog_workbuffer_log_in_process:      data
/var/nfs/v4_oldstate:   directory
/var/nfs/v4_state:      directory
All these files seem to be binary in nature and very likely they are in Berkeley DB format. I tried to use perl dbmopen to read it and unpack the key-value, but all I got are garbage. I suppose I need to fully understand the struct of that entry. To my surprise, there isn't any utility in the OS that allow me to view the content of the file. Also, I had no luck at all finding a solution on the Internet. Anyway, I am hitting a dead end and all I can do is to post it to the Sun folk for a solution.

Second approach that I wanted to try is Basic Security Module (BSM). Although this is meant for conforming to the US C2 security audit requirements, it does log access of files (any files, including sharable libraries) in the system. Anyway, I just want to run it to see what it can offer.

cd /etc/security
./bsmconv
Once bsmconv is activated, you need to reboot the server in oder for the bsm audit kernel module to be loaded in the next start up. The log file is located in /var/audit directory by default
$ ls  /var/audit
20070821022314.20070821022315.chihung  20070821023545.20070821023546.chihung
20070821022315.20070821023344.chihung  20070821023546.20070821024602.chihung

In BSM, it comes with a utility (praudit) to view the content. If you read up the man page, there are a couple of flags in this command. In particular, the '-l' flag and the '-x' flag are the one that I wanted to talk about. '-l' gives you one line per record so that you can use any of the standard Solaris utilities like sed/awk/cut to filter out the information you want.

This is a sample output of praudit -l with fm/fa/fc/fd (file modified/access/create/delete) audit turned on. See /etc/security/audit_class for a full list.

file,2007-08-21 10:35:46.111 +08:00,/var/audit/20070821023545.20070821023546.chihung
header,44,2,system booted,na,2007-08-21 10:34:49.704 +08:00,text,booting kernel
header,135,2,stat(2),,chihung,2007-08-21 10:39:22.700 +08:00,path,/usr/lib/pt_chmod,attribute,104511,root,bin,85,623,0,subject,chihung,root,staff,chihung,staff,704,2477344358,756 65558 ftpl_2_207,return,success,0
header,126,2,stat(2),fe,chihung,2007-08-21 10:39:22.727 +08:00,path,/platform/SUNW,UltraSPARC-IIi-cEngine/lib,subject,chihung,root,staff,chihung,staff,704,2477344358,756 65558 ftpl_2_207,return,failure: No such file or directory,-1
header,149,2,access(2),,chihung,2007-08-21 10:39:22.737 +08:00,path,/dev/pts/devices/pseudo/pts@0:1,attribute,20620,root,tty,335,12582918,103079215105,subject,chihung,root,staff,chihung,staff,704,2477344358,756 65558 ftpl_2_207,return,success,0
header,149,2,pathconf(2),,chihung,2007-08-21 10:39:22.737 +08:00,path,/dev/pts/devices/pseudo/pts@0:1,attribute,20620,root,root,335,12582918,103079215105,subject,chihung,root,staff,chihung,staff,704,2477344358,756 65558 ftpl_2_207,return,success,1
header,149,2,access(2),,chihung,2007-08-21 10:39:22.740 +08:00,path,/dev/pts/devices/pseudo/pts@0:1,attribute,20620,chihung,tty,335,12582918,103079215105,subject,chihung,chihung,staff,chihung,staff,703,2477344358,756
...
If you were to analyse the number of fields (FS) per record, you realise that they are not consistent. FS ranges from 3,8,19,21,22,28,29,30,31,32. Ability to extract the right field for analysis is going to be a nightmare.

How about the 'praudit -x' flag. Basically it will output the information in XML format. This is cool and XML is definitely my friend. Let's see the output:

<?xml version='1.0' encoding='UTF-8' ?>
<?xml-stylesheet type='text/xsl' href='file:///usr/share/lib/xml/style/adt_record.xsl.1' ?>

<!DOCTYPE audit PUBLIC '-//Sun Microsystems, Inc.//DTD Audit V1//EN' 'file:///usr/share/lib/xml/dtd/adt_record.dtd.1'>

<audit>
<file iso8601="2007-08-21 10:35:46.111 +08:00">/var/audit/20070821023545.20070821023546.chihung</file>
<record version="2" event="system booted" modifier="na" iso8601="2007-08-21 10:34:49.704 +08:00">
<text>booting kernel</text>
</record>
<record version="2" event="stat(2)" host="chihung" iso8601="2007-08-21 10:39:22.700 +08:00">
<path>/usr/lib/pt_chmod</path>
<attribute mode="104511" uid="root" gid="bin" fsid="85" nodeid="623" device="0"/>
<subject audit-uid="chihung" uid="root" gid="staff" ruid="chihung" rgid="staff" pid="704" sid="2477344358" tid="756 65558 ftpl_2_207"/>
<return errval="success" retval="0"/>
</record>
<record version="2" event="stat(2)" modifier="fe" host="chihung" iso8601="2007-08-21 10:39:22.727 +08:00">
<path>/platform/SUNW,UltraSPARC-IIi-cEngine/lib</path>
<subject audit-uid="chihung" uid="root" gid="staff" ruid="chihung" rgid="staff" pid="704" sid="2477344358" tid="756 65558 ftpl_2_207"/>
<return errval="failure: No such file or directory" retval="-1"/>
</record>
<record version="2" event="access(2)" host="chihung" iso8601="2007-08-21 10:39:22.737 +08:00">
<path>/dev/pts/devices/pseudo/pts@0:1</path>
<attribute mode="20620" uid="root" gid="tty" fsid="335" nodeid="12582918" device="103079215105"/>
<subject audit-uid="chihung" uid="root" gid="staff" ruid="chihung" rgid="staff" pid="704" sid="2477344358" tid="756 65558 ftpl_2_207"/>
<return errval="success" retval="0"/>
It even comes with a XML stylesheet that we can apply. Here is the screen dump of the html after running (xsltproc adt_record.xsl.1 audit.xml > audit-xml.html)

With XML, I can pick up a lot of interesting things from the data. Say I want to find out who access files that do not belong to them. With DOM implementation in Tcl (tDOM), I can script it like this

package require tdom
set doc [dom parse [tDOM::xmlReadFile audit.xml]]
set root [$doc documentElement]
foreach i [$root selectNodes {//attribute[@uid != string(../subject/@uid)]}] {
puts [[$i selectNodes ../path/text()] nodeValue]
}

Until I can resolve the NFS logging, it seems BSM is going to be the answer. Bear in mind that BSM generates tonnes of data. If I were to implement this approach, I will definitely allocate a lot of disk space (100+GB) and make sure this is in a separate disk to avoid too many IO activities in the OS disk (/var)

Labels: , , ,

Tuesday, June 12, 2007

Apache 2.2 Module-Directive Mapping

One of the high profile projects require performance tuning for the Apache 2.x running on Solaris 10. I have no problem in tuning the Solaris operating system.

So how about Apache. My approach will be to conduct a minimisation follow by tuning the MaxClients and other related parameters for the default prefork model. However, in order to determine which modules not to be included in the httpd.conf, we need to find out the mapping between module and it's respective directives. I was not able to find anything from the Internet and therefore I decided to work it out myself.

The Apache 2.2 documentation is written as a set of XHTML document and this make life a lot easier. With Tcl and tDOM (DOM implementation in Tcl), I am able to parse the XHTML files and dynamically work out the mapping relationship. With this mapping, I can confidently take out those modules that I do not need in the httpd.conf.

One thing that we need to watch out is that the XHTML file has a default XML namespace like this:
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
In the below Tcl program, I will have to assign my own namespace to avoid using local-name() in the XPath predicate.

package require http
package require tdom

set baseurl "http://httpd.apache.org/docs/2.2/mod/"
set s [http::geturl $baseurl]
set doc0 [dom parse [http::data $s]]
set root0 [$doc0 documentElement]
set xmlns0 [$root0 getAttribute xmlns]
http::cleanup $s

foreach module [$root0 selectNodes -namespace "ns $xmlns0" {//ns:dl/ns:dt/ns:a}] {
 set modlink [$module getAttribute href]
 set modname [[$module childNodes] nodeValue]

 # process each module
 set s [http::geturl $baseurl$modlink]
 set doc [dom parse [http::data $s]]
 set root [$doc documentElement]
 set xmlns [$root getAttribute xmlns]
 http::cleanup $s
 #
 foreach directive [$root selectNodes -namespaces "ns $xmlns0" \
  {//ns:div[@id="quickview"]/ns:ul[@id="toc"]/ns:li/ns:a/text()}] {
  puts "$modname [$directive nodeValue]"
 }
 $doc delete
}

Output of the module-directive mapping by :

$ tclsh module.tcl | sort | tee bymodule.txt
beos CoreDumpDirectory
beos Group
beos Listen
beos ListenBacklog
beos MaxClients
beos MaxMemFree
beos MaxRequestsPerThread
beos MaxSpareThreads
beos MinSpareThreads
beos PidFile
beos ReceiveBufferSize
beos ScoreBoardFile
beos SendBufferSize
beos StartThreads
beos User
core 
core 
core 
core 
core 
core 
core 
core 
core 
core 
core 
core AcceptFilter
core AcceptPathInfo
core AccessFileName
core AddDefaultCharset
core AddOutputFilterByType
core AllowEncodedSlashes
core AllowOverride
core AuthName
core AuthType
core CGIMapExtension
core ContentDigest
core DefaultType
core DocumentRoot
core EnableMMAP
core EnableSendfile
core ErrorDocument
core ErrorLog
core FileETag
core ForceType
core HostnameLookups
core Include
core KeepAlive
core KeepAliveTimeout
core LimitInternalRecursion
core LimitRequestBody
core LimitRequestFieldSize
core LimitRequestFields
core LimitRequestLine
core LimitXMLRequestBody
core LogLevel
core MaxKeepAliveRequests
core NameVirtualHost
core Options
core RLimitCPU
core RLimitMEM
core RLimitNPROC
core Require
core Satisfy
core ScriptInterpreterSource
core ServerAdmin
core ServerAlias
core ServerName
core ServerPath
core ServerRoot
core ServerSignature
core ServerTokens
core SetHandler
core SetInputFilter
core SetOutputFilter
core TimeOut
core TraceEnable
core UseCanonicalName
core UseCanonicalPhysicalPort
event AcceptMutex
event CoreDumpDirectory
event EnableExceptionHook
event Group
event Listen
event ListenBacklog
event LockFile
event MaxClients
event MaxMemFree
event MaxRequestsPerChild
event MaxSpareThreads
event MinSpareThreads
event PidFile
event ScoreBoardFile
event SendBufferSize
event ServerLimit
event StartServers
event ThreadLimit
event ThreadStackSize
event ThreadsPerChild
event User
mod_actions Action
mod_actions Script
mod_alias Alias
mod_alias AliasMatch
mod_alias Redirect
mod_alias RedirectMatch
mod_alias RedirectPermanent
mod_alias RedirectTemp
mod_alias ScriptAlias
mod_alias ScriptAliasMatch
mod_auth_basic AuthBasicAuthoritative
mod_auth_basic AuthBasicProvider
mod_auth_digest AuthDigestAlgorithm
mod_auth_digest AuthDigestDomain
mod_auth_digest AuthDigestNcCheck
mod_auth_digest AuthDigestNonceFormat
mod_auth_digest AuthDigestNonceLifetime
mod_auth_digest AuthDigestProvider
mod_auth_digest AuthDigestQop
mod_auth_digest AuthDigestShmemSize
mod_authn_alias 
mod_authn_anon Anonymous
mod_authn_anon Anonymous_LogEmail
mod_authn_anon Anonymous_MustGiveEmail
mod_authn_anon Anonymous_NoUserID
mod_authn_anon Anonymous_VerifyEmail
mod_authn_dbd AuthDBDUserPWQuery
mod_authn_dbd AuthDBDUserRealmQuery
mod_authn_dbm AuthDBMType
mod_authn_dbm AuthDBMUserFile
mod_authn_default AuthDefaultAuthoritative
mod_authn_file AuthUserFile
mod_authnz_ldap AuthLDAPBindDN
mod_authnz_ldap AuthLDAPBindPassword
mod_authnz_ldap AuthLDAPCharsetConfig
mod_authnz_ldap AuthLDAPCompareDNOnServer
mod_authnz_ldap AuthLDAPDereferenceAliases
mod_authnz_ldap AuthLDAPGroupAttribute
mod_authnz_ldap AuthLDAPGroupAttributeIsDN
mod_authnz_ldap AuthLDAPRemoteUserAttribute
mod_authnz_ldap AuthLDAPRemoteUserIsDN
mod_authnz_ldap AuthLDAPUrl
mod_authnz_ldap AuthzLDAPAuthoritative
mod_authz_dbm AuthDBMGroupFile
mod_authz_dbm AuthzDBMAuthoritative
mod_authz_dbm AuthzDBMType
mod_authz_default AuthzDefaultAuthoritative
mod_authz_groupfile AuthGroupFile
mod_authz_groupfile AuthzGroupFileAuthoritative
mod_authz_host Allow
mod_authz_host Deny
mod_authz_host Order
mod_authz_owner AuthzOwnerAuthoritative
mod_authz_user AuthzUserAuthoritative
mod_autoindex AddAlt
mod_autoindex AddAltByEncoding
mod_autoindex AddAltByType
mod_autoindex AddDescription
mod_autoindex AddIcon
mod_autoindex AddIconByEncoding
mod_autoindex AddIconByType
mod_autoindex DefaultIcon
mod_autoindex HeaderName
mod_autoindex IndexIgnore
mod_autoindex IndexOptions
mod_autoindex IndexOrderDefault
mod_autoindex IndexStyleSheet
mod_autoindex ReadmeName
mod_cache CacheDefaultExpire
mod_cache CacheDisable
mod_cache CacheEnable
mod_cache CacheIgnoreCacheControl
mod_cache CacheIgnoreHeaders
mod_cache CacheIgnoreNoLastMod
mod_cache CacheLastModifiedFactor
mod_cache CacheMaxExpire
mod_cache CacheStoreNoStore
mod_cache CacheStorePrivate
mod_cern_meta MetaDir
mod_cern_meta MetaFiles
mod_cern_meta MetaSuffix
mod_cgi ScriptLog
mod_cgi ScriptLogBuffer
mod_cgi ScriptLogLength
mod_cgid ScriptLog
mod_cgid ScriptLogBuffer
mod_cgid ScriptLogLength
mod_cgid ScriptSock
mod_charset_lite CharsetDefault
mod_charset_lite CharsetOptions
mod_charset_lite CharsetSourceEnc
mod_dav Dav
mod_dav DavDepthInfinity
mod_dav DavMinTimeout
mod_dav_fs DavLockDB
mod_dav_lock DavGenericLockDB
mod_dbd DBDExptime
mod_dbd DBDKeep
mod_dbd DBDMax
mod_dbd DBDMin
mod_dbd DBDParams
mod_dbd DBDPersist
mod_dbd DBDPrepareSQL
mod_dbd DBDriver
mod_deflate DeflateBufferSize
mod_deflate DeflateCompressionLevel
mod_deflate DeflateFilterNote
mod_deflate DeflateMemLevel
mod_deflate DeflateWindowSize
mod_dir DirectoryIndex
mod_dir DirectorySlash
mod_disk_cache CacheDirLength
mod_disk_cache CacheDirLevels
mod_disk_cache CacheMaxFileSize
mod_disk_cache CacheMinFileSize
mod_disk_cache CacheRoot
mod_dumpio DumpIOInput
mod_dumpio DumpIOLogLevel
mod_dumpio DumpIOOutput
mod_echo ProtocolEcho
mod_env PassEnv
mod_env SetEnv
mod_env UnsetEnv
mod_example Example
mod_expires ExpiresActive
mod_expires ExpiresByType
mod_expires ExpiresDefault
mod_ext_filter ExtFilterDefine
mod_ext_filter ExtFilterOptions
mod_file_cache CacheFile
mod_file_cache MMapFile
mod_filter FilterChain
mod_filter FilterDeclare
mod_filter FilterProtocol
mod_filter FilterProvider
mod_filter FilterTrace
mod_headers Header
mod_headers RequestHeader
mod_ident IdentityCheck
mod_ident IdentityCheckTimeout
mod_imagemap ImapBase
mod_imagemap ImapDefault
mod_imagemap ImapMenu
mod_include SSIEndTag
mod_include SSIErrorMsg
mod_include SSIStartTag
mod_include SSITimeFormat
mod_include SSIUndefinedEcho
mod_include XBitHack
mod_info AddModuleInfo
mod_isapi ISAPIAppendLogToErrors
mod_isapi ISAPIAppendLogToQuery
mod_isapi ISAPICacheFile
mod_isapi ISAPIFakeAsync
mod_isapi ISAPILogNotSupported
mod_isapi ISAPIReadAheadBuffer
mod_ldap LDAPCacheEntries
mod_ldap LDAPCacheTTL
mod_ldap LDAPConnectionTimeout
mod_ldap LDAPOpCacheEntries
mod_ldap LDAPOpCacheTTL
mod_ldap LDAPSharedCacheFile
mod_ldap LDAPSharedCacheSize
mod_ldap LDAPTrustedClientCert
mod_ldap LDAPTrustedGlobalCert
mod_ldap LDAPTrustedMode
mod_ldap LDAPVerifyServerCert
mod_log_config BufferedLogs
mod_log_config CookieLog
mod_log_config CustomLog
mod_log_config LogFormat
mod_log_config TransferLog
mod_log_forensic ForensicLog
mod_mem_cache MCacheMaxObjectCount
mod_mem_cache MCacheMaxObjectSize
mod_mem_cache MCacheMaxStreamingBuffer
mod_mem_cache MCacheMinObjectSize
mod_mem_cache MCacheRemovalAlgorithm
mod_mem_cache MCacheSize
mod_mime AddCharset
mod_mime AddEncoding
mod_mime AddHandler
mod_mime AddInputFilter
mod_mime AddLanguage
mod_mime AddOutputFilter
mod_mime AddType
mod_mime DefaultLanguage
mod_mime ModMimeUsePathInfo
mod_mime MultiviewsMatch
mod_mime RemoveCharset
mod_mime RemoveEncoding
mod_mime RemoveHandler
mod_mime RemoveInputFilter
mod_mime RemoveLanguage
mod_mime RemoveOutputFilter
mod_mime RemoveType
mod_mime TypesConfig
mod_mime_magic MimeMagicFile
mod_negotiation CacheNegotiatedDocs
mod_negotiation ForceLanguagePriority
mod_negotiation LanguagePriority
mod_nw_ssl NWSSLTrustedCerts
mod_nw_ssl NWSSLUpgradeable
mod_nw_ssl SecureListen
mod_proxy 
mod_proxy 
mod_proxy AllowCONNECT
mod_proxy NoProxy
mod_proxy ProxyBadHeader
mod_proxy ProxyBlock
mod_proxy ProxyDomain
mod_proxy ProxyErrorOverride
mod_proxy ProxyIOBufferSize
mod_proxy ProxyMaxForwards
mod_proxy ProxyPass
mod_proxy ProxyPassReverse
mod_proxy ProxyPassReverseCookieDomain
mod_proxy ProxyPassReverseCookiePath
mod_proxy ProxyPreserveHost
mod_proxy ProxyReceiveBufferSize
mod_proxy ProxyRemote
mod_proxy ProxyRemoteMatch
mod_proxy ProxyRequests
mod_proxy ProxyTimeout
mod_proxy ProxyVia
mod_rewrite RewriteBase
mod_rewrite RewriteCond
mod_rewrite RewriteEngine
mod_rewrite RewriteLock
mod_rewrite RewriteLog
mod_rewrite RewriteLogLevel
mod_rewrite RewriteMap
mod_rewrite RewriteOptions
mod_rewrite RewriteRule
mod_setenvif BrowserMatch
mod_setenvif BrowserMatchNoCase
mod_setenvif SetEnvIf
mod_setenvif SetEnvIfNoCase
mod_so LoadFile
mod_so LoadModule
mod_speling CheckCaseOnly
mod_speling CheckSpelling
mod_ssl SSLCACertificateFile
mod_ssl SSLCACertificatePath
mod_ssl SSLCADNRequestFile
mod_ssl SSLCADNRequestPath
mod_ssl SSLCARevocationFile
mod_ssl SSLCARevocationPath
mod_ssl SSLCertificateChainFile
mod_ssl SSLCertificateFile
mod_ssl SSLCertificateKeyFile
mod_ssl SSLCipherSuite
mod_ssl SSLCryptoDevice
mod_ssl SSLEngine
mod_ssl SSLHonorCipherOrder
mod_ssl SSLMutex
mod_ssl SSLOptions
mod_ssl SSLPassPhraseDialog
mod_ssl SSLProtocol
mod_ssl SSLProxyCACertificateFile
mod_ssl SSLProxyCACertificatePath
mod_ssl SSLProxyCARevocationFile
mod_ssl SSLProxyCARevocationPath
mod_ssl SSLProxyCipherSuite
mod_ssl SSLProxyEngine
mod_ssl SSLProxyMachineCertificateFile
mod_ssl SSLProxyMachineCertificatePath
mod_ssl SSLProxyProtocol
mod_ssl SSLProxyVerify
mod_ssl SSLProxyVerifyDepth
mod_ssl SSLRandomSeed
mod_ssl SSLRequire
mod_ssl SSLRequireSSL
mod_ssl SSLSessionCache
mod_ssl SSLSessionCacheTimeout
mod_ssl SSLUserName
mod_ssl SSLVerifyClient
mod_ssl SSLVerifyDepth
mod_status ExtendedStatus
mod_suexec SuexecUserGroup
mod_userdir UserDir
mod_usertrack CookieDomain
mod_usertrack CookieExpires
mod_usertrack CookieName
mod_usertrack CookieStyle
mod_usertrack CookieTracking
mod_version 
mod_vhost_alias VirtualDocumentRoot
mod_vhost_alias VirtualDocumentRootIP
mod_vhost_alias VirtualScriptAlias
mod_vhost_alias VirtualScriptAliasIP
mpm_common AcceptMutex
mpm_common CoreDumpDirectory
mpm_common EnableExceptionHook
mpm_common GracefulShutdownTimeout
mpm_common Group
mpm_common Listen
mpm_common ListenBackLog
mpm_common LockFile
mpm_common MaxClients
mpm_common MaxMemFree
mpm_common MaxRequestsPerChild
mpm_common MaxSpareThreads
mpm_common MinSpareThreads
mpm_common PidFile
mpm_common ReceiveBufferSize
mpm_common ScoreBoardFile
mpm_common SendBufferSize
mpm_common ServerLimit
mpm_common StartServers
mpm_common StartThreads
mpm_common ThreadLimit
mpm_common ThreadStackSize
mpm_common ThreadsPerChild
mpm_common User
mpm_netware Listen
mpm_netware ListenBacklog
mpm_netware MaxMemFree
mpm_netware MaxRequestsPerChild
mpm_netware MaxSpareThreads
mpm_netware MaxThreads
mpm_netware MinSpareThreads
mpm_netware ReceiveBufferSize
mpm_netware SendBufferSize
mpm_netware StartThreads
mpm_netware ThreadStackSize
mpm_winnt CoreDumpDirectory
mpm_winnt Listen
mpm_winnt ListenBacklog
mpm_winnt MaxMemFree
mpm_winnt MaxRequestsPerChild
mpm_winnt PidFile
mpm_winnt ReceiveBufferSize
mpm_winnt ScoreBoardFile
mpm_winnt SendBufferSize
mpm_winnt ThreadLimit
mpm_winnt ThreadStackSize
mpm_winnt ThreadsPerChild
mpm_winnt Win32DisableAcceptEx
mpmt_os2 Group
mpmt_os2 Listen
mpmt_os2 ListenBacklog
mpmt_os2 MaxRequestsPerChild
mpmt_os2 MaxSpareThreads
mpmt_os2 MinSpareThreads
mpmt_os2 PidFile
mpmt_os2 ReceiveBufferSize
mpmt_os2 SendBufferSize
mpmt_os2 StartServers
mpmt_os2 User
prefork AcceptMutex
prefork CoreDumpDirectory
prefork EnableExceptionHook
prefork Group
prefork Listen
prefork ListenBacklog
prefork LockFile
prefork MaxClients
prefork MaxMemFree
prefork MaxRequestsPerChild
prefork MaxSpareServers
prefork MinSpareServers
prefork PidFile
prefork ReceiveBufferSize
prefork ScoreBoardFile
prefork SendBufferSize
prefork ServerLimit
prefork StartServers
prefork User
worker AcceptMutex
worker CoreDumpDirectory
worker EnableExceptionHook
worker Group
worker Listen
worker ListenBacklog
worker LockFile
worker MaxClients
worker MaxMemFree
worker MaxRequestsPerChild
worker MaxSpareThreads
worker MinSpareThreads
worker PidFile
worker ReceiveBufferSize
worker ScoreBoardFile
worker SendBufferSize
worker ServerLimit
worker StartServers
worker ThreadLimit
worker ThreadStackSize
worker ThreadsPerChild
worker User

To sort the above based on directive:

$ awk '{print $2, $1}' bymodule.txt | sort | tee bydirective.txt
<AuthnProviderAlias> mod_authn_alias
<Directory> core
<DirectoryMatch> core
<Files> core
<FilesMatch> core
<IfDefine> core
<IfModule> core
<IfVersion> mod_version
<Limit> core
<LimitExcept> core
<Location> core
<LocationMatch> core
<Proxy> mod_proxy
<ProxyMatch> mod_proxy
<VirtualHost> core
AcceptFilter core
AcceptMutex event
AcceptMutex mpm_common
AcceptMutex prefork
AcceptMutex worker
AcceptPathInfo core
AccessFileName core
Action mod_actions
AddAlt mod_autoindex
AddAltByEncoding mod_autoindex
AddAltByType mod_autoindex
AddCharset mod_mime
AddDefaultCharset core
AddDescription mod_autoindex
AddEncoding mod_mime
AddHandler mod_mime
AddIcon mod_autoindex
AddIconByEncoding mod_autoindex
AddIconByType mod_autoindex
AddInputFilter mod_mime
AddLanguage mod_mime
AddModuleInfo mod_info
AddOutputFilter mod_mime
AddOutputFilterByType core
AddType mod_mime
Alias mod_alias
AliasMatch mod_alias
Allow mod_authz_host
AllowCONNECT mod_proxy
AllowEncodedSlashes core
AllowOverride core
Anonymous mod_authn_anon
Anonymous_LogEmail mod_authn_anon
Anonymous_MustGiveEmail mod_authn_anon
Anonymous_NoUserID mod_authn_anon
Anonymous_VerifyEmail mod_authn_anon
AuthBasicAuthoritative mod_auth_basic
AuthBasicProvider mod_auth_basic
AuthDBDUserPWQuery mod_authn_dbd
AuthDBDUserRealmQuery mod_authn_dbd
AuthDBMGroupFile mod_authz_dbm
AuthDBMType mod_authn_dbm
AuthDBMUserFile mod_authn_dbm
AuthDefaultAuthoritative mod_authn_default
AuthDigestAlgorithm mod_auth_digest
AuthDigestDomain mod_auth_digest
AuthDigestNcCheck mod_auth_digest
AuthDigestNonceFormat mod_auth_digest
AuthDigestNonceLifetime mod_auth_digest
AuthDigestProvider mod_auth_digest
AuthDigestQop mod_auth_digest
AuthDigestShmemSize mod_auth_digest
AuthGroupFile mod_authz_groupfile
AuthLDAPBindDN mod_authnz_ldap
AuthLDAPBindPassword mod_authnz_ldap
AuthLDAPCharsetConfig mod_authnz_ldap
AuthLDAPCompareDNOnServer mod_authnz_ldap
AuthLDAPDereferenceAliases mod_authnz_ldap
AuthLDAPGroupAttribute mod_authnz_ldap
AuthLDAPGroupAttributeIsDN mod_authnz_ldap
AuthLDAPRemoteUserAttribute mod_authnz_ldap
AuthLDAPRemoteUserIsDN mod_authnz_ldap
AuthLDAPUrl mod_authnz_ldap
AuthName core
AuthType core
AuthUserFile mod_authn_file
AuthzDBMAuthoritative mod_authz_dbm
AuthzDBMType mod_authz_dbm
AuthzDefaultAuthoritative mod_authz_default
AuthzGroupFileAuthoritative mod_authz_groupfile
AuthzLDAPAuthoritative mod_authnz_ldap
AuthzOwnerAuthoritative mod_authz_owner
AuthzUserAuthoritative mod_authz_user
BrowserMatch mod_setenvif
BrowserMatchNoCase mod_setenvif
BufferedLogs mod_log_config
CGIMapExtension core
CacheDefaultExpire mod_cache
CacheDirLength mod_disk_cache
CacheDirLevels mod_disk_cache
CacheDisable mod_cache
CacheEnable mod_cache
CacheFile mod_file_cache
CacheIgnoreCacheControl mod_cache
CacheIgnoreHeaders mod_cache
CacheIgnoreNoLastMod mod_cache
CacheLastModifiedFactor mod_cache
CacheMaxExpire mod_cache
CacheMaxFileSize mod_disk_cache
CacheMinFileSize mod_disk_cache
CacheNegotiatedDocs mod_negotiation
CacheRoot mod_disk_cache
CacheStoreNoStore mod_cache
CacheStorePrivate mod_cache
CharsetDefault mod_charset_lite
CharsetOptions mod_charset_lite
CharsetSourceEnc mod_charset_lite
CheckCaseOnly mod_speling
CheckSpelling mod_speling
ContentDigest core
CookieDomain mod_usertrack
CookieExpires mod_usertrack
CookieLog mod_log_config
CookieName mod_usertrack
CookieStyle mod_usertrack
CookieTracking mod_usertrack
CoreDumpDirectory beos
CoreDumpDirectory event
CoreDumpDirectory mpm_common
CoreDumpDirectory mpm_winnt
CoreDumpDirectory prefork
CoreDumpDirectory worker
CustomLog mod_log_config
DBDExptime mod_dbd
DBDKeep mod_dbd
DBDMax mod_dbd
DBDMin mod_dbd
DBDParams mod_dbd
DBDPersist mod_dbd
DBDPrepareSQL mod_dbd
DBDriver mod_dbd
Dav mod_dav
DavDepthInfinity mod_dav
DavGenericLockDB mod_dav_lock
DavLockDB mod_dav_fs
DavMinTimeout mod_dav
DefaultIcon mod_autoindex
DefaultLanguage mod_mime
DefaultType core
DeflateBufferSize mod_deflate
DeflateCompressionLevel mod_deflate
DeflateFilterNote mod_deflate
DeflateMemLevel mod_deflate
DeflateWindowSize mod_deflate
Deny mod_authz_host
DirectoryIndex mod_dir
DirectorySlash mod_dir
DocumentRoot core
DumpIOInput mod_dumpio
DumpIOLogLevel mod_dumpio
DumpIOOutput mod_dumpio
EnableExceptionHook event
EnableExceptionHook mpm_common
EnableExceptionHook prefork
EnableExceptionHook worker
EnableMMAP core
EnableSendfile core
ErrorDocument core
ErrorLog core
Example mod_example
ExpiresActive mod_expires
ExpiresByType mod_expires
ExpiresDefault mod_expires
ExtFilterDefine mod_ext_filter
ExtFilterOptions mod_ext_filter
ExtendedStatus mod_status
FileETag core
FilterChain mod_filter
FilterDeclare mod_filter
FilterProtocol mod_filter
FilterProvider mod_filter
FilterTrace mod_filter
ForceLanguagePriority mod_negotiation
ForceType core
ForensicLog mod_log_forensic
GracefulShutdownTimeout mpm_common
Group beos
Group event
Group mpm_common
Group mpmt_os2
Group prefork
Group worker
Header mod_headers
HeaderName mod_autoindex
HostnameLookups core
ISAPIAppendLogToErrors mod_isapi
ISAPIAppendLogToQuery mod_isapi
ISAPICacheFile mod_isapi
ISAPIFakeAsync mod_isapi
ISAPILogNotSupported mod_isapi
ISAPIReadAheadBuffer mod_isapi
IdentityCheck mod_ident
IdentityCheckTimeout mod_ident
ImapBase mod_imagemap
ImapDefault mod_imagemap
ImapMenu mod_imagemap
Include core
IndexIgnore mod_autoindex
IndexOptions mod_autoindex
IndexOrderDefault mod_autoindex
IndexStyleSheet mod_autoindex
KeepAlive core
KeepAliveTimeout core
LDAPCacheEntries mod_ldap
LDAPCacheTTL mod_ldap
LDAPConnectionTimeout mod_ldap
LDAPOpCacheEntries mod_ldap
LDAPOpCacheTTL mod_ldap
LDAPSharedCacheFile mod_ldap
LDAPSharedCacheSize mod_ldap
LDAPTrustedClientCert mod_ldap
LDAPTrustedGlobalCert mod_ldap
LDAPTrustedMode mod_ldap
LDAPVerifyServerCert mod_ldap
LanguagePriority mod_negotiation
LimitInternalRecursion core
LimitRequestBody core
LimitRequestFieldSize core
LimitRequestFields core
LimitRequestLine core
LimitXMLRequestBody core
Listen beos
Listen event
Listen mpm_common
Listen mpm_netware
Listen mpm_winnt
Listen mpmt_os2
Listen prefork
Listen worker
ListenBackLog mpm_common
ListenBacklog beos
ListenBacklog event
ListenBacklog mpm_netware
ListenBacklog mpm_winnt
ListenBacklog mpmt_os2
ListenBacklog prefork
ListenBacklog worker
LoadFile mod_so
LoadModule mod_so
LockFile event
LockFile mpm_common
LockFile prefork
LockFile worker
LogFormat mod_log_config
LogLevel core
MCacheMaxObjectCount mod_mem_cache
MCacheMaxObjectSize mod_mem_cache
MCacheMaxStreamingBuffer mod_mem_cache
MCacheMinObjectSize mod_mem_cache
MCacheRemovalAlgorithm mod_mem_cache
MCacheSize mod_mem_cache
MMapFile mod_file_cache
MaxClients beos
MaxClients event
MaxClients mpm_common
MaxClients prefork
MaxClients worker
MaxKeepAliveRequests core
MaxMemFree beos
MaxMemFree event
MaxMemFree mpm_common
MaxMemFree mpm_netware
MaxMemFree mpm_winnt
MaxMemFree prefork
MaxMemFree worker
MaxRequestsPerChild event
MaxRequestsPerChild mpm_common
MaxRequestsPerChild mpm_netware
MaxRequestsPerChild mpm_winnt
MaxRequestsPerChild mpmt_os2
MaxRequestsPerChild prefork
MaxRequestsPerChild worker
MaxRequestsPerThread beos
MaxSpareServers prefork
MaxSpareThreads beos
MaxSpareThreads event
MaxSpareThreads mpm_common
MaxSpareThreads mpm_netware
MaxSpareThreads mpmt_os2
MaxSpareThreads worker
MaxThreads mpm_netware
MetaDir mod_cern_meta
MetaFiles mod_cern_meta
MetaSuffix mod_cern_meta
MimeMagicFile mod_mime_magic
MinSpareServers prefork
MinSpareThreads beos
MinSpareThreads event
MinSpareThreads mpm_common
MinSpareThreads mpm_netware
MinSpareThreads mpmt_os2
MinSpareThreads worker
ModMimeUsePathInfo mod_mime
MultiviewsMatch mod_mime
NWSSLTrustedCerts mod_nw_ssl
NWSSLUpgradeable mod_nw_ssl
NameVirtualHost core
NoProxy mod_proxy
Options core
Order mod_authz_host
PassEnv mod_env
PidFile beos
PidFile event
PidFile mpm_common
PidFile mpm_winnt
PidFile mpmt_os2
PidFile prefork
PidFile worker
ProtocolEcho mod_echo
ProxyBadHeader mod_proxy
ProxyBlock mod_proxy
ProxyDomain mod_proxy
ProxyErrorOverride mod_proxy
ProxyIOBufferSize mod_proxy
ProxyMaxForwards mod_proxy
ProxyPass mod_proxy
ProxyPassReverse mod_proxy
ProxyPassReverseCookieDomain mod_proxy
ProxyPassReverseCookiePath mod_proxy
ProxyPreserveHost mod_proxy
ProxyReceiveBufferSize mod_proxy
ProxyRemote mod_proxy
ProxyRemoteMatch mod_proxy
ProxyRequests mod_proxy
ProxyTimeout mod_proxy
ProxyVia mod_proxy
RLimitCPU core
RLimitMEM core
RLimitNPROC core
ReadmeName mod_autoindex
ReceiveBufferSize beos
ReceiveBufferSize mpm_common
ReceiveBufferSize mpm_netware
ReceiveBufferSize mpm_winnt
ReceiveBufferSize mpmt_os2
ReceiveBufferSize prefork
ReceiveBufferSize worker
Redirect mod_alias
RedirectMatch mod_alias
RedirectPermanent mod_alias
RedirectTemp mod_alias
RemoveCharset mod_mime
RemoveEncoding mod_mime
RemoveHandler mod_mime
RemoveInputFilter mod_mime
RemoveLanguage mod_mime
RemoveOutputFilter mod_mime
RemoveType mod_mime
RequestHeader mod_headers
Require core
RewriteBase mod_rewrite
RewriteCond mod_rewrite
RewriteEngine mod_rewrite
RewriteLock mod_rewrite
RewriteLog mod_rewrite
RewriteLogLevel mod_rewrite
RewriteMap mod_rewrite
RewriteOptions mod_rewrite
RewriteRule mod_rewrite
SSIEndTag mod_include
SSIErrorMsg mod_include
SSIStartTag mod_include
SSITimeFormat mod_include
SSIUndefinedEcho mod_include
SSLCACertificateFile mod_ssl
SSLCACertificatePath mod_ssl
SSLCADNRequestFile mod_ssl
SSLCADNRequestPath mod_ssl
SSLCARevocationFile mod_ssl
SSLCARevocationPath mod_ssl
SSLCertificateChainFile mod_ssl
SSLCertificateFile mod_ssl
SSLCertificateKeyFile mod_ssl
SSLCipherSuite mod_ssl
SSLCryptoDevice mod_ssl
SSLEngine mod_ssl
SSLHonorCipherOrder mod_ssl
SSLMutex mod_ssl
SSLOptions mod_ssl
SSLPassPhraseDialog mod_ssl
SSLProtocol mod_ssl
SSLProxyCACertificateFile mod_ssl
SSLProxyCACertificatePath mod_ssl
SSLProxyCARevocationFile mod_ssl
SSLProxyCARevocationPath mod_ssl
SSLProxyCipherSuite mod_ssl
SSLProxyEngine mod_ssl
SSLProxyMachineCertificateFile mod_ssl
SSLProxyMachineCertificatePath mod_ssl
SSLProxyProtocol mod_ssl
SSLProxyVerify mod_ssl
SSLProxyVerifyDepth mod_ssl
SSLRandomSeed mod_ssl
SSLRequire mod_ssl
SSLRequireSSL mod_ssl
SSLSessionCache mod_ssl
SSLSessionCacheTimeout mod_ssl
SSLUserName mod_ssl
SSLVerifyClient mod_ssl
SSLVerifyDepth mod_ssl
Satisfy core
ScoreBoardFile beos
ScoreBoardFile event
ScoreBoardFile mpm_common
ScoreBoardFile mpm_winnt
ScoreBoardFile prefork
ScoreBoardFile worker
Script mod_actions
ScriptAlias mod_alias
ScriptAliasMatch mod_alias
ScriptInterpreterSource core
ScriptLog mod_cgi
ScriptLog mod_cgid
ScriptLogBuffer mod_cgi
ScriptLogBuffer mod_cgid
ScriptLogLength mod_cgi
ScriptLogLength mod_cgid
ScriptSock mod_cgid
SecureListen mod_nw_ssl
SendBufferSize beos
SendBufferSize event
SendBufferSize mpm_common
SendBufferSize mpm_netware
SendBufferSize mpm_winnt
SendBufferSize mpmt_os2
SendBufferSize prefork
SendBufferSize worker
ServerAdmin core
ServerAlias core
ServerLimit event
ServerLimit mpm_common
ServerLimit prefork
ServerLimit worker
ServerName core
ServerPath core
ServerRoot core
ServerSignature core
ServerTokens core
SetEnv mod_env
SetEnvIf mod_setenvif
SetEnvIfNoCase mod_setenvif
SetHandler core
SetInputFilter core
SetOutputFilter core
StartServers event
StartServers mpm_common
StartServers mpmt_os2
StartServers prefork
StartServers worker
StartThreads beos
StartThreads mpm_common
StartThreads mpm_netware
SuexecUserGroup mod_suexec
ThreadLimit event
ThreadLimit mpm_common
ThreadLimit mpm_winnt
ThreadLimit worker
ThreadStackSize event
ThreadStackSize mpm_common
ThreadStackSize mpm_netware
ThreadStackSize mpm_winnt
ThreadStackSize worker
ThreadsPerChild event
ThreadsPerChild mpm_common
ThreadsPerChild mpm_winnt
ThreadsPerChild worker
TimeOut core
TraceEnable core
TransferLog mod_log_config
TypesConfig mod_mime
UnsetEnv mod_env
UseCanonicalName core
UseCanonicalPhysicalPort core
User beos
User event
User mpm_common
User mpmt_os2
User prefork
User worker
UserDir mod_userdir
VirtualDocumentRoot mod_vhost_alias
VirtualDocumentRootIP mod_vhost_alias
VirtualScriptAlias mod_vhost_alias
VirtualScriptAliasIP mod_vhost_alias
Win32DisableAcceptEx mpm_winnt
XBitHack mod_include

Let's take a look at the httpd.conf-example (default httpd.conf) file to see what has been loaded in the default configuration.

$ awk '/^[ \t]*#/ || /^[ \t]*$/ {continue} {print}' /etc/apache2/httpd.conf-example
ServerRoot "/usr/apache2"
Listen 80
LoadModule authn_file_module libexec/mod_authn_file.so
LoadModule authn_dbm_module libexec/mod_authn_dbm.so
LoadModule authn_anon_module libexec/mod_authn_anon.so
LoadModule authn_dbd_module libexec/mod_authn_dbd.so
LoadModule authn_default_module libexec/mod_authn_default.so
LoadModule authz_host_module libexec/mod_authz_host.so
LoadModule authz_groupfile_module libexec/mod_authz_groupfile.so
LoadModule authz_user_module libexec/mod_authz_user.so
LoadModule authz_dbm_module libexec/mod_authz_dbm.so
LoadModule authz_owner_module libexec/mod_authz_owner.so
LoadModule authz_default_module libexec/mod_authz_default.so
LoadModule auth_basic_module libexec/mod_auth_basic.so
LoadModule auth_digest_module libexec/mod_auth_digest.so
LoadModule file_cache_module libexec/mod_file_cache.so
LoadModule cache_module libexec/mod_cache.so
LoadModule disk_cache_module libexec/mod_disk_cache.so
LoadModule mem_cache_module libexec/mod_mem_cache.so
LoadModule dbd_module libexec/mod_dbd.so
LoadModule dumpio_module libexec/mod_dumpio.so
LoadModule ext_filter_module libexec/mod_ext_filter.so
LoadModule include_module libexec/mod_include.so
LoadModule filter_module libexec/mod_filter.so
LoadModule deflate_module libexec/mod_deflate.so
LoadModule log_config_module libexec/mod_log_config.so
LoadModule log_forensic_module libexec/mod_log_forensic.so
LoadModule logio_module libexec/mod_logio.so
LoadModule env_module libexec/mod_env.so
LoadModule mime_magic_module libexec/mod_mime_magic.so
LoadModule cern_meta_module libexec/mod_cern_meta.so
LoadModule expires_module libexec/mod_expires.so
LoadModule headers_module libexec/mod_headers.so
LoadModule ident_module libexec/mod_ident.so
LoadModule usertrack_module libexec/mod_usertrack.so
LoadModule unique_id_module libexec/mod_unique_id.so
LoadModule setenvif_module libexec/mod_setenvif.so
LoadModule version_module libexec/mod_version.so
LoadModule proxy_module libexec/mod_proxy.so
LoadModule proxy_connect_module libexec/mod_proxy_connect.so
LoadModule proxy_ftp_module libexec/mod_proxy_ftp.so
LoadModule proxy_http_module libexec/mod_proxy_http.so
LoadModule proxy_ajp_module libexec/mod_proxy_ajp.so
LoadModule proxy_balancer_module libexec/mod_proxy_balancer.so
LoadModule ssl_module libexec/mod_ssl.so
LoadModule mime_module libexec/mod_mime.so
LoadModule dav_module libexec/mod_dav.so
LoadModule status_module libexec/mod_status.so
LoadModule autoindex_module libexec/mod_autoindex.so
LoadModule asis_module libexec/mod_asis.so
LoadModule info_module libexec/mod_info.so
LoadModule suexec_module libexec/mod_suexec.so
LoadModule cgi_module libexec/mod_cgi.so
LoadModule dav_fs_module libexec/mod_dav_fs.so
LoadModule vhost_alias_module libexec/mod_vhost_alias.so
LoadModule negotiation_module libexec/mod_negotiation.so
LoadModule dir_module libexec/mod_dir.so
LoadModule imagemap_module libexec/mod_imagemap.so
LoadModule actions_module libexec/mod_actions.so
LoadModule speling_module libexec/mod_speling.so
LoadModule userdir_module libexec/mod_userdir.so
LoadModule alias_module libexec/mod_alias.so
LoadModule rewrite_module libexec/mod_rewrite.so
<IfModule !mpm_netware_module>
User webservd
Group webservd
</IfModule>
ServerAdmin you@yourhost.com
ServerName 127.0.0.1
DocumentRoot "/var/apache2/htdocs"
<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>
<Directory "/var/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>
<FilesMatch "^\.ht">
    Order allow,deny
    Deny from all
    Satisfy All
</FilesMatch>
ErrorLog /var/apache2/logs/error_log
LogLevel warn
<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog /var/apache2/logs/access_log common
</IfModule>
<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/var/apache2/cgi-bin/"
</IfModule>
<IfModule cgid_module>
</IfModule>
<Directory "/var/apache2/cgi-bin">
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>
DefaultType text/plain
<IfModule mime_module>
    TypesConfig /etc/apache2/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
</IfModule>
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>
<IfModule prefork.c>
    ListenBacklog 8192
    ServerLimit 2048
    MaxClients 2048
</IfModule>

So, if we want to remove mod_dav module from the httpd.conf, we need to make sure
Dav, DavDepthInfinity, DavMinTimeout
are not mentioned in the httpd.conf file.

Labels: , , ,

Thursday, May 17, 2007

RSS Feed from Government Sites ? One only

I was asked to write a feed aggregration for a project, so I tried to aggregrate the government related sites (150+) as an examples. Guess what, all of those sites that are available do not have RSS or Atom feed provided in their HTML header, execpt the official government site.

Tcl program was written using packages such as http and tDOM to do this exploratory work. BTW, ActiveTcl from ActiveState has a lot of these extensions pre-compiled. I extracted all the govt related sites from their "A-Z Government List" and looped through all these sites to see whether they provide feed in their header. A snippet of the Tcl using XPath syntax to locate the feed link is:

set result [$root selectNode {//link[@type="application/rss+xml" or @type="application/atom+xml"]}]
if { [llength $result] > 0 } {
 puts "Yes - $url"
} else {
 puts "No  - $url"
}

So the big question is: Why there isn't any feed ? May be it is embedded in the html body instead of head, or there is intellectual property in the feed that is too valuable to expose to the rest of the world.

Anyway, I will let you to figure that out.

Labels: , , ,

Thursday, May 03, 2007

Web Scraping, the Tcl way

My office's resource booking system does not provide a birdeye view of the availability of resource (meeting rooms). This seems to be another good opportunity to web scrap it with Tcl (with tDOM) to reformat the data into something more user friendly.

HTML data is read and DOM tree is built (set doc [dom parse -html $data]). Once we have the DOM, it is pretty easy to locate the information using XPath

This is a snippet of the HTML code:

<table>
<tr class='DashNavCurDashArea'>
<td align=left valign=top height=60><b>3</b>
<br><font size=1>
<a Title='boardroom: user1' href="display_event.asp?Pkey=13931"><img src=image/R.gif border=0 alt='boardroom: user1'>
10:00-12:00
</font></a><br>
<font size=1>
<a Title='room3: user2' href="display_event.asp?Pkey=13948"><img src=image/R.gif border=0 alt='room3: user2'>
13:30-15:00
</font></a><br>
<font size=1>
<a Title='boardroom: user3' href="display_event.asp?Pkey=13938"><img src=image/R.gif border=0 alt='boardroom: user3'>
16:30-18:00
</font></a><br>
...
With tDOM, you can locate all the resources (or nodes) booked today and then loop through them to extract the username and timeslot.
set todayNode [$root selectNode "//table/tr\[@class='DashNavCurDashArea'\]/td\[b/text()=\"$today\"]"]
foreach node [$todayNode selectNode {font/a/img[@src="image/R.gif"]}] {
 foreach { r u } [split [$node getAttribute alt] {:}] {}
 set room [string trim $r]
 set user [string trim $u]
 set time [string trim [[$node nextSibling] nodeValue]]
}

Since the resource booking timeslot interval is 10 minute, I create a HTML table with 144 (24*6) columns to represent each and every interval in a day. If a particular resource at a particular interval is taken, the table cell will be filled by a 1x1 pixel image (in red, but resize to 5x10). Also, they will be hyperlinked to itself (#) with attribute title set to the username so that the username will be displayed when mouse over it.

Before:

After:

Labels: , , , ,

Saturday, March 24, 2007

Web Site Response Time

I was asked to monitor the response time of one of our managed hosting customers' site. The reason for doing it is to cover somebody's backside in case they were asked "why the site is so slow one ha?" (in Singlish). I can tell you that I hate to do this type of thing, but what can I do....

Anyway, I used one of the Solaris zones and compiled Tcl with tDOM, and httperf. These are the steps that I used:

  1. Download the home page html using Tcl with http package
  2. Parse the html and convert that to a DOM tree with tDOM
  3. Retrieve all the dependencies (image, flash, javascript, css, ...)
  4. Write a temporary file of the html + dependencies, this will be used as the httperf's session workload input file (see -wsesslog option)
  5. Execute httperf with 2 concurrent connections (that's normally configured in web browsers)
  6. Append the data in RRD update format
  7. RRD update format will be cut and paste to my auto graph generator S.T.A.R.

Here is the output graph

The home page consists of 17 thumbnail photos (in jpg format) and other stuff. However, these jpeg files are of size of 225x141 and they are all forced to display in 125x71. If we were to convert these thumbnail photos to the correct size (125x71), we could have saved 364,107 bytes. According to my calculation, the response time of the home page will be reduced by a maximum of 0.93 seconds on a 1.5Mbps internet connection.

The above was put forward to the developer, but I was told the 225x141 size photos were being used in another location. Instead of creating another set of thumbnails for the home page, the thumbnails were forced to display smaller (125x71). Of course it works by wasting a lot of bandwidth and making the home page load slower.

The developer may not know that this can be easily done in Solaris. FYI, ImageMagick is now a built-in utility in Solaris. It is located under the /usr/sfw directory and the package name is SUNWimagick. A script like this can create another set of thumbnails of size 125x71.

PATH=/usr/sfw/bin:$PATH; export PATH
LD_LIBRARY_PATH=/usr/sfw/lib:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH
for i in *jpg
do
new="`basename $i .jpg`_s.jpg"
convert $i -resize 125x71 $new
done
It took 5 seconds on my X4500 to create another set of thumbnails for the home page. With a one time effort of 5 seconds CPU time, you are likely to reduce the home page response time by almost 1 second. The choice is yours. From the above graph, you can see the response time reduced by almost a seconds after 22 March. FYI, the above was proposed to the developer on the 15 March.

Labels: , , , , ,