How to reliably return results from Oracle SQL*Plus to a variable in Korn shell? - linux

Hello Unix/Linux geniae,
When an error occurs in the query, why does the shell variable (OPEN_MODE in this case) contain not only the expected SQL error message but also a listing of all the files in the directory?
I realise it has to do with the backticks and the fact that there is an asterisk in the error message but how can I get the error message back without the directory listing?
Run from command line:
$ OPEN_MODE=`sqlplus -s '/ as sysdba' <<'EOSQL' 2>/tmp/results.synchro.$$
> set headi off newpa none feedb off
> whenever sqlerror exit failure
> select open_mode from v$database;
> EOSQL
> `
$ echo $OPEN_MODE
select open_mode from v$database db_space_calculation.ksh get_emc_schedule_status.ksh set_emc_schedule_status.ksh synchro.ksh synchro_adsp_adso.cfg synchro_arp_arpt.cfg synchro_xbrl_xbrla.cfg synchro_xbrl_xbrlt.cfg test.sh ERROR at line 1: ORA-01034: ORACLE not available Process ID: 0 Session ID: 0 Serial number: 0
And run interactively from SQL*Plus to show how the error is normally presented...
$ sqlplus '/ as sysdba'
SQL*Plus: Release 12.1.0.2.0 Production on Mon Jan 15 20:31:04 2018
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to an idle instance.
SQL> set headi off newpa none feedb off
SQL> whenever sqlerror exit failure
SQL> select open_mode from v$database;
select open_mode from v$database
*
ERROR at line 1:
ORA-01034: ORACLE not available
Process ID: 0
Session ID: 0 Serial number: 0
Disconnected
I have also tried the "piping into read" method but doesn't work either.
sqlplus -s '/ as sysdba' <<'EOSQL' 2>/tmp/results.synchro.$$ | read OPEN_MODE
set headi off newpa none feedb off
whenever sqlerror exit failure
select open_mode from v$database;
EOSQL
Has to work in ksh. No bash please.
$() produces the same results as backticks. The only time I use backticks in ksh is when calling sqlplus! There are times when $() simply does not work. But that's for another day :-)

Related

Trouble running a custom monit check, stderr maybe?

Trying to run this check from monit, but it doesn't work. The gravity program sends its output to stderr. Could it be that monit doesn't handle this properly because of the way it exec's the check?
contents of system.monitrc:
check program gravityStatus with path /usr/local/bin/check.sh
with timeout 10 seconds
if status !=0 then alert
check.sh:
root#tiki:~# cat /usr/local/bin/check.sh
#!/bin/bash
#This will return zero if all good
/usr/bin/gravity status |& /usr/bin/jq .SyncInfo.catching_up | grep -q 'false'
Output:
Program 'gravityStatus'
status Status failed
monitoring status Monitored
monitoring mode active
on reboot start
last exit value 1
last output parse error: Invalid numeric literal at line 1, column 6
data collected Tue, 01 Feb 2022 19:52:37
If I execute the contents of check.sh on the command line, the script works:
root#tiki:~# /usr/bin/gravity status |& /usr/bin/jq .SyncInfo.catching_up | grep -q 'false'
root#tiki:~# echo $?
0
I figured it out. I want to thank #boppy for his comment, it was very helpful. Here's what I did:
I changed the check.sh to just run 'gravity status' and then looked at the monit status. It says this:
Program 'gravityStatus'
status Status failed
monitoring status Monitored
monitoring mode active
on reboot start
last exit value 2
last output panic: $HOME is not defined
goroutine 1 [running]:
github.com/cosmos/cosmos-sdk/simapp.init.0()
/go/pkg/mod/github.com/cosmos/cosmos-sdk#v0.44.5/simapp/app.go:182 +0x189
The problem was that gravity status would die before it could send output to the jq process. gravity is a command that has to look at $HOME/.gravity were a bunch of configs are located. So the solution was to set $HOME to /root which is where all the gravity stuff is setup.

Not to display SQLPLUS prompt

I am trying to connect with sqlplus using a bash script. When I execute the script below SQLPLUS banner displayed.
Below the script:
$ORACLE_HOME/bin/sqlplus "/ as sysdba" <<EOF
set echo off
set heading off
spool bind.txt
select * from DBMS_LOCK_ALLOCATED where name = '$uservar';
spool off
exit
EOF
Output of the script
oracle#DMOTA01:~/script> ./before_bind.sh
SQL*Plus: Release 11.2.0.3.0 Production on Wed Nov 27 11:54:01 2019
Copyright (c) 1982, 2011, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> SQL> 2 3 4 Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
oracle#DMOTA01:~/script>
I don't want to display "SQL*Plus: Release 11............. Real Application Testing options" lines. How i can do it?
You need to add -S to sqlplus to switch it in silence mode:
$ORACLE_HOME/bin/sqlplus -S "/ as sysdba" <<EOF
set echo off
set heading off
spool bind.txt
select * from DBMS_LOCK_ALLOCATED where name = '$uservar';
spool off
exit
EOF

Why I get an error when I try to execute a command remotely?

