【问题标题】:bash script: how to save return value of first command in a pipeline?bash脚本:如何在管道中保存第一个命令的返回值?
【发布时间】:2011-05-10 19:50:31
【问题描述】:

Bash:我想运行一个命令并将结果通过一些过滤器传递,但是如果命令失败,我想返回命令的错误值,而不是过滤器无聊的返回值:

例如:

if !(cool_command | output_filter); then handle_the_error; fi

或者:

set -e
cool_command | output_filter

无论哪种情况,我关心的是cool_command 的返回值——对于第一种情况下的“if”条件,或者在第二种情况下退出脚本。

这样做有什么干净的习惯用法吗?

【问题讨论】:

    标签: bash return-value pipeline


    【解决方案1】:

    使用PIPESTATUS 内置变量。

    来自man bash

    管道状态

    数组变量(请参阅数组 下面)包含退出列表 来自进程的状态值 最近执行的前台 管道(可能只包含一个 单个命令)。

    【讨论】:

    • 只是为了完成答案,[[ ${PIPESTATUS[0]} -ne 0 ]] && handle_the_error
    【解决方案2】:

    如果你不需要显示命令的错误输出,你可以这样做

    if ! echo | mysql $dbcreds mysql; then
        error "Could not connect to MySQL. Did you forget to add '--db-user=' or '--db-password='?"
        die "Check your credentials or ensure server is running with /etc/init.d/mysqld status"
    fi
    

    在示例中,error 和 die 是已定义的函数。脚本的其他地方。 $dbcreds 也被定义,尽管它是从命令行选项构建的。如果该命令没有产生错误,则不返回任何内容。如果发生错误,此特定命令将返回文本。

    如果我错了,请纠正我,但我觉得你真的想做一些比这更复杂的事情

    [ `id -u` -eq '0' ] || die "Must be run as root!"
    

    在 if 语句之前实际获取用户 ID,然后执行测试。这样做,如果您选择,您可以显示结果。这将是

    UID=`id -u`
    if [ $UID -eq '0' ]; then
        echo "User is root"
    else
        echo "User is not root"
        exit 1 ##set an exit code higher than 0 if you're exiting because of an error
    fi
    

    【讨论】:

      【解决方案3】:

      以下脚本使用 fifo 在单独的进程中过滤输出。与其他答案相比,这具有以下优点。首先,它不是特定于 bash 的。特别是它不依赖于 PIPESTATUS。其次,在命令完成之前不会停止输出。

      $ cat >test_filter.sh <<EOF
      #!/bin/sh
      
      cmd()
      {  
          echo $1
          echo $2 >&2
          return $3
      }
      
      filter()
      {  
          while read line
          do     
                  echo "... $line"
          done
      }
      
      tmpdir=$(mktemp -d)
      fifo="$tmpdir"/out
      mkfifo "$fifo"
      
      filter <"$fifo" &
      pid=$!
      cmd a b 10 >"$fifo" 2>&1
      ret=$?
      wait $pid
      echo exit code: $ret
      rm -f "$fifo"
      rmdir "$tmpdir"
      EOF
      $ sh ./test_filter.sh
      ... a
      ... b
      exit code: 10
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-14
        • 1970-01-01
        • 2016-05-02
        相关资源
        最近更新 更多