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

Posted

技术标签:

【中文标题】发送 stderr/stdout 消息到函数并捕获退出信号【英文标题】:Send stderr/stdout messages to function and trap exit signal 【发布时间】:2015-07-04 18:16:07 【问题描述】:

我正在处理错误并登录我的 bash 脚本。下面我包含了一个简化的代码 sn-p 来举例说明用例。

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

    陷阱退出信号应该触发下面代码中的 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 $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】:

你必须使用

set -o pipefail

看到这个related *** Question。


小例子

#!/bin/bash

trap handler ERR
handler()  echo trapped ; 

echo 1
false | :

echo 2
set -o pipefail
false | :

输出

$ bash test.sh
1
2
trapped

【讨论】:

谢谢,这确实有效。但是,onexit() 函数中的退出代码为 0。根据您提到的线程,这是因为返回了最右边命令的退出信号,在我的例子中是 logStd()。对于这个用例,我怎么能在 onexit() 中得到非零信号? @IsmarSlomic:Bash 没有像您预期的那样将$1 中的信号传递给您的onexit()函数。所以pipefail 设置对此没有影响。如果您需要区分信号接收,则必须为每个陷阱使用不同的陷阱。 我可以通过在 onexit() 函数中使用 local exit_status=$1:-$? 来区分不同的信号。我现在已经更新了我的脚本。非常感谢您的支持! 不客气,效果很好。我只是怀疑你可能写了$? 而不是$1:-$?,因为我看不到任何其他东西被传递到onexit() 的情况。

以上是关于发送 stderr/stdout 消息到函数并捕获退出信号的主要内容,如果未能解决你的问题,请参考以下文章

python -u

docker入门基础

python stderr,stdout写入变量

stderr,stdout,a.txt缓冲区别

Python,捕获操作系统输出并作为不和谐的消息发送

Google Cloud Pub/Sub - 捕获发送到死信主题的消息的消息传递失败原因[关闭]