Not able to connect to Oracle DB from Shell Script - shell

I am having challenge connecting to Oracle DB (Load Balanced environment - Multiple host) from Shell Script.
I tried the following in linux box directly and it's working.
/apps/oracle/product/11.2.0/client_1/bin/sqlplus
/#'(DESCRIPTION=(ADDRESS_LIST=(FAILOVER = YES)
(ADDRESS = (PROTOCOL=TCP)(HOST=hostname1)(PORT = 6235)) (ADDRESS =
(PROTOCOL = TCP)(HOST = hostname2)(PORT = 1521))) (CONNECT_DATA =
(SERVER = DEDICATED) (SERVICE_NAME = lruata1)))'
When I tried the same from shell script (reading the db connect url from environment script) its not working.
Getting output as sqlplus parameters
SQL*Plus: Release 11.2.0.1.0 Production
Copyright (c) 1982, 2009, Oracle. All rights reserved.
Use SQLPlus to execute SQL, PL/SQL and SQLPlus statements.
Usage 1: sqlplus -H | -V
-H Displays the SQL*Plus version and the
usage help.
-V Displays the SQL*Plus version.
content from config.sh
oracle.base=/apps/oracle/product/11.2.0/client_1
db.connect.url='(DESCRIPTION=(ADDRESS_LIST=(FAILOVER = YES) (ADDRESS = (PROTOCOL=TCP)(HOST=hostname1)(PORT = 6235)) (ADDRESS = (PROTOCOL = TCP)(HOST = hostname2)(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = lruata1)))'
log.path=/apps/lriservers/bpmdbo_scripts/logs
Reading the key & Value in the main script
function getPropertyFromFile()
{
propertyName=`echo $1 | sed -e 's/\./\\\./g'`
fileName=$2;
cat $fileName | sed -n -e "s/^[ ]*//g;/^#/d;s/^$propertyName=//p" | tail -1
}
export ORACLE_BASE=`getPropertyFromFile oracle.base $CONFIG_FILE`
export CONNECT_IDENTIFIER=`getPropertyFromFile db.connect.url $CONFIG_FILE`
export LOG_PATH=`getPropertyFromFile log.path $CONFIG_FILE`
export ORACLE_HOME=${ORACLE_BASE}
echo "Oracle Base : "$ORACLE_BASE
echo "Connect Identifier : "$CONNECT_IDENTIFIER
echo "Log Path : "$LOG_PATH
export LD_LIBRARY_PATH=${ORACLE_HOME}/lib
export SQP=${ORACLE_HOME}/bin/sqlplus
LOG_FILE=$LOG_PATH/$ENV_NAME'_'$DEPLOYMENT_VERSION.log
cd $SCRIPT_HOME
CONNECT_STRING=${DB_USERNAME}/$DB_PASSWORD#${CONNECT_IDENTIFIER}
${SQP} -S ${CONNECT_STRING} << EOF
WHENEVER SQLERROR EXIT SQL.SQLCODE;
SET ECHO ON;
SET SERVEROUTPUT ON;
spool $LOG_FILE
#$SCRIPT_NAME
spool off;
EXIT
EOF
Regards
Balaji Subramaniam

Related

Can not connect to oracle outside docker container

