Я пишу модуль ControlCaller, чтобы контролировать только одну команду, которая может быть выполнена одновременно. Я использую threading.Lock (), чтобы сделать это. Но иногда замок не открывается вечно. Кажется, есть ошибка, но я не могу понять.
Есть два основных метода. Точка входа "вызов":
def _command_caller(self, cmd, timeout):
with subprocess.Popen(cmd, universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE) as process:
try:
stdout, stderr = process.communicate(timeout=timeout)
except Exception:
process.kill()
raise Exception("run command timeout")
retcode = process.poll()
if retcode:
self.logger.error("run command failed. %s", str(stderr))
raise Exception("run command failed")
else:
return stdout
def call(self, cmd, timeout=10):
start_time = time.time()
if self.caller_lock.acquire(timeout=timeout) is False:
return {"returncode": -1,
"output": "cannot acquire lock"}
try:
self.logger.debug("Run cmd: %s", " ".join(cmd))
result = {}
stdout = self._command_caller(cmd, timeout=timeout)
self.except_cnt = 0
result = {"returncode": 0,
"output": stdout.strip()}
except Exception as e:
self.logger.debug("Caller handle exception")
result = {"returncode": -1,
"output": str(e)}
finally:
self.logger.debug("Release Lock after run cmd: %s", " ".join(cmd))
self.logger.debug("Cost Time: %s", str(time.time() - start_time))
self.caller_lock.release()
return result
Журнал сообщений:
2020-02-13 03:42:36,966 [DEBUG] - interface.control_caller: Run cmd: ipmitool sdr
2020-02-13 03:42:38,055 [DEBUG] - interface.control_caller: Release Lock after run cmd: ipmitool sdr
2020-02-13 03:42:38,055 [DEBUG] - interface.control_caller: Cost Time: 1.0889253616333008
2020-02-13 03:42:38,056 [DEBUG] - interface.control_caller: Run cmd: ipmitool power status
2020-02-13 03:42:48,058 [WARNING] - interface.control_caller: cannot acquire lock
2020-02-13 03:43:01,062 [WARNING] - interface.control_caller: cannot acquire lock