Tuesday, April 16, 2013

An Unexpected Impact of LANG

In the process of trying to sort a delimited character string for a bash script I came across a situation where the setting of LANG at the OS-level impacted the results.  In my situation I was working on a script for monitoring Oracle services by comparing "srvctl configure" output with "srvctl status" output.  Since services that cross multiple instances may list those instances in various orders, I wanted to make sure the listing was always sorted for a proper comparison.

While a simple stream of "echo | tr ' ' '\n' | sort | tr '\n' ' ' | sed 's/,$/\n/'" works just fine, I found that when testing the monitor script across all our servers I was getting different results.  Looking closer I found that the difference was related to running the script locally vs. via SSH.

After a bit of debugging I came up with a simple example to show the issue:

Create a file with 4 rows of numbers, with varying leading spaces.

% echo "1
2
3
   4" >x.dat

Next, sort the file locally.

% sort x.dat
1
2
3
   4

 Last, sort the file on the same server (I'm connect to lnx261) but pretend it's a remote operation via ssh.

% ssh oracle@`hostname -s` 'sort x.dat'
   4
2
1
3

For both sorts the same file was used and run on the same server.  What would there be a difference?

LANGUAGE!  Your OS LANG setting affects sorts, just like NLS* settings do in Oracle.  Most session-level settings are not set when you SSH.  So either sourcing the appropriate profile (/etc/profile, ~/.bash_profile, etc.) or setting LC_ALL within your SSH session will give you the expected results:

% ssh oracle@`hostname -s` 'export LANG=en_US.UTF-8; sort x.dat'
1
2
3
   4

Although I knew issues related to NLS_DATE_FORMAT not being set I had never previously run into issues with LANG.  Fortunately Enterprise Manager's agent (as part of $ORACLE_HOME/bin/nmo) runs through a full process creation so that your various profile scripts get sourced when you execute EM Jobs or simply run "Execute Host Command".