14 May, 2014

Validate PATH environment variable entries - OS

Following on from the post where I wrote about managing the entries in the PATH environment variable to avoid OS and application misbehaviour, I thought I'd share another story on PATH which can also show you why we (IT guys) should never forget the basics and that the simplest idea is the best idea!

I've come across some hosts where the PATH was more than 2048 characters long which made applications stop working. OK, no problem (I thought), I just run my script which removes duplicates from the PATH and it should go well under 2048 characters. I'm not an overconfident guy, but I was surprised when I saw the length still well above 2000. Now what? Then it hit me, why do I take it for granted that all these entries in the PATH are needed? Maybe there are PATH entries which don't even exist on the file system anymore! Simple, isn't it, just get rid of garbage from the environment variable.

Let's run through the PATH entries one by one and check if those folders exist on the box at all - important: if you do this on a cluster node where one of the PATH entries points to one of the clustered drives, you can incorrectly identify that folder as non existent, but in reality the folder exists, it's just on a disk which is active on another node of the cluster at that time, so be careful.

Of course we want to do this remotely:
$srv = "r2d2"
$pathString = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $srv).OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\Environment").getvalue("path")

$pathstring.split(";") | %{
$obj = "" | Select Item,Accessible
$obj.Item = $_.trim()
$obj.Accessible = test-path ("\\$srv\" + $obj.item.replace(":","$"))
$obj}

Make it shorter by creating the output object on the fly:
$srv = "r2d2"
$pathString = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $srv).OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\Environment").getvalue("path")

 
$pathstring.split(";") | %{
New-Object psobject -Property @{test=(test-path $_); item=$_}
} | ft item,test -auto

Or you can do it locally on a host (which makes it simpler and it can even be a oneliner:
(Get-ItemProperty "HKLM:SYSTEM\CurrentControlSet\Control\Session Manager\Environment").path.split(";") | %{new-object psobject -Property @{test=(test-path $_); item=$_}} | ft item,test -auto

This will show you something like:


You can make this a script by adding parameters, get the list of hosts from $input...etc.

t