包装器bash脚本调用ksh脚本但挂起函数

时间:2017-04-24 19:31:44

标签: bash shell unix ksh

我有一个bash脚本

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

所以我可以说,简单地调用ksh脚本没有问题,因为" b4 getora"和#34;在getora"之后工作。但是执行该功能存在一些问题,因为我没有得到回声" 1"或回声" 2"我期待的。

此外,如果我将foo.sh作为ksh脚本运行,一切正常。

因此,我可以假设两种语言之间的语法存在某种差异,我没有抓到。有人可以帮忙吗?

更新 我在我的完整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

解决方案:

while read VAR VALUE

do

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

我会标记为完整。但是,如果我能够收到更多关于为什么这个解决方法可以解决问题的信息,我将非常感激。

3 个答案:

答案 0 :(得分:3)

获取文件会忽略shebang,因此它引用ksh的事实并不会阻止bash处理它。

问题出在那一行:

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

ksh下,管道的最后一个组件由主shell运行,而在bash下,它由子shell运行。变量SID, ORAHOMEASKbash下设置后就会丢失。

这是一种解决方法:

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中运行每个命令。这意味着在其中一个管道命令中完成的任何变量设置都将丢失。在您的脚本中,您有几个command 1 | read variable1 variable2个成语。这适用于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}")

答案 1 :(得分:0)

最可能的情况是功能名称&#39; getoravariables&#39;用于在此处未列出的其中一个脚本中定义第二个函数(它不会执行任何可见的操作)。 试着寻找“getoravariables”&#39;在你的所有文件中,也许你找到它。

答案 2 :(得分:0)

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

#!/bin/sh
#

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

我假设您可以使用类似的东西强制执行ksh。 ps选项是POSIX,因此它们应该是可移植的。

P.S。如果有更好的方法,请发布它。我并不自豪。