So,
let's say that you wanted to have a script on your dbTier that will
reach out to your appsTier and shut down the applications. Maybe
this is your system-level shutdown script so that when the Unix
administrator shuts down the dbTier, everything is shut down nice and
neat like...
For
the purpose of this exercise, we're going to need to assume that the
APPS password is known to the script (how you do that might be the
subject of another blog posting). We're also going to assume that
the Unix environment is set automatically (and without prompting) on
the remote system.
So,
how do you do it?
Well,
first you have to set up ssh pre-shared keys. This will allow you to
login without being asked for a password. (See my earlier posting:
Password-less
Login Using SSH Pre-Shared Keys)
Once
that is configured, you can use a command like this:
ssh
applmgr@myappstier.mydomain "cd
${ADMIN_SCRIPTS_HOME};./adstpall.sh apps/${APPSPW}" 2>&1
|tee -a ${LOG}
A
few things here. First, you'll notice that I'm actually executing
TWO commands remotely. The "cd"
to change directories and then the adstpall.sh
script (the semicolon allows me to do that in Unix). Secondly,
there are environment variables. Here's the thing about those
environment variables. In the command above, they are NOT evaluated
on the target system. They are evaluated locally on the SOURCE
system. If you want to use variables that are local to the target,
you're going to have to "escape" them.
For
example, this one will use a variable evaluated on the source
machine:
ssh
applmgr@myappstier.mydomain "echo ${CONTEXT_NAME}"
And
this one will use a variable evaluated on the target machine:
ssh
applmgr@myappstier.mydomain 'echo ${CONTEXT_NAME}'
Similarly,
you can evaluate a variable on the target by “escaping” it:
ssh
applmgr@myappstier.mydomain "echo \${CONTEXT_NAME}"
At
one client, their standard is to use a script that wraps around the
standard "oraenv"
to set their environment variables. As a result, every time they
log in, they are greeted with a prompt asking them to choose their
environment.
This
raised an interesting problem for some of the automated processes we
were trying to deploy. The automation was driven from a remote box
and would need to ssh over to a target box and issue commands. So,
how do we configure the environment so that a user logging in
interactively is prompted and one issuing a command remotely through
ssh isn't? Well, it turns out that, on Linux at least, that remote
command doesn't get assigned a TTY. So, we've made a change to the
.bash_profile on the target node that
looks something like this:
if
tty | fgrep pts ; then
#
# Normal,
interactive logins
#
export
ORAENV_ASK=YES
else
#
# Human-less
logins (ssh "command")
# (Suppress
output and bypass prompting for oracle environment)
#
export
ORAENV_ASK=NO
fi
Now,
let's assume you want to be a little more elaborate. You want to
clean up extraneous output and capture the results of the command in
your logfile (represented by the environment variable ${LOG}):
ssh
applmgr@myappstier.mydomain ". ./.bash_profile 2>&1
1>/dev/null;cd ${ADMIN_SCRIPTS_HOME};./adstpall.sh apps/${APPSPW}"
2>&1 |tee -a ${LOG}
Or,
maybe you'd like to do something in SQL*Plus on a remote system?
ssh
applmgr@myappstier.mydomain “. ./.bash_profile 2>&1
1>/dev/null;sqlplus apps/${APPSPW}” <&1
1>>${LOG}
select
sysdate from dual;
EOF
This
will redirect stderr to stdout, and send both to your logfile
(${LOG}).
Pay close attention to the line containing the EOF.
It has to be the ONLY thing on the line (not even a trailing space!)
– James