【问题标题】:unix shell, getting exit code with piped childunix shell,使用管道子获取退出代码
【发布时间】:2010-05-17 18:21:09
【问题描述】:

假设我在 unix shell 中执行此操作

$ some-script.sh | grep mytext

$ echo $?

这会给我grep的退出代码

但是我怎样才能得到some-script.sh的退出码

编辑

假设管道操作是不可变的。即,我无法将其拆分并分别运行这两个命令

【问题讨论】:

    标签: unix shell io-redirection exitstatus


    【解决方案1】:

    有多种解决方案,这取决于您到底想做什么。

    最简单易懂的方法是将输出发送到文件,然后在保存退出代码后对其进行 grep:

    tmpfile=$(mktemp)
    ./some-script.sh > $tmpfile
    retval=$?
    grep mytext $tmpfile
    rm tmpfile
    

    【讨论】:

    • 我明白了。也许这是一个解决方案:tmpfile=$(mktemp); (./some-script.sh; echo $? > $tmpfile) | grep mytext; retval=$(cat $tmpfile)。这很脏,但也许有帮助。
    • 然后grep得到echo $? > tmpfile的输出
    • 否,因为echo $? > $tmpfile 没有输出。 echo的标准输出发送到$tmpfile
    • 对,没有任何东西传递给 grep,它不会附加第一个命令的输出
    • 我不确定我是否理解正确。第一个命令 (./some-script.sh) 的输出仍然到达 grep。你试过了吗?也许您可以添加带有问题的实际脚本以及为什么管道操作是不可变的。
    【解决方案2】:

    comp.unix.shell FAQ (#13) 中的一个技巧解释了如何在 Bourne shell 中使用管道来帮助完成您想要的:

       You need to use a trick to pass the exit codes to the main
       shell.  You can do it using a pipe(2). Instead of running
       "cmd1", you run "cmd1; echo $?" and make sure $? makes it way
       to the shell.
    
       exec 3>&1
       eval `
         # now, inside the `...`, fd4 goes to the pipe
         # whose other end is read and passed to eval;
         # fd1 is the normal standard output preserved
         # the line before with exec 3>&1
         exec 4>&1 >&3 3>&- 
         {
           cmd1 4>&-; echo "ec1=$?;" >&4
         } | {
           cmd2 4>&-; echo "ec2=$?;" >&4
         } | cmd3
         echo "ec3=$?;" >&4
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 bash:

      PIPESTATUS
          An array variable (see Arrays) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command). 
      

      【讨论】:

      • 我正在使用 sh。我的客户不喜欢 bash
      【解决方案4】:

      有一个名为mispipe 的实用程序是moreutils 包的一部分。

      正是这样做的:mispipe some-script.sh 'grep mytext'

      【讨论】:

        【解决方案5】:

        第一种方法,将退出状态暂时保存在某个文件中。这导致您必须使用大括号创建子shell:

        (your_script.sh.pl.others; echo $? >/tmp/myerr)|\ #subshell with exitcode saving
        grep sh #next piped commands
        exitcode=$(cat /tmp/myerr) #restore saved exitcode
        echo $exitcode  #and print them
        

        上面 Randy 提出的另一种方法,更简单的代码实现:

        some-script.sh | grep mytext
        echo ${PIPESTATUS[0]} #print exitcode for first commands. tables are indexted from 0
        

        就是这样。两者都在 bash 下工作(我知道,bashizm)。祝你好运 :) 两种方法都不会将临时管道保存到物理文件,只会退出代码。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-03-05
          • 1970-01-01
          • 1970-01-01
          • 2016-09-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多