I have create an image for the oracle 19c. I have started my container with below command.
docker run --name oracledb -d -p 1527:1521 -p 5700:5500 -e ORACLE_PWD=password1 -e ORACLE_CHARACTERSET=AL32UTF8 -v /d/docker-code/oracle-data oracle/database:19.3.0-ee
After creation of container, I am able to login in the container. I am able to connect with the below command inside the container.
sqlplus system/password1#172.17.0.2:1527/ORCLCDB
Outside of the container, from the cmd, I can not connect to that oracle instance.
Note: I have already installed oracle on the windows machine at port 1521 which is default port.
listener.ora
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
(ADDRESS = (PROTOCOL = TCP)(HOST = 172.17.0.2)(PORT = 1527))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(GLOBAL_DBNAME = ORCLCDB)
(ORACLE_HOME = /opt/oracle/product/19c/dbhome_1)
(SID_NAME = ORCLCDB)
)
)
DEDICATED_THROUGH_BROKER_LISTENER=OFF
DIAG_ADR_ENABLED = off
tnsnames.ora
ORCLCDB=172.17.0.2:1527/ORCLCDB
ORCLPDB1=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 172.17.0.2)(PORT = 1527))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ORCLPDB1)
)
)
I am not able to connect from SQL Developer or from CMD. I am able to get timeout error when I am trying to access outside of the docker container.
ERROR:
ORA-12170: TNS:Connect timeout occurred
Please guide me to resolve this issue.
Thanks in Advance.
Make sure all container network interfaces are listening for database traffic, hence 0.0.0.0. Do not hardcode a docker bridge network address (172..) because this address will be assigned at container startup. Just stick with the default port 1521 local to the container. This port - 1521 - is local to the container and not exposed to the host OS. You publish this port to the host OS where you decide which port to use, hence -p 1522:1521
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
(ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
)
)
Now you can fire up the container on your host OS by issuing:
docker run --name oracledb -d -p 1522:1521 -p 5700:5500 -e ORACLE_PWD=password1 -e ORACLE_CHARACTERSET=AL32UTF8 -v /d/docker-code/oracle-data oracle/database:19.3.0-ee
This should now work
sqlplus system/password1#localhost:1522/ORCLCDB
Tip. You can now pull Oracle XE 18c from Docker Hub. I recommend you to test this image if you still cannot connect using the image you have built.
docker run -d -p 1522:1521 --rm -e ORACLE_PASSWORD=Welcome_1 -v oracle-volume:/opt/oracle/oradata gvenzl/oracle-xe
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
97ce7cd3d7ca gvenzl/oracle-xe "container-entrypoin…" About an hour ago Up About an hour 0.0.0.0:1522->1521/tcp elegant_borg
sqlplus system/Welcome_1#localhost:1522/XE
SQL*Plus: Release 19.0.0.0.0 - Production on Mon May 31 10:21:18 2021
Version 19.8.0.0.0
Copyright (c) 1982, 2020, Oracle. All rights reserved.
Last Successful login time: Mon May 31 2021 10:20:19 +02:00
Connected to:
Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0
system#XE> set echo on
system#XE> #pdbs
system#XE>
system#XE> col con_id format 999
system#XE> col dbid format 99999999999999999
system#XE> col name format a30
system#XE> col open_mode format a10
system#XE> col open_time format a38
system#XE>
system#XE> select p1.con_id, p1.dbid, p1.name, p2.status, p1.open_mode, p1.open_time
2 from
3 v$pdbs p1 join dba_pdbs p2 on (p1.con_id = p2.con_id);
CON_ID DBID NAME STATUS OPEN_MODE OPEN_TIME
------ ------------------ ------------------------------ ---------- ---------- --------------------------------------
2 1957965804 PDB$SEED NORMAL READ ONLY 31.05.2021 06:54:00474 AM +00:00
3 4267393270 XEPDB1 NORMAL READ WRITE 31.05.2021 06:54:01229 AM +00:00
2 rows selected.
system#XE>
Best of luck!

How to connect to Oracle DB in shell script to execute multiple SQL queries

