Thursday, June 30, 2011

Using PowerShell to modify Apache httpd.conf files

Now, you might think this is easy and straightforward.  But when you touch an httpd.conf file with PowerShell – manipulate the contents of the file a bit and then write it back.  Then turn around and start the Apache service and all you get back is “invalid function” – this simple solution becomes a major achievement.

The root to this whole issue I found described in a powershellcommunity.org forum post:  “When you Get-Content, it returns an array of strings, and somewhere between assigning the array to the Body property, it is stripping out the formatting”

This poster had it close.  It is not that manipulating the object is stripping out formatting, it is actually that it is inserting some.

Another clue came from Linux.com:

image

The key is in the first paragraph I included:  “Every operating system uses a special character (or sequence of characters) to signify the end of a line of text. They cannot use standard, common characters to represent the line end, because those could appear in normal text, so they use special, nonprinting characters -- but each operating system uses different ones:”

The other bit of information that I needed was that the application I was using actually runs Apache on Windows.  Apache being a Linux-centric application the pieces were beginning to fall into place.

So, the application generates a template httpd.conf file that I read in: 

$confFile = get-item -path $confFilePath

$conf = (get-content $confFile)

I create a new array abject to write my modifications to: $newConf = @()

I do this because the $conf (the contents of the configuration file) PowerShell actually treats as a String Array.  So, to read each line and find the lines and contents I want to change just needs a foreach loop and a switch.

foreach ($e in $conf) {
    $newConf += $e
    switch -wildcard ($e) {
        "Multiplexer*" {$newConf += "ProtocolMultiplexer " }
        "#Listen*" {$newConf += "Listen " + $Ipv4 }
     }
}
$conf = $newConf  # save the new array back to the original in memory, overwriting the original
Clear-Variable -Name newConf  # clear the variable to prevent duplication, why not reuse the variable.
$newConf = @()  # it has to be cast to an array again.

Now, if I didn’t create the empty array $newConf and just let the loop shove the lines in as it goes I end up with a big text blob.  Not very easy to find and edit things, nor does it give me a usable format to write out.

In the script I repeat this manipulation, inserting sections, modifying lines, etc.

At the end I write the file back out. and I start my Apache engine.

I tried Out-File, I tried Set-Content, I try Add-Content – nothing was working and this is a 200+ line configuration file.  This is when I started researching and thinking about the little tidbits I mentioned at the beginning.

In the end the solution was really rather simple – strip out all the formatting.  The following little loop fixed it all:

foreach ($e in $conf) {
    if ($e -ne $NULL) {
        $e = $e -replace "\r\n",""
        $e = $e -replace "\r", ""
        $e = $e -replace "\n", ""
        Add-content -path $confFile.FullName -Value "$e"
    }
}

Since I am using Add-Content I deleted the original (incomplete)  file prior to writing.  Those replacement strings are the regex representations of the  new line designators the Linux.com article describes.

After I stripped the file of all newline characters (which editors don’t show) then the Apache service started right up.

No comments: