【问题标题】:Incorrect exit status being fetched after executing a script执行脚本后获取的退出状态不正确
【发布时间】:2020-11-07 03:23:49
【问题描述】:

我有 2 个脚本。我正在调用另一个脚本来捕获退出状态。

Import.sh

    SCHEMA=$1
    DBNAME=$2
    LOGPATH=/app/dbimport/PreImport_`date +%d%b%Y`.log
    export ORACLE_HOME=/oracle/product/11.2.0/db
    set -x
    for line in `cat "$SCHEMA" | egrep -w 'PANV|PANVPXE'`
    do
            USER=`echo "$line" |cut -d ';' -f1`
            echo "Fetching User : $USER" >> "$LOGPATH"
            PASSWORD=`echo "$line" | cut -d ';' -f2`
            echo "Fetching Password: $PASSWORD" >> "$LOGPATH"
            SOURCE=`echo "$line" | cut -d ';' -f3`
            echo "Fetching Source Schema : $SOURCE" >> "$LOGPATH"
    done
    exit $?

temp.sh

RC=`/app/arjun/scripts/Import.sh schema_remap_AANV02_UAT2.txt ARJSCHEMA`
echo "Return code = $RC"

schema_remap_AANV02_UAT2.txt

AANVPXE;Arju4578;PANVPXE
AANVSL;Arj0098;PANVSL
AANV;Arju1345;PANV

.txt 文件没有读取权限(确保您没有授予读取权限),因此脚本应该通过将退出状态返回为 exit $ 来失败? .

下面是我运行 temp.sh 后的输出

+ cat schema_remap_AANV02_UAT2.txt
+ egrep -w 'PANV|PANVPXE'
cat: schema_remap_AANV02_UAT2.txt: Permission denied
+ exit 1
Return code =

内部脚本以 exit 1 退出(因为 cat 命令失败),但在 temp.sh 中,我在捕获返回码时没有获得预期值。

我想确保无论哪个命令在 import.sh 中失败,脚本都应该以适当的退出状态返回。

【问题讨论】:

  • @oguzismail 提供了所需的一切。你能告诉我你还需要什么吗? ?
  • @oguzismail 我已更正,提供了 schema_remap_AANV02_UAT2.txt 文件的内容。 Import.sh 脚本仅使用此 txt 文件。
  • 顺便说一下,请参阅 DontReadLinesWithForBashFAQ #1 了解编写循环的更有效方法。
  • 并且不要为您自己的变量使用全大写的名称——它们用于对您不应该覆盖的系统有意义的变量。为避免破坏其他期望像$USER 这样的内置变量具有其原始、有意义的值的程序,请在您自己定义时使用小写的$user。这也是 POSIX 标准推荐的内容:请参阅 pubs.opengroup.org/onlinepubs/9699919799/basedefs/…,在阅读时请记住,设置 shell 变量会覆盖任何预先存在的同名环境变量。
  • @alecxs, ...好吧,总是在回显成功时:)——但现在,他们甚至没有尝试exit $RC,所以使用@ 987654331@而不是...command...; rc=$?是现有代码主动出错的地方。

标签: linux bash shell unix


【解决方案1】:

要获取脚本 Import.sh 的退出代码而不是其输出,请将脚本 temp.sh 更改为

/app/arjun/scripts/Import.sh schema_remap_AANV02_UAT2.txt ARJSCHEMA
RC=$?
echo "Return code = $RC"

或者干脆

/app/arjun/scripts/Import.sh schema_remap_AANV02_UAT2.txt ARJSCHEMA
echo "Return code = $?"

有关如何修复/改进脚本的提示,请参阅 cmets。

【讨论】:

    【解决方案2】:

    我试图了解您将子脚本 ( Import ) 调用到父脚本 ( temp.sh ) 中的方式。好吧,让我告诉你发生了什么

    导入脚本

    SCHEMA=$1
    DBNAME=$2
    LOGPATH=/app/dbimport/PreImport_`date +%d%b%Y`.log
    export ORACLE_HOME=/oracle/product/11.2.0/db
    set -x
    for line in `cat "$SCHEMA" | egrep -w 'PANV|PANVPXE'`
    do
            USER=`echo "$line" |cut -d ';' -f1`
            echo "Fetching User : $USER" >> "$LOGPATH"
            PASSWORD=`echo "$line" | cut -d ';' -f2`
            echo "Fetching Password: $PASSWORD" >> "$LOGPATH"
            SOURCE=`echo "$line" | cut -d ';' -f3`
            echo "Fetching Source Schema : $SOURCE" >> "$LOGPATH"
    done
    exit $?
    

    当 grep 出现问题时,此脚本将以不同于 0 的值退出,因此如果您要查找的模式不存在,它将失败。

    $ echo "hello" | egrep -i "bye"
    $ echo $?
    1
    

    那么你是从其他程序运行这个脚本

    启动器

    RC=`/app/arjun/scripts/Import.sh schema_remap_AANV02_UAT2.txt ARJSCHEMA`
    echo "Return code = $RC"
    

    这就是问题所在。您正在调用脚本,就像它是一个函数并期待一个结果。变量 RC 正在获取脚本发送到 STDOUT 的任何输出,仅此而已。 RC 将始终为空,因为您的脚本不会向 STDOUT 发送任何内容。因此,您必须了解从子程序获取结果与评估生成子程序的返回码之间的区别。

    让我向您展示一个我刚刚使用自己的脚本向您解释过的示例。我有两个脚本: child.sh 只是 Oracle 的一个 sqlplus。父母以与您相同的方式调用孩子。

    $ more child.sh
    #/bin/bash
    
    $ORACLE_HOME/bin/sqlplus -S "/ as sysdba" << eof
    whenever sqlerror exit failure;
    select * from dual ;
    eof
    
    if [[ $? -eq 0 ]];
    then
       exit 0;
    else
       exit 99;
    fi
    $ more parent.sh
    #!/bin/bash
    
    # run child
    
    var=`/orabatch/ftpcpl/log/child.sh`
    
    echo $var
    
    $ ./child.sh
    
    D
    -
    X
    
    $ echo $?
    0
    $ ./parent.sh
    D - X
    $ echo $?
    0
    

    如您所见,我的父母正在获取子脚本发送到 STDOUT 的任何内容。现在让我们在子脚本中强制一个错误来验证我的父脚本是否仍然正常退出:

    $ ./child.sh
    select * from dual0
              *
    ERROR at line 1:
    ORA-00942: table or view does not exist
    
    $ ./parent.sh 
    ERROR at line 1:
    ORA-00942: table or view does not exist
    $ echo $? 
    0 
    

    如您所见,我的操作的输出是第一个错误,但不是错误,而是输出。我的父母已经结束了,甚至你可以看到有一个错误。

    我会重写脚本如下:

    #/bin/bash
    my_path=/app/arjun/scripts
    
    $my_path/Import.sh schema_remap_AANV02_UAT2.txt ARJSCHEMA 
    result=$?
    if [ ${result} -ne 0 ]; 
    then
        echo "error"
        exit 2;
    fi
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-24
      • 1970-01-01
      • 2019-06-23
      • 2017-05-18
      • 1970-01-01
      • 2015-10-31
      • 1970-01-01
      • 2015-05-10
      相关资源
      最近更新 更多