I have a problem about execute command remotely via SSH. I am trying below.
ssh xx.xx.xx.xx "psql -U qradar -c "select count(id) from offense_view where to_timestamp(start_time/1000) > NOW() - interval '180 minutes'"
It gives an error like:
Pseudo-terminal will not be allocated because stdin is not a terminal.
ERROR: syntax error at or near "180"
LINE 1: ... to_timestamp(start_time/1000) > NOW() - interval 180 minute...
The problem is that you're using double quotes to delimit the argument to ssh and also the argument to psql inside the command. This is causing your strings to be parsed incorrectly. You're also missing the ending double quote for the psql command.
Nesting quotes is tricky in shell, and it's even harder when you're using ssh. It's easier if you use a here-doc.
ssh xx.xx.xx.xx <<EOF
psql -U qradar -c "select count(id) from offense_view where to_timestamp(start_time/1000) > NOW() - interval '180 minutes'"
EOF

Get return code from command run on ssh tunnel [duplicate]

This question already has answers here:
Exit when one process in pipe fails
(2 answers)
Closed 4 years ago.
Even if the mycode.sh has non-0 exit code this command returns 0 as ssh connection was successful. How to get the actual return code of the .sh on remote server?
/home/mycode.sh '20'${ODATE} 1 | ssh -L 5432:localhost:5432 myuser#myremotehost cat
This is not related to SSH, but to how bash handles the exit status in pipelines. From the bash manual page:
The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully. If the reserved word ! precedes a pipeline, the exit status of that pipeline is the logical negation of the exit status as described above. The shell waits for all commands in the pipeline to terminate before returning a value.
If you want to check that there was an error in the pipeline due to any of the commands involved, just set the pipefail option:
set -o pipefail
your_pipeline_here
echo $? # Prints non-zero if something went wrong
It is not possible to actually send the exit status to the next command in the pipeline (in your case, ssh) without additional steps. If you really want to do that, the command will have to be split like this:
res="$(/home/mycode.sh '20'${ODATE} 1)"
if (( $? == 0 )); then
echo -n "$res" | ssh -L 5432:localhost:5432 myuser#myremotehost cat
else
# You can do anything with the exit status here - even pass it on as an argument to the remote command
echo "mycode.sh failed" >&2
fi
You may want to save the output of mycode.sh to a temporary file instead of the $res variable if it's too large.
/home/mycode.sh is located onto the local host.
the ssh command is running cat on the remote server.
All text printed to the standard output of the /home/mycode.sh is redirected to the cat standard input.
The man ssh reads:
EXIT STATUS
ssh exits with the exit status of the remote command or with 255 if an error occurred.
Conclusion: the ssh exists with the EXIT STATUS of the cat or 255 if an error occurred.
if /home/mycode.sh script prints commands to the standard input, they can be run on the remote server when the cat is not present:
/home/mycode.sh '20'${ODATE} 1 | ssh -L 5432:localhost:5432 myuser#myremotehost
In my test, the EXIT STATUS of the last command executed on the remote server is returned by ssh:
printf "%s\n" "uname -r" date "ls this_file_does_not_exist" |\
ssh -L 5432:localhost:5432 myuser#myremotehost ;\
printf "EXIT STATUS of the last command, executed remotely with ssh is %d\n" $?
4.4.0-119-generic
Wed Aug 29 02:55:04 EDT 2018
ls: cannot access 'this_file_does_not_exist': No such file or directory
EXIT STATUS of the last command, executed remotely with ssh is 2

running ddl file through sh

I am having issue when running a ddl script file through sh on one of the servers but executes fine on another. The script is as below
sqlplus mgr/$1#$2 #export_all_tables_mgr.ddl
if [ $? != 0 ];
then
echo 'ERROR exporting MGR data, Refer to .CSV and .CTL files for detail.' | tee -a MGR_ExtractionLog.log
fi
It uses sqlplus to run the ddl file but one the rogue server, it would just connect to sql plus and won't do anything.
oracle#dbsdev55z2 $ export_all_tables_mgr.sh password servicename
SQL*Plus: Release 10.2.0.4.0 - Production on Thu Jan 24 08:39:18 2013
Copyright (c) 1982, 2007, Oracle. All Rights Reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production With the Partitioning, Data Mining and Real Application Testing options
SQL>
To mention here, I am using Oracle 10g here. export_all_tables_mgr.ddl file is as below
alter session set nls_date_format = 'DDMMYYYYHH24MISS';
#drop_table_temp_extraction_counts.ddl
#create_table_temp_extraction_counts.ddl
WHENEVER SQLERROR EXIT -1
WHENEVER OSERROR EXIT -1
SET HEADING OFF
SET FEEDBACK OFF
SET VERIFY OFF
SPOOL MGR_ExtractionLog.log
SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYY HH24:MI:SS'), '- Start extract process' FROM dual;
SPOOL OFF
define TableName=TABLE1
#ExportTable
define TableName=TABLE2
#ExportTable
SPOOL MGR_ExtractionLog.log append
SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYY HH24:MI:SS'), '- End extract process' FROM dual;
SPOOL OFF
EXIT 0
I'm guessing that this is a shell problem, try adding the following as the first line of your shell script to tell it which interpreter to use:
#!/bin/sh

Resources