过滤输出由tee写入文件,但不是由tee写入控制台的输出

问题描述 投票:0回答:1

我知道有类似的问题,但我一直无法找到解决这种特殊情况的任何问题。

我有一系列不同的python脚本使用logging库(打印到stderr)。这些脚本由bash脚本串联在一起,它按顺序调用它们并通过cron进行调度。在每次运行结束时,bash脚本通过电子邮件发送各种退出代码的摘要,并且旨在包含各种其他日志记录消息(即,如果存在critical级别的日志记录事件,它应该使其成为我所称的“cron log”)。

由于python代码本身在日志记录中非常冗长,我不想不小心给自己发送一个5-10MB的日志,而且我只想要特定的输出来进入cron日志。我想使用tee来过滤来自python的stderr日志记录,并且只将特定消息定向到cron日志,但是所有消息仍然应该进入控制台。

为了重现性,请说我有以下bash脚本:

#!/bin/bash

LOGPFX="BASH"  # if a log msg has this term, put it in CRONLOG
CRONLOG="cronlog.txt"

exec 2> >(grep ${LOGPFX} | tee -a ${CRONLOG})

# run
python test.py

以下是test.py的内容:

import logging

def get_logger():
    logger = logging.getLogger("testlog")
    logger.setLevel(logging.INFO)
    lformat = "%(asctime)s - %(levelname)s - %(module)s - %(funcName)s - %(message)s"

    handler = logging.StreamHandler()
    handler.setLevel(logging.INFO)
    handler.setFormatter(logging.Formatter(lformat))

    logger.addHandler(handler)
    return logger

if __name__ == '__main__':
    logger = get_logger()
    logger.info("Should not appear in console but not cronlog.txt")
    logger.info("[BASH INFO] Should appear in both")

"[BASH INFO] Should appear in both"消息确实成功进入了cron日志,但问题是第一个日志消息完全从控制台输出中省略。如何过滤这些消息,使那些通过grep的消息进入控制台和日志,而其他所有消息只能进入控制台?

我知道这是需要改变的路线:

exec 2> >(grep ${LOGPFX} | tee -a ${CRONLOG})

cronlog.txt的内容:

$ cat cronlog.txt 
2017-12-21 08:19:39,267 - INFO - test - <module> - [BASH INFO] Should appear in both

我也测试了这个版本的bash:

#!/bin/bash

LOGPFX="BASH"
CRONLOG="cronlog.txt"

ftee () {
    echo "I FOUND THIS: ${1}"
    echo "$1" >> ${CRONLOG}
}

exec 2> >(grep ${LOGPFX} | ftee) 2>&1

# run
python test.py

它正确地将所有内容指向控制台,但没有将正确的消息写入日志("I FOUND THIS: ${1}"行打印一个空字符串)

python bash tee
1个回答
1
投票

tee写入另一个进程替换(在写入之前执行grep)将完成这一操作:

# all-caps variable names are used for variables with meaning to the shell
# don't use them for names you assign yourself.
logpfx="BASH"  # if a log msg has this term, put it in CRONLOG
cronlog="cronlog.txt"

exec 3>&2 # backup original stderr on FD 3
exec 2> >(tee -a >(grep "$logpfx" >"$cronlog"))

请注意,在邮寄日志之前,您应确保关闭文件描述符并让它刷新。因此,在收集您要记录的内容并在发送电子邮件之前,您需要运行:

exec 2>&3 # restore backup of original FD 3, so tee and grep can exit
© www.soinside.com 2019 - 2024. All rights reserved.