Reputation: 1250
I have a bash script
foo.sh:
#!/bin/bash
echo "start"
. /path/to/bar/bar.ksh
echo "after bar"
getoravariables $1
bar.ksh (purpose is to just set oracle variables):
#!/bin/ksh
echo "b4 getora"
getoravariables () {
echo "1"
if [ $# -ne 1 ]
then
echo "2"
echo "Usage: getoravariables sid"
exit 1
fi
grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g" | read SID ORAHOME ASK
if [ $? -ne 0 ]
then
print "Error: Please enter a vaild SID and check the ${orafile} file for correct input"
return 1
fi
ps -ef|grep pmon|grep ${SID} >> /dev/null
if [ $? -ne 0 ]
then
print "Error: SID ${SID} does not seem to be started. "
return 2
fi
export ORACLE_SID=${SID}
export ORACLE_HOME="${ORAHOME}"
export ORAENV_ASK=NO
. $ORACLE_HOME/bin/oraenv > /dev/null
}
echo "after getora"
After executing foo.sh I get:
>./foo.sh validsid
start
b4 getora
after getora
So I can tell that there is no problem in simply calling the ksh script since the echo commands for "b4 getora" and "after getora" work. But there is some issue with executing the function since I don't get echo "1" or echo "2" which I would expect.
Furthermore, If I run foo.sh as a ksh script, everything works fine.
Therefore, I can assume that there is some sort of difference in syntax between the two languages that i am not catching. Can anyone assist?
UPDATE:
I added set -x
at the top of my full ksh script, (what I included in my question is just a subset). I found that the script hung at a point later in my script that the function I posted:
++ echo
++ grep -v '#'
++ read VAR VALUE
(hanging here)
Those code for this part of the script is:
echo $GLOBPARFIL
grep -v "#" ${GLOBPARFIL}|while read VAR VALUE
do
export ${VAR}=${VALUE}
done
So $GLOBPARFIL
doesn't get set properly. It also happens to be a variable that gets pulled in and set from getoravariables ()
. Output from debugging tat demonstrates this:
++ read VAR VALUE
++ export GLOBPARFIL=/home/local/par/global.par
++ GLOBPARFIL=/home/local/par/global.par
This lines up with @jlliagre answer below that declares that the the variables are not getting properly set. However, I tried the workaround with only the same undesirable result.
UPDATE 2:
Following the information and logic provided I was able to find the true source and create a workaround:
PROBLEM:
grep -v "#" ${file_location}| tr "^" " " | while read VAR VALUE
SOLUTION:
while read VAR VALUE
do
export ${VAR}=${VALUE}
done <<%
$(grep -v "#" ${file_location}| tr "^" " ")
%
I will mark as complete. But if I could receive more information on why exactly this workaround solves the problem I would greatly appreciate it.
Upvotes: 0
Views: 936
Reputation: 30843
Sourcing a file ignores the shebang so the fact it refers to ksh
doesn't prevent bash
to process it.
The issue is with that line:
grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g" | read SID ORAHOME ASK
Under ksh
, the last component of a pipeline is run by the main shell while under bash, it is run by a subshell. The variables SID,
ORAHOME
and ASK
are then lost just after being set under bash
.
Here is a workaround:
read SID ORAHOME ASK <<%
$(grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g")
%
Edit:
For the second issue, you might use:
while read VAR VALUE
do
export ${VAR}=${VALUE}
done <<%
$(grep -v # "${GLOBPARFIL}")
%
If GLOBPARFIL
is set, the variables would be correctly set and exported and if GLOBPARFIL
is unset, which is likely an issue, that would at least not hang the script.
Explanation:
When you run a shell command pipeline, e.g. command1 | command2 | command3
, the bash
interpreter is running every command in a subshell. That means any variable setting done in one of the pipeline commands is lost. In your script, you have several command 1 | read variable1 variable2
idioms. This works with ksh
which run the read
instruction in the current shell but not with bash
.
A portable workaround is to reverse the order of commands by reading the variable at the beginning of the line, and use a here document
to set read standard input. A here document is delimited by any custom string and a common one is %
. A here document normally contains the standard input itself as plain text. Here we want this input to be the result of the commands that were preceding the set
instruction in the pipeline so command substitution ($(command)
) is used. This is putting command
output in the here document.
You might also have used process substitution:
read SID ORAHOME ASK < <(grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g")
...
while read VAR VALUE
do
export ${VAR}=${VALUE}
done < <(grep -v "#" "${GLOBPARFIL}")
Upvotes: 3
Reputation: 1099
I've got a script like this to "force" bash execution of a script.
#!/bin/sh
#
if [ "$(ps -p "$$" -o comm=)" != "bash" ]; then
exec /usr/local/bin/bash "$0" "$@@"
exit 255
fi
echo blah...
I assume that you could use something like this to force ksh execution. The ps
options are POSIX, so they should be portable-ish.
p.s. If there's a better way to do this, please post it. I'm not proud.
Upvotes: 0
Reputation: 601
The most likely scenario is that the function name 'getoravariables' was used to define a second function (which doesn't do anything visible) inside one of the scripts that is not listed here. Try to grep for 'getoravariables' in all your files, maybe you find it.
Upvotes: 0