Skip to content

Instantly share code, notes, and snippets.

@kwirk
Last active December 16, 2015 19:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kwirk/5484839 to your computer and use it in GitHub Desktop.
Save kwirk/5484839 to your computer and use it in GitHub Desktop.
fail2ban/fail2ba issue #190
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