【问题标题】:How a function should exit when it called with here-document from shell script?使用 shell 脚本中的 here-document 调用函数时应该如何退出?
【发布时间】:2014-03-26 02:56:26
【问题描述】:

我有一个 COBOL 程序,它应该通过 shell 脚本运行,并且应该接受此处文档中的值。在此处的文档中,我应该调用一个函数,该函数应该让控件使用退出代码异常退出。

我已经尝试如下,但它不适合我。

这是我的 COBOL 程序:

   01  WW-ANS              PIC X value space. 

IRS-200.
      display "ARE THE ABOVE ANSWERS CORRECT? Y/N/E".
      Accept ws-ans.
      display "entered value is " ws-ans "<".

      IF WW-ANS  =  "E"  or "e"
         PERFORM STOP-RUN-CA.

      IF WW-ANS  NOT =  "Y" AND "N" AND "E"      
                    and "y" and "n" and "e"      
          PERFORM DISPLAY-01 THRU DISPLAY-01-EXIT
          GO  TO  IRS-200.

      IF WW-ANS  =  "Y" or "y"                   
          display "Program executed successfully"
          PERFORM STOP-RUN-CA. 
      ELSE                                       
          GO  TO  IRS-200.

DISPLAY-01.                       
      DISPLAY "value is >" WW-ANS "<".
      DISPLAY "INVALID RESPONSE".

这是我的 shell 脚本:

#!/bin/bash
funexit ()
{
echo "calling funexit"
exit 1
}

/caplus/pub/test123<<:EOD:
1
g
$(funexit)
Y
:EOD:

输出为:

[Linux Dev:adminusr ~]$ ./test123.sh
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is 1<
value is >1<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is g<
value is >G<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is  c<
value is >C<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is Y<
Program executed successfully

当从这里调用函数时,COBOL 程序接受值作为“C”,因为在函数:它调用 echo 命令并考虑“调用 funexit”字符串中的第一个字符,而不是退出。

从函数中,我删除了如下的 echo 语句:

#!/bin/bash
funexit ()
{
exit 1
}

/caplus/pub/test123<<:EOD:
1
g
$(funexit)
Y
:EOD:

输出为:

[Linux Dev:adminusr ~]$ ./test123.sh
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is 1<
value is >1<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is g<
value is >G<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is   <
value is > <
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is Y<
Program executed successfully.

当从这里调用函数时,COBOL 程序会接受该值作为空格而不是退出。

脚本应该通过一些退出代码异常退出。

【问题讨论】:

  • 如果您使用终端而不是heredoc,“退出”的等价物是什么?
  • @choroba .. 如果我理解正确,终端意味着在命令行。如果是这样,在命令行退出将起作用。但我的要求是通过shell脚本调用COBOL程序,通过shell脚本将接受变量传递给它。这只能通过heredoc来实现。所以我应该使用heredoc。使用退出语句没有限制。任何外壳控制中断语句/逻辑都可能用于异常退出进程..

标签: bash shell unix cobol heredoc


【解决方案1】:

这个例子看起来很做作,因为你给它两个静态输入。但是,这可能是因为这只是一个简化的示例。

我猜你希望 funexit 返回 E 以便输入意味着没有更多输入,如果有更多输入则什么都没有。需要明确的是,在调用 COBOL 之前调用了 funexit 脚本(并完成)。

我想你会想这样编写你的 shell 脚本:

#!/bin/bash
funexit ()
{
  echo calling funexit 1>&2
  echo E
}

/caplus/pub/test123<<:EOD:
1
g
$(funexit)Y
:EOD:

请注意,对 funexit 的调用和后面的 Y 位于同一行。这样,如果 funexit 没有返回任何内容,cobol 程序就不会看到空行。如果 funexit 返回一个 E(实际上是一个 E 后跟一个新行),它将看到 E。

还要注意“Calling funexit”的调试输出被重定向到标准错误;在它被发送到 cobol 程序之前,它接受了字母 C(来自“Calling”)。

最后,funexit 脚本不需要退出,因为无论如何这将在脚本结束时发生。

