我知道有类似的问题已被提出,但我一直无法找到解决这种特殊情况的任何问题。
我有一系列使用logging
库(打印到stderr
)的不同python脚本。这些脚本由bash脚本串联在一起,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}"
行打印空字符串)
答案 0 :(得分: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