I am trying to connect Oracle DB to execute multiple SQL scripts and am using the DB properties file to get the database connection properties also it has the date parameters passed from shell script, I used below to execute but it gives me an error stating invalid connection.
......
for (( i=1;i<=$Dbcount;i++ ))
do
sqlplus -S ${user1}#$CONNECTIONNAME_$i/${Password} <<-EOF &
spool /data/sqlcsvwaydb_$i.csv
#query.sql $date1 $date2
exit
EOF
.......
But when I use same connection with below code it does execute it. Is there anything wrong in above method? Note I used DB properties file to get the DB count and user password extra.
............
sqlplus -S ${user1}#$CONNECTIONNAME_${i}/${Password} #query.sql
............
It should be user/password#connection
Also I'd suggest to put spool and exit into the same sql script
I decided to break your script down into pieces, then – proving each part in turn, build it out piece by piece.
First, just a simple proof that the loop control itself does what you expect: I named the script ‘doit.sh’. For the first iteration, I simply populate all of the environment variables that you referenced, then simply execute the loop with some ‘echo’ to prove what it is generating:
====
oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
do
echo $i
done
And executing it
oracle:oklacity$ doit.sh
1
2
3
oracle:oklacity$
====
So, we know the loop control itself works, let’s see how it expands your connection string:
oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
do
echo Connecting with ${user1}#$CONNECTIONNAME_$i/${Password}
done
And executing it:
oracle:oklacity$ doit.sh
Connecting with scott#1/tiger
Connecting with scott#2/tiger
Connecting with scott#3/tiger
oracle:oklacity$
Well, there’s your first issue, you are not getting the $CONNECTIONNAME expanded properly. Let’s fix that by putting curly brackets around it
oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
do
echo Connecting with ${user1}#${CONNECTIONNAME}_$i/${Password}
done
And executing it:
oracle:oklacity$ doit.sh
Connecting with scott#oklacity_1/tiger
Connecting with scott#oklacity_2/tiger
Connecting with scott#oklacity_3/tiger
Now that we have fixed your first problem, let’s add a simple connection to the database. I notice you are using the loop control number as part of your database connection string, so I’ve create three entries in my tnsnames.ora to match the example 3 iterations in my script. They all point to the same database, but for this exercise that doesn’t matter.
oracle:oklacity$ cat /u01/app/oracle/product/11.2.0/dbhome_1/network/admin/tnsnames.ora
oklacity =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = oklacity)
)
)
oklacity_1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = oklacity)
)
)
oklacity_2 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = oklacity)
)
)
oklacity_3 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = vbdb112-01)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = oklacity)
)
)
And we add the actual connection with sqlplus to our script. Again I had to add curly brackets around an environment variable name:
oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
do
echo Connecting with ${user1}#${CONNECTIONNAME}_$i/${Password}
sqlplus -s ${user1}#${CONNECTIONNAME}_$i/${Password} <<-EOF &
show user
EOF
done
And executing it
oracle:oklacity$ doit.sh
Connecting with scott#oklacity_1/tiger
Connecting with scott#oklacity_2/tiger
Connecting with scott#oklacity_3/tiger
oracle:oklacity$ USER is "SCOTT"
USER is "SCOTT"
USER is "SCOTT"
But what’s this? We executed the loop 3 timses, but only got 2 outputs from sqlplus. And the shell 'echo' are grouped separately from the sqlplus 'prompt'. And I had to manually hit ‘enter’ to get out of the loop. That’s because you put an ‘&’ at the end of the line invoking sqlplus. What was that all about? Let’s fix it.
oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
do
echo Connecting with ${user1}#${CONNECTIONNAME}_$i/${Password}
sqlplus -s ${user1}#${CONNECTIONNAME}_$i/${Password} <<-EOF
show user
EOF
done
And executing it
oracle:oklacity$ doit.sh
Connecting with scott#oklacity_1/tiger
USER is "SCOTT"
Connecting with scott#oklacity_2/tiger
USER is "SCOTT"
Connecting with scott#oklacity_3/tiger
USER is "SCOTT"
Now I have fixed two syntax issues with your original and so far everything is working. Now let’s add in the calling of the sql script from sqlplus. You are passing it two command line parms, so I will write a simple sql script to show what ever is passed to it.
oracle:oklacity$ cat query.sql
prompt First parm is &1
prompt Second parm is &2
exit
oracle:oklacity$
And the shell script with the call to query.sql added:
oracle:oklacity$ cat doit.sh
#!/bin/sh
DBcount=3
date1='8-Aug-2020'
date2='10-Aug-2020'
user1='scott'
CONNECTIONNAME='oklacity'
Password='tiger'
#
for (( i=1;i<=$DBcount;i++ ))
do
echo Connecting with ${user1}#${CONNECTIONNAME}_$i/${Password}
sqlplus -s ${user1}#${CONNECTIONNAME}_$i/${Password} <<-EOF
show user
#query.sql $date1 $date2
EOF
done
oracle:oklacity$
And finally, the complete execution:
oracle:oklacity$ doit.sh
Connecting with scott#oklacity_1/tiger
USER is "SCOTT"
First parm is 8-Aug-2020
Second parm is 10-Aug-2020
Connecting with scott#oklacity_2/tiger
USER is "SCOTT"
First parm is 8-Aug-2020
Second parm is 10-Aug-2020
Connecting with scott#oklacity_3/tiger
USER is "SCOTT"
First parm is 8-Aug-2020
Second parm is 10-Aug-2020
oracle:oklacity$

Executing sqlplus without entry in tnsnames.ora, standalone command works and script get struck

