From 7eda0ac20c96dfc4bcd8774da99fed026ab2b4a4 Mon Sep 17 00:00:00 2001 From: Sven Sager Date: Fri, 7 Aug 2026 06:26:48 +0200 Subject: [PATCH] refactor: Include exit status in `send_cmd` and improve decoding logic Extend `send_cmd` to return `exit_status` along with `stdout` and `stderr`. Adjust handling to ensure proper decoding of byte outputs to strings. Signed-off-by: Sven Sager --- src/revpicommander/helper.py | 2 +- src/revpicommander/ssh_tunneling/server.py | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/revpicommander/helper.py b/src/revpicommander/helper.py index f40b016..e69c83a 100644 --- a/src/revpicommander/helper.py +++ b/src/revpicommander/helper.py @@ -383,7 +383,7 @@ class ConnectionManager(QtCore.QThread): # Check for Unix socket on remote system try: - stdout, stderr = ssh_tunnel_server.send_cmd("cat /etc/revpipyload/revpipyload.conf") + stdout, stderr, exit_code = ssh_tunnel_server.send_cmd("cat /etc/revpipyload/revpipyload.conf") if stdout: config = ConfigParser() config.read_string(stdout) diff --git a/src/revpicommander/ssh_tunneling/server.py b/src/revpicommander/ssh_tunneling/server.py index d00a25a..84d4573 100644 --- a/src/revpicommander/ssh_tunneling/server.py +++ b/src/revpicommander/ssh_tunneling/server.py @@ -187,13 +187,13 @@ class SSHLocalTunnel: except Exception: return True - def send_cmd(self, cmd: str, timeout: float = None) -> Union[Tuple[str, str], Tuple[None, None]]: + def send_cmd(self, cmd: str, timeout: float = None) -> Union[Tuple[str, str, int], Tuple[None, None, None]]: """ Send simple command to ssh host. :param cmd: Shell command to execute on remote host :param timeout: Timeout for execution - :return: Tuple with stdout and stderr + :return: Tuple with stdout, stderr, exit status """ if not self.connected: raise RuntimeError("Not connected") @@ -201,15 +201,19 @@ class SSHLocalTunnel: # Running async command from sync context async def _exec(): result = await self._conn.run(cmd, timeout=timeout) - return result.stdout, result.stderr + return result.stdout, result.stderr, result.exit_status try: future = asyncio.run_coroutine_threadsafe(_exec(), self._loop) - stdout, stderr = future.result(timeout=timeout) - return stdout, stderr + stdout, stderr, exit_status = future.result(timeout=timeout) + if type(stdout) is bytes: + stdout = stdout.decode(errors="ignore") + if type(stderr) is bytes: + stderr = stderr.decode(errors="ignore") + return stdout, stderr, exit_status except Exception as e: log.error(e) - return None, None + return None, None, None @property def connected(self):