【讨论】:

    【解决方案2】:

    @ANR;

    使用 ACCEPT ... 在例外情况下

    阿拉

       identification division.
       program-id. sample.
    
       data division.
       working-storage section.
       01 the-fields.
          05 field-one         pic x(8).
          05 field-two         pic x(8).
          05 field-three       pic x(8).
          05 field-four        pic x(8).
    
      *> ***************************************************************
       procedure division.
    
       accept field-one end-accept
       display field-one end-display
    
       accept field-two end-accept
       display field-two end-display
    
       accept field-three
           on exception
               display "no field three entered" end-display
           not on exception
              display field-three end-display
       end-accept
    
       accept field-four
           on exception
               display "no field four entered" end-display
           not on exception
               display field-four end-display
       end-accept
    
       goback.
       end program sample.
    

    所以四行输入的运行看起来像

    ./sample <fourdatums.txt
    one
    two
    three
    four
    

    只有三个

    ./sample <threedatums.txt
    one
    two
    three
    no field four entered
    

    【讨论】:

    • @Brain Tiffin.. 非常感谢你。但我不想更改 COBOL 代码。我应该只处理 shell 脚本。当从 shell 脚本传递给 COBOL 的输入值不正确时,shell 脚本应该以异常退出条件退出。如果您对此有任何想法,请分享一下。
    • @ANR;抱歉 ANR,但数据永远无法影响代码。永远不能。缺少数据永远不会影响控制台 ACCEPT,COBOL 程序只会继续运行代码流。如果您正在编写 shell 脚本,并且知道您不会提供足够的数据,请不要运行程序并退出 1。如果您不介意突然异常终止,请在 heredoc 中输入几行数据后发送kill -9 &lt;cobol-process-pid&gt;。同样,您永远无法将数据流中的出口“注入”到 COBOL。但是您可以终止该进程(在heredoc之外,而不是在其中)。
    【解决方案3】:

    由于funexit 在由命令替换创建的子shell 中执行,您需要在此处文档之外检查其退出状态以确定父shell 是否应该退出。

    #!/bin/bash
    funexit () {
      echo "calling funexit"
      exit 1
    }
    
    output=$(funexit) || exit
    
    /caplus/pub/test123<<:EOD:
    1
    g
    $output
    Y
    :EOD:
    

    【讨论】:

    • @chepner.. 我试过你的建议,但它不符合我的要求。它从脚本中退出并且不允许我执行 COBOL 程序。
    • 您是说希望在调用funexit 时退出您的COBOL 程序吗?那是不可能的。 funexittest123 运行之前被调用。如果你希望 funexit 在 `test123 已经读取了前面的输入行之前不被调用,你将不得不重写程序。
    • 感谢@chepner 的快速回复。您认为有什么方法可以通过 shell 脚本调用 COBOL 程序吗?
    • 否;您的 Cobol 代码本身需要在适当的时间调用 funexit(或者至少将 funexit 在调用时是成功还是失败作为输入),以便它可以采取适当的行动。
    • 我认为你的想法会奏效..您能否详细说明 COBOL 程序如何调用funexit 函数的示例...我是 shell 脚本的新手..!这可能是非常可观的..
    【解决方案4】:

    将函数的输出分配给heredoc之外的变量并在那里检查失败:

    #!/bin/bash
    funexit ()
    {
        exit 1
    }
    
    if ! funexitvalue=$(funexit) ; then
        echo "Failure!"
        exit 1
    fi
    
    
    /caplus/pub/test123<<:EOD:
    1
    g
    $funexitvalue
    Y
    :EOD:
    

    如果funexit 没有成功退出,这将阻止 COBOL 程序运行。

    解释

    bash 中的命令替换 ($(...)) 始终“有效”,例如,替换被命令的输出替换。即使命令以错误退出:

    $ echo "$(echo foobar; exit 1)"
    foobar
    $ echo $?
    0
    

    如您所见,第一个回显成功退出,即使替换中的命令失败。命令替换的返回码不会以任何方式影响实际的命令。

    相比之下:

    $ a="$(echo foobar; exit 1)"
    $ echo $?
    1
    $ echo $a
    foobar
    

    这里命令替换的返回码不会被任何其他命令遮蔽,因此您可以实际检查它是否成功返回。反正输出分配给a还是成功的。


    注意:如果您打算将 COBOL 程序运行到会发生错误输入的地步,那么使用 heredocs 不是的方法,因为它们在它们甚至之前就已经被完全评估了传递给程序。因此,对于 heredocs,这是一个全有或全无的交易。

    【讨论】:

    • @Adaephon..!我已经尝试过你的建议,但它对我不起作用。它不允许我执行 COBOL 程序。它只是显示“失败!”向终端发送消息。我的意图是运行 COBOL 程序,并且在运行时向 COBOL 程序传递的参数不足时应该退出。这可以是此处的文档,也可以是任何方法。如果您认为 here-doc 无法做到这一点,那么您能否建议我一个好的解决方案。
    • #!/bin/bash funexit () { a="$(echo foobar; exit 1)" exit 1 } /caplus/pub/test123&lt;&lt;:EOD: 1 g 5 $(funexit) Y :EOD: 如上所述尝试但没有运气 COBOL 程序在函数调用处接受空值。它没有退出。
    【解决方案5】:

    heredoc 将由 shell 解析并作为输入完整传递,而您的方法不起作用。但是,您当然可以分解输入:

    { cat << EOF
    This text will always be entered to the test123 executable;
    EOF
    funexit  # exit or return, as needed
    cat << EOF
    If funexit returned, this will go to test123.
    If funexit exited, it will not
    EOF
    } | caplus/pub/test123
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-08
      • 1970-01-01
      • 2011-01-04
      • 1970-01-01
      • 2019-12-24
      相关资源
      最近更新 更多