I am running unix script, that executes the SQL commands to get a report, as I do not have entry in tnsnames.ora, I give full description of portal in the sqlplus command and then the sqlfile. When I try to run the script the control gets struck.
I use sqlplus -s option to silent the prompt of username and password.
I ran the script with ksh -x myscript.ksh and when the script got struck, I copied the sqlplus line and ran it standalone, it works fine.
$ORACLE_HOME/sqlplus -S 'username/password#(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=
(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=umyhostname)(Port=1599)))
(CONNECT_DATA=(SID=idb)))' #/usr/local/myrpt.sql
Please try this
$ORACLE_HOME/sqlplus -S "username/password#umyhostname:1599/idb" #/usr/local/myrpt.sql
Show you script if it possible.
oracle#esmd:/opt/oracle> more test3.ksh
#!/usr/bin/ksh
username=SCOTT
#password lowercase
password=\"tiger\"
TNS_ALIAS='(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = zzzz.yyy.xxx)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ESMD)
)
)'
echo username: $username
echo password: $password
echo TNS_ALIAS: $TNS_ALIAS
sqlplus -s $username/$password#"$TNS_ALIAS" #test.sql
oracle#esmd:~> ksh
oracle#esmd:/opt/oracle> ./test3.ksh
username: SCOTT
password: "tiger"
TNS_ALIAS: (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = zzzz.xxx.yyy)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ESMD) ) )
TO_CHAR(SYSDATE,'DD
-------------------
24-06-2019 09:51:27

Oracle Database docker linux VM - Laptop connection

I have an Oracle database running in a Linux VM. The way i started the docker is using the following command
sudo docker run -d --name my_db --net oac_net -p 1521:1521 -P --shm-size=4G bi.docker.oraclecorp.com/database/enterprise:12.1.0.2
This is running inside a Linux VM.
[oracle#07f1d37f71c9 /]$ hostname -i
172.18.0.2
I would like to connect to this database docker from my laptop. The TNS entry in my laptop is like the following
odidocker = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.18.0.2)(PORT = 1521))
(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ORCL.localdomain) ) )
PDBORCL=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 172.18.0.2)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = pdborcl.localdomain)
))
Trying to connect using the following command
sqlplus system/welcome1#odidocker
the error we are getting is the following
ORA-12154: TNS:could not resolve the connect identifier specified
What is the mistake i am making. Could someone please help.
Thanks
Bala

How do I list tnsnames

Is there any easy way to list out all the available tnsnames in my system via command line?
Whenever I need to find out a tnsname, I just simply search for the tnsnames.ora file with tnsping command and open it in a text editor to scan through. Then subsequently run tnsping [tnsname] to check the connection health. I was thinking if there's any easy command like tnslist or tns -l to list out all the tnsnames but I couldn't find such.
Assuming that you have such a tnsnames.ora file :
DB01 =
(DESCRIPTION =
(FAILOVER=off)
(LOAD_BALANCE=off)
(ADDRESS = (PROTOCOL = TCP)(HOST = db01-vip)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = mydb1)
)
)
DB02 =
(DESCRIPTION =
(FAILOVER=off)
(LOAD_BALANCE=off)
(ADDRESS = (PROTOCOL = TCP)(HOST = db02-vip)(PORT = 1531))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = mydb2)
)
)
edit your .profile or .bash_profile like this:
[oracle#mydb12c~ ] vi .bash_profile
ORACLE_HOME=/u01/app/oracle/product/12.1.0.2/dbhome_1; export ORACLE_HOME
...
alias lstns="sed -n '/DESCR/{x;p;d;}; x' $ORACLE_HOME/network/admin/tnsnames.ora | sed "s/=/${s}/""
echo 'lstns : tnsnames.ora listing'
[oracle#mydb12c~ ] . .bash_profile
lstns : tnsnames.ora listing
[oracle#mydb12c~ ] lstns
DB01
DB02
There is no tnsnames.ora file listing command. But there are several options where the tnsnames.ora file can be placed. You can only use the find command
The priority of searching for tnsnames.ora files by the oracle client.
1) current directory (Linux, Windows)
2) $TNS_ADMIN (Linux, Windows environment variable, Windows registry key)
3) $ORACLE_HOME/network/admin (Linux, Windows)
4) /etc (Linux)
5) %USERPROFILE%/AppData/Oracle ( Windows 7).
[root#elbrus-1 ~]# find / -name tnsnames.ora
/opt/ora/app/oracle/product/11.2.0/dbhome_1/network/admin/tnsnames.ora
/opt/ora/app/oracle/product/11.2.0/dbhome_1/network/admin/samples/tnsnames.ora
/home/oracle/diman/tnsnames.ora
[root#elbrus-1 ~]#

Resources