mirror of https://github.com/fail2ban/fail2ban
fail2ban-regex: stop endless logging on closed streams (redirected pipes like `... | head -n 100`), exit if stdout channel is closed
parent
12b3ac684a
commit
9c7bd80807
|
@ -709,6 +709,7 @@ class Fail2banRegex(object):
|
||||||
|
|
||||||
|
|
||||||
def exec_command_line(*args):
|
def exec_command_line(*args):
|
||||||
|
logging.exitOnIOError = True
|
||||||
parser = get_opt_parser()
|
parser = get_opt_parser()
|
||||||
(opts, args) = parser.parse_args(*args)
|
(opts, args) = parser.parse_args(*args)
|
||||||
errors = []
|
errors = []
|
||||||
|
|
|
@ -208,6 +208,25 @@ class FormatterWithTraceBack(logging.Formatter):
|
||||||
return logging.Formatter.format(self, record)
|
return logging.Formatter.format(self, record)
|
||||||
|
|
||||||
|
|
||||||
|
logging.exitOnIOError = False
|
||||||
|
def __stopOnIOError(logSys=None, logHndlr=None): # pragma: no cover
|
||||||
|
if logSys and len(logSys.handlers):
|
||||||
|
logSys.removeHandler(logSys.handlers[0])
|
||||||
|
if logHndlr:
|
||||||
|
logHndlr.close = lambda: None
|
||||||
|
logging.StreamHandler.flush = lambda self: None
|
||||||
|
#sys.excepthook = lambda *args: None
|
||||||
|
if logging.exitOnIOError:
|
||||||
|
try:
|
||||||
|
sys.stderr.close()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
try:
|
||||||
|
BrokenPipeError
|
||||||
|
except NameError: # pragma: 3.x no cover
|
||||||
|
BrokenPipeError = IOError
|
||||||
__origLog = logging.Logger._log
|
__origLog = logging.Logger._log
|
||||||
def __safeLog(self, level, msg, args, **kwargs):
|
def __safeLog(self, level, msg, args, **kwargs):
|
||||||
"""Safe log inject to avoid possible errors by unsafe log-handlers,
|
"""Safe log inject to avoid possible errors by unsafe log-handlers,
|
||||||
|
@ -223,6 +242,10 @@ def __safeLog(self, level, msg, args, **kwargs):
|
||||||
try:
|
try:
|
||||||
# if isEnabledFor(level) already called...
|
# if isEnabledFor(level) already called...
|
||||||
__origLog(self, level, msg, args, **kwargs)
|
__origLog(self, level, msg, args, **kwargs)
|
||||||
|
except (BrokenPipeError, IOError) as e: # pragma: no cover
|
||||||
|
if e.errno == 32: # closed / broken pipe
|
||||||
|
__stopOnIOError(self)
|
||||||
|
raise
|
||||||
except Exception as e: # pragma: no cover - unreachable if log-handler safe in this python-version
|
except Exception as e: # pragma: no cover - unreachable if log-handler safe in this python-version
|
||||||
try:
|
try:
|
||||||
for args in (
|
for args in (
|
||||||
|
@ -237,6 +260,18 @@ def __safeLog(self, level, msg, args, **kwargs):
|
||||||
pass
|
pass
|
||||||
logging.Logger._log = __safeLog
|
logging.Logger._log = __safeLog
|
||||||
|
|
||||||
|
__origLogFlush = logging.StreamHandler.flush
|
||||||
|
def __safeLogFlush(self):
|
||||||
|
"""Safe flush inject stopping endless logging on closed streams (redirected pipe).
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
__origLogFlush(self)
|
||||||
|
except (BrokenPipeError, IOError) as e: # pragma: no cover
|
||||||
|
if e.errno == 32: # closed / broken pipe
|
||||||
|
__stopOnIOError(None, self)
|
||||||
|
raise
|
||||||
|
logging.StreamHandler.flush = __safeLogFlush
|
||||||
|
|
||||||
def getLogger(name):
|
def getLogger(name):
|
||||||
"""Get logging.Logger instance with Fail2Ban logger name convention
|
"""Get logging.Logger instance with Fail2Ban logger name convention
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue