Last active
December 16, 2015 19:28
-
-
Save kwirk/5484839 to your computer and use it in GitHub Desktop.
fail2ban/fail2ba issue #190
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/fail2ban/server/action.py b/fail2ban/server/action.py | |
index 6c36bbc..38c2c00 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 | |
@@ -52,6 +52,11 @@ _RETCODE_HINTS = { | |
signame = dict((num, name) | |
for name, num in signal.__dict__.iteritems() if name.startswith("SIG")) | |
+# Globals for capturing STDOUT and STDERR. | |
+# Use within command thread lock only. | |
+STDOUT = tempfile.TemporaryFile(suffix=".stdout", prefix="fai2ban_") | |
+STDERR = tempfile.TemporaryFile(suffix=".stderr", prefix="fai2ban_") | |
+ | |
## | |
# Execute commands. | |
# | |
@@ -353,8 +358,13 @@ class Action: | |
logSys.debug(realCmd) | |
_cmd_lock.acquire() | |
try: # Try wrapped within another try needed for python version < 2.5 | |
+ STDOUT.seek(0) | |
+ STDOUT.truncate() | |
+ STDERR.seek(0) | |
+ STDERR.truncate() | |
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: | |
@@ -373,9 +383,18 @@ class Action: | |
except OSError, e: | |
logSys.error("%s failed with %s" % (realCmd, e)) | |
return False | |
+ | |
+ STDOUT.seek(0) | |
+ stdout = STDOUT.read() | |
+ STDERR.seek(0) | |
+ stderr = STDERR.read() | |
finally: | |
_cmd_lock.release() | |
+ std_level = retcode == 0 and logging.DEBUG or logging.ERROR | |
+ logSys.log(std_level, "%s stdout: %s" % (realCmd, `stdout`)) | |
+ logSys.log(std_level, "%s stderr: %s" % (realCmd, `stderr`)) | |
+ | |
if retcode == 0: | |
logSys.debug("%s returned successfully" % realCmd) | |
return True | |
diff --git a/fail2ban/tests/actiontestcase.py b/fail2ban/tests/actiontestcase.py | |
index 6cac0c1..abeab7d 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'")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment