from __future__ import annotations import io import tarfile from typing import Tuple def exec_shell(container, cmd: str) -> Tuple[int, str]: for shell in (["sh", "-lc"], ["bash", "-lc"]): try: res = container.exec_run(shell + [cmd], demux=False) out = res.output.decode(errors="ignore") if isinstance(res.output, (bytes, bytearray)) else str(res.output) return res.exit_code, out except Exception: continue return 127, "" def read_text_from_container(container, abs_path: str, max_bytes: int = 800_000) -> str: stream, _stat = container.get_archive(abs_path) buf = io.BytesIO() for chunk in stream: buf.write(chunk) if buf.tell() > max_bytes: break buf.seek(0) with tarfile.open(fileobj=buf) as tar: members = tar.getmembers() if not members: raise FileNotFoundError(abs_path) f = tar.extractfile(members[0]) if f is None: raise FileNotFoundError(abs_path) return f.read().decode(errors="ignore")