diff --git a/fail2ban/server/action.py b/fail2ban/server/action.py index a61bbfab..ab27c83a 100644 --- a/fail2ban/server/action.py +++ b/fail2ban/server/action.py @@ -787,7 +787,10 @@ class CommandAction(ActionBase): # otherwise stop/start will theoretically remove all the bans, # but the tickets are still in BanManager, so in case of new failures # it will not be banned, because "already banned" will happen. - self.stop() + try: + self.stop() + except RuntimeError: # bypass error in stop (if start/check succeeded hereafter). + pass self.start() if not self.executeCmd(checkCmd, self.timeout): self._logSys.critical("Unable to restore environment") diff --git a/fail2ban/tests/actiontestcase.py b/fail2ban/tests/actiontestcase.py index 3a069c65..9ed0ad8e 100644 --- a/fail2ban/tests/actiontestcase.py +++ b/fail2ban/tests/actiontestcase.py @@ -335,7 +335,16 @@ class CommandActionTest(LogCaptureTestCase): self.__action.actionban = "rm /tmp/fail2ban.test" self.__action.actioncheck = "[ -e /tmp/fail2ban.test ]" self.assertRaises(RuntimeError, self.__action.ban, {'ip': None}) - self.assertLogged('Unable to restore environment') + self.assertLogged('Invariant check failed', 'Unable to restore environment', all=True) + # 2nd time, try to restore with producing error in stop, but succeeded start hereafter: + self.pruneLog('[phase 2]') + self.__action.actionstart = "touch /tmp/fail2ban.test" + self.__action.actionstop = "rm /tmp/fail2ban.test" + self.__action.actionban = 'printf "%%b\n" >> /tmp/fail2ban.test' + self.__action.actioncheck = "[ -e /tmp/fail2ban.test ]" + self.__action.ban({'ip': None}) + self.assertLogged('Invariant check failed') + self.assertNotLogged('Unable to restore environment') def testExecuteActionCheckRepairEnvironment(self): self.__action.actionstart = ""