Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02669-87ee-7a31-b111-edc95a16e0fa
43 lines
1.4 KiB
Python
Executable file
43 lines
1.4 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""Small, value-safe SSH argv transport shared by attended procedures."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shlex
|
|
import subprocess
|
|
from typing import Callable
|
|
|
|
|
|
class RemoteExecutionError(RuntimeError):
|
|
pass
|
|
|
|
|
|
def remote_command(argv: list[str]) -> str:
|
|
if not argv or any(not isinstance(part, str) or "\0" in part for part in argv):
|
|
raise RemoteExecutionError("remote argv must contain non-NUL strings")
|
|
return shlex.join(argv)
|
|
|
|
|
|
def run_remote(
|
|
host: str,
|
|
argv: list[str],
|
|
*,
|
|
label: str,
|
|
input_text: str | None = None,
|
|
allow_missing: bool = False,
|
|
runner: Callable[..., subprocess.CompletedProcess[str]] = subprocess.run,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
if not host or any(character.isspace() for character in host):
|
|
raise RemoteExecutionError("remote host must be a single SSH destination")
|
|
completed = runner(
|
|
["ssh", "-o", "BatchMode=yes", host, remote_command(argv)],
|
|
text=True,
|
|
capture_output=True,
|
|
input=input_text,
|
|
check=False,
|
|
)
|
|
if completed.returncode and not (allow_missing and completed.returncode == 1):
|
|
# Remote output may contain provider or application material. Keep the
|
|
# durable error value-safe and let an attended operator inspect locally.
|
|
raise RemoteExecutionError(f"{label} failed (exit {completed.returncode})")
|
|
return completed
|