Ich weiß, dass ähnliche Fragen gefragt worden sind, aber ich konnte nichts finden, das diese bestimmte Situation anspricht.Filterausgabe geschrieben durch T-Stück zur Datei, aber nicht ausgegeben durch T-Stück zur Konsole geschrieben
Ich habe eine Reihe von verschiedenen Python-Skripten, die die logging
Bibliothek verwenden (die auf stderr
druckt). Diese Skripte werden von einem Bash-Skript aneinandergereiht, das sie sequentiell aufruft und über cron
eingeplant ist. Am Ende jedes Laufs sendet das Bash-Skript eine Zusammenfassung der verschiedenen Beendigungscodes per E-Mail und soll verschiedene andere Logging-Nachrichten enthalten (dh wenn es eine critical
Level Logging-Vorkommen gibt, sollte es zu dem kommen, was ich anrufe "Cron-Protokoll").
Da der Python-Code selbst ziemlich ausführlich in seiner Protokollierung ist, möchte ich nicht versehentlich ein 5-10MB-Protokoll per E-Mail senden, und ich möchte nur bestimmte Ausgabe, um es in das Cron-Protokoll zu machen. Ich möchte tee
verwenden, um die stderr
Protokollierung von Python zu filtern, und nur direkte insbesondere Nachrichten an die Cron-Protokoll, aber alle Nachrichten sollten es immer noch auf die Konsole machen.
Für Reproduzierbarkeit, sage ich das folgende Bash-Skript haben:
#!/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
Und hier sind die Inhalte von 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")
Die "[BASH INFO] Should appear in both"
Nachricht hat erfolgreich machen zum cron log , aber das Problem besteht darin, dass die erste Protokollierungsnachricht in der Konsolenausgabe vollständig weggelassen wird. Wie kann ich diese Nachrichten filtern, so dass diejenigen, die die grep
übergeben, es an die Konsole und das Protokoll machen, während alle anderen es nur an die Konsole schaffen?
Ich weiß, dass dies die Linie ist, die sich ändern muss:
exec 2> >(grep ${LOGPFX} | tee -a ${CRONLOG})
Inhalt von cronlog.txt
:
$ cat cronlog.txt
2017-12-21 08:19:39,267 - INFO - test - <module> - [BASH INFO] Should appear in both
ich auch diese Version der bash getestet haben:
#!/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
, die alles ordnungsgemäß an die Konsole leitet, aber nicht die richtige Nachricht in das Protokoll schreibt (Die "I FOUND THIS: ${1}"
Linie druckt eine leere Zeichenkette)
'ftee' offensichtlich gebrochen ist - siehe [BashFAQ # 1] (http: //mywiki.wooledge .org/BashFAQ/001) als Anleitung zum Lesen von stdin, vs. der Befehlszeile (die es ab sofort liest, obwohl auf seiner Kommandozeile nichts übergeben wurde). –