Tuesday 8 October 2013

Windows: Concatenate output from multiple commands & output redirection

I was trying to be creative and flex my rusty Windows shell/DOS/cmd scripting using findstr, nslookup and Windows/DOS command redirection...

I was having to repeatedly run the same commands over and over with as few keystrokes as possible:

ipconfig /flushdns >null 2>1 && nslookup SERVER1 && nslookup SERVER2 && ...
  • >null
    This gets rid of normal output (STDOUT, or Standard Output) from displaying on the screen.  Normally STDOUT is connected to the current terminal (command window), so I redirect to the built-in black hole, which is file descriptor 'null', or device /dev/null in UNIX/Linux.
  • 2>1
    This gets rid of error messages from the screen (STDOUT).  When redirecting both STDOUT and STDERR from a single command they have to appear in numerical order of their codes, so it goes STDIN(0), STDOUT(1), STDERR(2).  '2>1', effectively says "redirect file descriptor 2 (STDERR) to the same place that we've sent 1 (STDOUT).
  • &&
    I only want the subsequent nslookup commands to run if the first one, flushdns is successful (if its return code is >0, zero being success in Windows/DOS), so I use '&&' (same in UNIX/Linux).
Now I wanted to concatenate the output from all the commands into a single string and then strip out matching lines... Just wrap the commands in normal parentheses (like this):

( ipconfig /flushdns >null 2>1 && nslookup SERVER1 && nslookup SERVER2 ) | findstr /b "N A"

The 'b/' tells findstr to match beginning of lines.  Putting the search terms in double quotes separated with spaces means use logical ORs so it matches any one of them.  So we end up with the output we're looking for:

( ipconfig /flushdns >null 2>1 && nslookup SERVER1 && nslookup SERVER2 && nslookup SERVER3  ) | findstr /b "Server Name Address"
Server:  gs1gpcmadcv01.gphc.local
Address:  172.16.82.1
Name:    GPHCDMZWS01.gphc.local
Address:  172.17.82.10
Server:  gs1gpcmadcv01.gphc.local
Address:  172.16.82.1
Name:    GPHCDMZDWWS01.gphc.local
Address:  172.17.82.11
Server:  gs1gpcmadcv01.gphc.local
Address:  172.16.82.1
Name:    GPHCDMZDWSTG01.gphc.local
Address:  172.17.82.13

If wish I knew how to strip out the two lines that relate to the DNS server itself - it gives the name of the Server and its Address before the target host we're resolving.  Maybe grep/awk on UNIX/Linux would be easier than figuring out how to handle line breaks with findstr, which doesn't seem to handle them at all without some dos scripting black magic!

Wednesday 21 August 2013

Using Windows 7 runas for dsa.msc mmc causes error 740: The requested operation requires elevation.

Microsoft's User Account Control in Windows 7 Professional

This is my first really bad experience with Microsoft's new User Account Control (UAC).  Something caused our long-used and well trusted service account to be disabled.

After installing Windows Server 2003 Administrative Tools Pack so I can use MMC snap-in "Domain Users and Computers" (dsa.msc) on my local PC and after a few runas error 193, I kept getting the following error message:

C:\>runas /user:"domain\username" "mmc %windir%\system32\dsa.msc"
Ento start mmc C:\Windows\system32\dsa.msc as user "domain\username" ...
RUNAS ERROR: Unable to run - mmc C:\Windows\system32\dsa.msc
740: The requested operation requires elevation.

The solution was to call 'cmd /c' which tells 'cmd' to open and run the command supplied as a parameter, which is our mmc command:

C:\>runas /user:"domain\username" "cmd /c mmc %windir%\system32\dsa.msc"
Enter the password for domain\username:
Attempting to start cmd /c mmc C:\Windows\system32\dsa.msc as user "domain\username" ...


...now it works! :)


Sunday 4 August 2013

Oracle database connections lost contact across firewalls/networks

The Problem:

At work during the quietest periods of activity, our database connections would sometimes become unusable and create an exception when used.  It took us a lot of effort to track down the problem to firewalls killing them without ADO.NET knowing.  This tended to happen with Oracle and the exception was one of the following:
  • ORA-03135: connection lost contact
  • ORA-03113: end-of-file on communication channel
The comms goes like:

Internet-based-client =firewall=> DMZ service =firewall=> DB-on-private-LAN


The Cause

The connections were created in the DMZ and traversed the network boundary through the firewall and to the DBMS in the private LAN.  This firewall was set to automatically kill idle TCP/IP sessions after a max time period (I'm informed this is normal behaviour.  With connection pooling turned on (default), ADO.NET will only know a connection has been severed in this way the next time it tries to use it.

Example: User X uses our website, creating a new connection and once their website session ends, the connection is returned to the pool.  The firewall kills the TCP/IP session used by the database connection because it's timed out through inactivity.  User Y uses the website which tries to reuse the database connection and it fails with an exception.


The Solution

We can limit the max lifetime of a connection to prevent connections sitting idle for too long either:
  • Employ a custom solution for retrying, clearing connection pool, etc.
  • Using 'Connection Lifetime=XXXX' in the connection string.
  • Setting SQLNET.EXPIRE_TIME on the client (if using full, non-xcopy version of the Oracle client), or on the server (sqlnet.ora file in ORACLE_HOME\network\admin).

At first we employed a custom solution that retried opening connections, clearing pools and all sorts of black magic!.  Now we've learnt of connection string setting 'Connection Lifetime':


Connection Lifetime
  • MSDN: When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified.  Default is 0.
  • To mitigate against severed connections eg across firewalls and networks, ensure to set a timeout value.  We're starting with a value of 3200 (1hr).