diff --git a/pkgs/clan-cli/clan_cli/ssh/__init__.py b/pkgs/clan-cli/clan_cli/ssh/__init__.py index 89e38b5a..2d3ef34f 100644 --- a/pkgs/clan-cli/clan_cli/ssh/__init__.py +++ b/pkgs/clan-cli/clan_cli/ssh/__init__.py @@ -270,30 +270,37 @@ class Host: cwd: None | str | Path = None, check: bool = True, timeout: float = math.inf, + interactive: bool = False, ) -> subprocess.CompletedProcess[str]: with ExitStack() as stack: read_std_fd, write_std_fd = (None, None) read_err_fd, write_err_fd = (None, None) - if stdout is None or stderr is None: + if not interactive and (stdout is None or stderr is None): read_std_fd, write_std_fd = stack.enter_context(_pipe()) read_err_fd, write_err_fd = stack.enter_context(_pipe()) - if stdout is None: + if interactive: stdout_read = None - stdout_write = write_std_fd - elif stdout == subprocess.PIPE: - stdout_read, stdout_write = stack.enter_context(_pipe()) - else: - raise Exception(f"unsupported value for stdout parameter: {stdout}") - - if stderr is None: stderr_read = None - stderr_write = write_err_fd - elif stderr == subprocess.PIPE: - stderr_read, stderr_write = stack.enter_context(_pipe()) + stdout_write: IO[str] | None = sys.stdout + stderr_write: IO[str] | None = sys.stderr else: - raise Exception(f"unsupported value for stderr parameter: {stderr}") + if stdout is None: + stdout_read = None + stdout_write = write_std_fd + elif stdout == subprocess.PIPE: + stdout_read, stdout_write = stack.enter_context(_pipe()) + else: + raise Exception(f"unsupported value for stdout parameter: {stdout}") + + if stderr is None: + stderr_read = None + stderr_write = write_err_fd + elif stderr == subprocess.PIPE: + stderr_read, stderr_write = stack.enter_context(_pipe()) + else: + raise Exception(f"unsupported value for stderr parameter: {stderr}") env = os.environ.copy() env.update(extra_env) @@ -319,14 +326,17 @@ class Host: stderr_write.close() start = time.time() - stdout_data, stderr_data = self._prefix_output( - displayed_cmd, - read_std_fd, - read_err_fd, - stdout_read, - stderr_read, - timeout, - ) + if interactive: + stdout_data, stderr_data = "", "" + else: + stdout_data, stderr_data = self._prefix_output( + displayed_cmd, + read_std_fd, + read_err_fd, + stdout_read, + stderr_read, + timeout, + ) try: ret = p.wait(timeout=max(0, timeout - (time.time() - start))) except subprocess.TimeoutExpired: @@ -356,6 +366,7 @@ class Host: cwd: None | str | Path = None, check: bool = True, timeout: float = math.inf, + interactive: bool = False, ) -> subprocess.CompletedProcess[str]: """ Command to run locally for the host @@ -387,6 +398,7 @@ class Host: cwd=cwd, check=check, timeout=timeout, + interactive=interactive, ) def run( @@ -398,8 +410,9 @@ class Host: extra_env: dict[str, str] = {}, cwd: None | str | Path = None, check: bool = True, - verbose_ssh: bool = False, timeout: float = math.inf, + interactive: bool = False, + verbose_ssh: bool = False, tty: bool = True, ) -> subprocess.CompletedProcess[str]: """ @@ -458,6 +471,7 @@ class Host: cwd=cwd, check=check, timeout=timeout, + interactive=interactive, ) def ssh_cmd( @@ -623,9 +637,10 @@ class HostGroup: extra_env: dict[str, str] = {}, cwd: None | str | Path = None, check: bool = True, + timeout: float = math.inf, + interactive: bool = False, verbose_ssh: bool = False, tty: bool = True, - timeout: float = math.inf, ) -> Results: results: Results = [] threads = [] @@ -642,8 +657,9 @@ class HostGroup: extra_env=extra_env, cwd=cwd, check=check, - verbose_ssh=verbose_ssh, timeout=timeout, + interactive=interactive, + verbose_ssh=verbose_ssh, tty=tty, ), )