Send stderr/stdout messages to function and trap e

2019-03-02 15:21发布

Im working on error handling and logging in my bash script. Below I have included a simplified code snippet that exemplify the use case.

I want to achieve following in my script:

  1. trap exit signals which should trigger onexit() function in the code below
  2. stderr and stdout should be sent to the log() function which will make sure to log the output to an log file according to specific log format (simplified in the example below)

Issue with current code below:

  • Step 1 is not trapped by onexit function and script is continuing to Step 2. Most probably because stderr is piped to logStd(). How can I send error messages to logStd() but still trap the exit signal in onexit()?

Resolution:

  1. Add set -o pipefail
  2. Get exit status on onexit() by adding local exit_status=${1:-$?}

script.sh (edited after resolution)

#!/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

output:

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条回答
乱世女痞
2楼-- · 2019-03-02 15:35

You have to use

set -o pipefail

See this related StackOverflow Question.


Minimal example:

#!/bin/bash

trap handler ERR
handler() { echo trapped ; }

echo 1
false | :

echo 2
set -o pipefail
false | :

Output:

$ bash test.sh
1
2
trapped
查看更多
登录 后发表回答