将stderr / stdout消息发送到函数并捕获退出信号

时间:2015-04-26 10:14:06

标签: bash shell unix stdout stderr

我正在处理错误处理和登录我的bash脚本。下面我列出了一个简化的代码片段,它举例说明了用例。

我想在我的剧本中实现以下目标:

  1. 陷阱退出信号应触发下面代码中的onexit()函数
  2. 应该将stderr和stdout发送到log()函数,该函数将确保根据特定的日志格式将输出记录到日志文件中(在下面的示例中简化)
  3. 发布以下当前代码:

    • 第1步没有被onexit函数捕获,脚本继续执行第2步。很可能是因为stderr被传送到logStd()。如何向logStd()发送错误消息,但仍将陷阱信号捕获到onexit()?

    解决:

    1. 添加set -o pipefail
    2. 通过添加onexit()
    3. 获取local exit_status=${1:-$?}的退出状态

      script.sh(解析后编辑)

      #!/bin/bash -E
      set -o pipefail
      
      # Perform program exit housekeeping
      function onexit {
          local exit_status=${1:-$?}
          log "onexit() called with param: $exit_status"
          exit $1
      }
      
      # Simplified log function that sends input parameter to echo. This function is used within this script
      # In real case this function would send log statement to log file according to specific log format
      function log {
          echo "log(): $1"
      }
      
      # Simplified log function that reads input stream and sends to log
      # This function is used from commands
      function logStd {
          log "logStd() called"
          while IFS= read -r line; do log "$line"; done
      }
      
      # http://linuxcommand.org/wss0160.php
      # The trap command allows you to execute a command when a signal is received by your script.
      # Usage: trap arg signals
      # "signals" is a list of signals to intercept and "arg" is a command to execute when one of the signals is received
      # arg can either be a command or a function name like clean_up below
      trap onexit 1 2 3 15 ERR
      
      # STEP 1 - should fail, send errors to logstd() and be trapped by onexit()
      log "**Tarballing should fail, file doesn´t exist"
      tar -czf /Users/ismar.slomic/shellscripting/unknownfile.txt.gz /Users/ismar.slomic/shellscripting/unknownfile.txt 2>&1 | logStd
      
      # STEP 2 - should run successfully and send "tar: Removing leading '/' from member names" to logStd()
      log "**Tarballing should run successfully"
      tar -czf /Users/ismar.slomic/shellscripting/file.txt.gz /Users/ismar.slomic/shellscripting/file.txt 2>&1 | logStd
      
      onexit
      

      输出

      log(): **Tarballing should fail, file doesn´t exist
      log(): logStd() called
      log(): tar: /Users/ismar.slomic/shellscripting/unknownfile.txt: Cannot stat:  No such file or directory
      log(): tar: Error exit delayed from previous errors.
      log(): **Tarballing should run successfully
      log(): logStd() called
      log(): tar: Removing leading '/' from member names
      log(): onexit() called with param:
      

1 个答案:

答案 0 :(得分:1)

你必须使用

set -o pipefail

请参阅此related StackOverflow Question

最小示例

#!/bin/bash

trap handler ERR
handler() { echo trapped ; }

echo 1
false | :

echo 2
set -o pipefail
false | :

<强>输出

$ bash test.sh
1
2
trapped