When working on servers with multiple ORACLE_HOMEs, keeping a session's Oracle-related environment variables in alignment is critical to an administrator's sanity. Different versions of the RDBMS or application server software can require different binaries and shared libraries, and different ORACLE_HOMEs may have different network setups. An improperly configured Oracle environment can lead to TNS errors when attempting to connect to a database ("Oh, it's trying to use that tnsnames.ora..."), restarts of the wrong app server ("Wait a minute, which opmnctl did I just run?"), or wasted weekend afternoons (I once sat on the phone w/ Oracle Support for 3 hours because $ORACLE_HOME/ctx/lib was not in my LD_LIBRARY_PATH. Good times!).
Oracle addresses the need for managing environment configuration with the 'oraenv' script, and with the various environment files that need to be sourced to work in the different contexts of Oracle Applications. Furthermore, a number of common utilities on the application server side of the world, such as emctl and opmnctl, are shell scripts that explicitly set the Unix environment before launching processes that do actual work. For some systems, however, these tools may not be enough. For example, the oraenv script does not set TNS_ADMIN, and does not remove any custom additions to the PATH environment variables that are based on a previous value of ORACLE_HOME.
Some simple solutions
There are a number of simple ways to prevent your Unix session environment from becoming a tangled mess of inappropriate paths, without resorting to setting individual environment variables manually, including:
- Don't switch Oracle environments during a session. Instead, always start a new session to work in a new environment. This is can be good for maintaining personal discipline, but a bit tedious in practice, and besides, if I stopped there I wouldn't have much of a blog post, would I?
- Create separate shell scripts to do the work of setting up the environment variables needed, appending or prepending Oracle-related values. This is a common practice, but after switching back and forth between environments a few times, the PATH environment variable can grow from this:
/u01/app/oracle/product/client/10gR2/bin:/u01/app/oracle/product/client/10gR2/OPatch: /u01/app/oracle/product/client/10gR2/opmn/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin: /opt/oracle/bin
...to something like this admittedly contrived monstrosity:
/u01/app/oracle/product/client/11gR1/bin:/u01/app/oracle/product/client/11gR1/OPatch: /u01/app/oracle/product/client/11gR1/opmn/bin:/u01/app/oracle/product/client/10gR2/bin:/u01 /app/oracle/product/client/10gR2/OPatch:/u01/app/oracle/product/client/10gR2/opmn/bin:/u01/app /oracle/product/client/11gR1/bin:/u01/app/oracle/product/client/11gR1/OPatch:/u01/app/oracle/product /client/11gR1/opmn/bin:/u01/app/oracle/product/client/10gR2/bin:/u01/app/oracle/product/client /10gR2/OPatch:/u01/app/oracle/product/client/10gR2/opmn/bin:/usr/kerberos/bin:/usr/local/bin:/bin: /usr/bin:/opt/oracle/bin
Alternately, instead of appending/prepending values to the environment variables, you could just reset them to default values, but those defaults may vary across servers, which can decrease portability of your scripts.
- Unset all Oracle-related environment variables manually before setting up the new Oracle environment. This works well for things like ORACLE_HOME and TNS_ADMIN, but what about PATH and LD_LIBRARY_PATH? Doing 'unset PATH' is a surefire way to wreck a perfectly good session, and resetting PATH by copying only the elements you wish to preserve can be error-prone.
I'd like to have a method to unset just the Oracle environment in my session; that is, it should remove references to the current ORACLE_HOME from the environment and leave other environment variables untouched. What I've settled on is the code shown below, which can be adapted into a shell function, dropped into an existing environment setup script, or placed in a standalone script:
#!/bin/bash #Remove references to current ORACLE_HOME in various environment variables. #Do nothing if ORACLE_HOME is not set if [[ -n $ORACLE_HOME ]] then echo "Removing ORACLE_HOME references from environment" echo "Old ORACLE_HOME: $ORACLE_HOME" export LD_LIBRARY_PATH=`echo $LD_LIBRARY_PATH | sed "s#$ORACLE_HOME[^:]*:*##g"` # Include additional lines for clearing CLASSPATH, PERL5LIB, etc. as # needed *before* modifying PATH export PATH=`echo $PATH | sed "s#$ORACLE_HOME[^:]*:*##g"` unset TNS_ADMIN ORACLE_HOME ORACLE_SID ORACLE_BASE fi
Here's a demo:
[oracle@lyta ~]$ . setup_11gR1.env [oracle@lyta ~]$ echo $ORACLE_HOME; echo $LD_LIBRARY_PATH; echo $PATH /u01/app/oracle/product/client/11gR1 /u01/app/oracle/product/client/11gR1/lib /u01/app/oracle/product/client/11gR1/bin:/u01/app/oracle/product/client/11gR1/OPatch:/u01/app/oracle/product/client/11gR1/opmn/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/opt/oracle/bin [oracle@lyta ~]$ . clear_oracle Removing ORACLE_HOME references from environment Old ORACLE_HOME: /u01/app/oracle/product/client/11gR1 [oracle@lyta ~]$ echo $ORACLE_HOME; echo $LD_LIBRARY_PATH; echo $PATH /usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/opt/oracle/bin
Since one person's completely sensible regular expression can be another person's incomprehensible line noise, here are some notes on the regex used in the sed command:
- Uses # instead of the traditional / as a separator to prevent errors resulting from interpolation of the $ORACLE_HOME environment variable.
[^:]*matches zero or more non-colon characters. Since the colon is the separator for entries in the path, this prevents the regex from matching more than one entry at a time.
:*removes the colon from the end of a matched path entry, so the revised path doesn't contain a string of useless separators (
I may have just presented a solution in search of problem. On the other hand, I've found this to be useful, so maybe you will, too. If so, please leave a glowingly grateful comment. If not, then I've just revealed myself to the entire Internet as a slightly obsessive geek. There's a first time for everything.