diff --git a/fail2ban/server/action.py b/fail2ban/server/action.py index 6c36bbca..dcc4dad6 100644 --- a/fail2ban/server/action.py +++ b/fail2ban/server/action.py @@ -27,7 +27,7 @@ __date__ = "$Date$" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import logging, os, subprocess, time, signal +import logging, os, subprocess, time, signal, tempfile import threading #from subprocess import call @@ -353,8 +353,11 @@ class Action: logSys.debug(realCmd) _cmd_lock.acquire() try: # Try wrapped within another try needed for python version < 2.5 + stdout = tempfile.TemporaryFile(suffix=".stdout", prefix="fai2ban_") + stderr = tempfile.TemporaryFile(suffix=".stderr", prefix="fai2ban_") try: - popen = subprocess.Popen(realCmd, shell=True) + popen = subprocess.Popen( + realCmd, stdout=stdout, stderr=stderr, shell=True) stime = time.time() retcode = popen.poll() while time.time() - stime <= timeout and retcode is None: @@ -376,6 +379,15 @@ class Action: finally: _cmd_lock.release() + std_level = retcode == 0 and logging.DEBUG or logging.ERROR + if std_level >= logSys.getEffectiveLevel(): + stdout.seek(0) + logSys.log(std_level, "%s stdout: %r" % (realCmd, stdout.read())) + stderr.seek(0) + logSys.log(std_level, "%s stderr: %r" % (realCmd, stderr.read())) + stdout.close() + stderr.close() + if retcode == 0: logSys.debug("%s returned successfully" % realCmd) return True diff --git a/fail2ban/tests/actiontestcase.py b/fail2ban/tests/actiontestcase.py index 6cac0c14..abeab7d6 100644 --- a/fail2ban/tests/actiontestcase.py +++ b/fail2ban/tests/actiontestcase.py @@ -103,3 +103,11 @@ class ExecuteAction(unittest.TestCase): self.assertAlmostEqual(time.time() - stime, 2.1, places=1) self.assertTrue(self._is_logged('sleep 60 timed out after 2 seconds')) self.assertTrue(self._is_logged('sleep 60 killed with SIGTERM')) + + def testCaptureStdOutErr(self): + Action.executeCmd('echo "How now brown cow"') + self.assertTrue(self._is_logged("'How now brown cow\\n'")) + Action.executeCmd( + 'echo "The rain in Spain stays mainly in the plain" 1>&2') + self.assertTrue(self._is_logged( + "'The rain in Spain stays mainly in the plain\\n'"))