【问题标题】:wrapper bash script calls ksh script but hangs on a function包装器 bash 脚本调用 ksh 脚本但挂在函数上
【发布时间】:2017-04-24 19:31:43
【问题描述】:

我有一个 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”和“getora 之后”的回显命令有效。但是执行该函数存在一些问题,因为我没有得到预期的 echo "1" 或 echo "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 () 拉入和设置的变量。调试 tat 的输出证明了这一点:

++ 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 "^" " ")
%

我将标记为完成。但是,如果我能收到更多关于为什么这个解决方法能解决问题的更多信息,我将不胜感激。

【问题讨论】:

    标签: bash shell unix ksh


    【解决方案1】:

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

    问题在于那一行:

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

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

    这里有一个解决方法:

    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 成语。这适用于在当前 shell 中运行 read 指令的 ksh,但不适用于 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}")
    

    【讨论】:

    • 谢谢,我的示例 bar.ksh 脚本实际上是我的一个较大脚本的子集。你的回答让我质疑我真正的 bar.ksh 是否一直到最后。我在它的末尾添加了一个回声,它没有返回。问题肯定出在其他地方,我将不得不做更多的工作来寻找源头。
    • @exit_1 要调试 shell 脚本,请将 set -x 放在开头。然后它将在执行时显示所有行。
    • 是的,或者直接运行bash -x foo.sh
    • 语法上,显示的ksh 脚本是有效的bash。在语义上,bash 对它的解释不同,即在运行 read 作为管道的最后一个组件的行中。
    • @chepner 很好,我错过了那个问题。 bash下确实没有设置变量。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

      附言如果有更好的方法可以做到这一点,请发布。我不骄傲。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-21
        • 1970-01-01
        • 2012-01-08
        • 1970-01-01
        • 1970-01-01
        • 2019-01-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多