2017-04-24 93 views
0

我有一个bash脚本包装bash脚本调用KSH脚本,但挂在功能

foo.sh:

#!/bin/bash 
echo "start" 
. /path/to/bar/bar.ksh 
echo "after bar" 

getoravariables $1 

bar.ksh(目的是刚刚成立的Oracle变量):

#!/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" 

执行foo.sh后我得到:

>./foo.sh validsid 
start 
b4 getora 
after getora 

所以我可以说,自从“b4 getora”和“getora之后”的echo命令工作以后,只需调用ksh脚本就没有问题。但是执行该函数有一些问题,因为我没有得到我期望的回声“1”或回声“2”。此外,如果我运行foo.sh作为ksh脚本,一切正常。

因此,我可以假设这两种语言之间的语法存在某种差异,但我并不感兴趣。任何人都可以协助

UPDATE: 我在全KSH脚本的顶部添加set -x,(我包含在我的问题只是一个子集)。我发现剧本中我的脚本功能我贴挂在一个点以后:

++ echo 

++ grep -v '#' 
++ read VAR VALUE 
(hanging here) 

对于这部分脚本那些代码是:

echo $GLOBPARFIL 
grep -v "#" ${GLOBPARFIL}|while read VAR VALUE 
do 
     export ${VAR}=${VALUE} 
done 

所以$GLOBPARFIL不被设置正常。它也恰好是一个变量,从getoravariables()被拉入和设置。从调试达输出说明了这一点:

++ read VAR VALUE 
++ export GLOBPARFIL=/home/local/par/global.par 
++ GLOBPARFIL=/home/local/par/global.par 

这行了@jlliagre回答以下声明的变量没有得到正确设置。不过,我尝试了解决方法只有相同的不良结果。

更新2:

按照规定我能找到真正的源头,并创建一个解决方法的信息和逻辑:

问题:

grep -v "#" ${file_location}| tr "^" " " | while read VAR VALUE 

SOLUTION:

while read VAR VALUE 

do 

     export ${VAR}=${VALUE} 
done <<% 
$(grep -v "#" ${file_location}| tr "^" " ") 
% 

我会马上k一样完整。但是,如果我可以收到更多关于为什么这种解决方法可以解决问题的信息,我将不胜感激。

回答

3

源文件忽略了shebang,所以它引用的事实ksh并不妨碍bash来处理它。

的问题是与该行:

grep -w ${1} ${ORATAB_LOC} | grep -v "#" | sed "s/:/ /g" | read SID ORAHOME ASK 

ksh,管道的最后一个组件是由主壳运行,而在bash下,它是由一个子shell中运行。然后在bash下设置变量SID,ORAHOMEASK

这里是一个解决办法:

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}") 
% 

如果GLOBPARFIL设置,变量会被正确地设置和导出,如果GLOBPARFIL未设置,这可能是一个问题,至少不会挂起脚本。

说明:

当您运行shell命令管道时,例如, command1 | command2 | command3bash解释器正在子shell中运行每个命令。这意味着在其中一个管道命令中完成的任何变量设置都会丢失。在你的脚本中,你有几个成语。这适用于ksh,它在当前shell中运行read指令,但不与bash一起运行。

便携式解决方法是通过读取行​​开头的变量来颠倒命令的顺序,并使用here document来设置读取标准输入。这里的文档由任何自定义字符串分隔,常见的是%。这里的文档通常包含标准输入本身作为纯文本。在这里,我们希望该输入是流水线中的set指令之前的命令的结果,因此使用command substitution$(command))。这里输入command这里的文件。

您可能还使用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}") 
+0

谢谢你,我的例子bar.ksh脚本实际上是我的一个更大脚本的子集。你的回答让我质疑,如果我的真正酒吧。ksh正在一路走到最后。我在它的最后发出了回声,它没有回来。这个问题必须在其他地方,我将不得不更多地寻找来源。 –

+0

@ exit_1要调试shell脚本,请在开始处加上'set -x'。它会在执行它们时显示所有行。 – Barmar

+0

是的,或者只是运行'bash -x foo.sh'。 – jlliagre

0

最有可能的情况是,函数名“getoravariables”来定义第二函数(没有按在这里没有列出的其中一个脚本内部做任何可见的事情。 尝试在所有文件中grep for“getoravariables”,也许你会找到它。

0

我有这样的脚本来“强制”bash执行脚本。

#!/bin/sh 
# 

if [ "$(ps -p "$$" -o comm=)" != "bash" ]; then 
    exec /usr/local/bin/bash "$0" "[email protected]@" 
    exit 255 
fi 
echo blah... 

我假设你可以使用类似的东西强制执行ksh。 ps选项是POSIX,所以它们应该是便携式的。

p.s.如果有更好的方法来做到这一点,请发布。我并不自豪。