向函数发送 stderr/stdout 消息并捕获退出信号
Send stderr/stdout messages to function and trap exit signal
我正在处理错误并在我的 bash 脚本中记录。下面我包含了一个简化的代码片段来举例说明用例。
我想在我的脚本中实现以下目标:
- 在下面的代码中捕获应该触发 onexit() 函数的退出信号
- stderr 和 stdout 应该被发送到 log() 函数,这将确保根据特定的日志格式(在下面的示例中简化)将输出记录到日志文件中
以下当前代码存在问题:
- 第 1 步未被 onexit 函数捕获,脚本继续执行第 2 步。很可能是因为 stderr 通过管道传输到 logStd()。如何向 logStd() 发送错误消息,但仍然在 onexit() 中捕获退出信号?
解析:
- 添加
set -o pipefail
- 通过添加
local exit_status=${1:-$?}
在 onexit()
上获取退出状态
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
}
# 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(): "
}
# 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:
你必须使用
set -o pipefail
看到这个related Whosebug Question。
最小示例:
#!/bin/bash
trap handler ERR
handler() { echo trapped ; }
echo 1
false | :
echo 2
set -o pipefail
false | :
输出:
$ bash test.sh
1
2
trapped
我正在处理错误并在我的 bash 脚本中记录。下面我包含了一个简化的代码片段来举例说明用例。
我想在我的脚本中实现以下目标:
- 在下面的代码中捕获应该触发 onexit() 函数的退出信号
- stderr 和 stdout 应该被发送到 log() 函数,这将确保根据特定的日志格式(在下面的示例中简化)将输出记录到日志文件中
以下当前代码存在问题:
- 第 1 步未被 onexit 函数捕获,脚本继续执行第 2 步。很可能是因为 stderr 通过管道传输到 logStd()。如何向 logStd() 发送错误消息,但仍然在 onexit() 中捕获退出信号?
解析:
- 添加
set -o pipefail
- 通过添加
local exit_status=${1:-$?}
在
onexit()
上获取退出状态
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
}
# 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(): "
}
# 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:
你必须使用
set -o pipefail
看到这个related Whosebug Question。
最小示例:
#!/bin/bash
trap handler ERR
handler() { echo trapped ; }
echo 1
false | :
echo 2
set -o pipefail
false | :
输出:
$ bash test.sh
1
2
trapped