Files
gniza4linux/tui/backend.py
shuki 8fec087987 Write job output to file instead of pipe to survive TUI exit
The subprocess stdout was a pipe to the TUI. When the TUI exited, the
pipe broke (SIGPIPE) and killed the backup process. Now the subprocess
writes to a log file in WORK_DIR, and the TUI tails it for live
display. When the TUI exits, the subprocess keeps running because it
writes to a file, not a pipe. On restart, the log file is loaded to
show output for reconnected or finished background jobs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:50:09 +02:00

61 lines
1.7 KiB
Python

import asyncio
import os
from pathlib import Path
def _gniza_bin() -> str:
gniza_dir = os.environ.get("GNIZA_DIR", "")
if gniza_dir:
return str(Path(gniza_dir) / "bin" / "gniza")
here = Path(__file__).resolve().parent.parent / "bin" / "gniza"
if here.is_file():
return str(here)
return "gniza"
async def run_cli(*args: str) -> tuple[int, str, str]:
cmd = [_gniza_bin(), "--cli"] + list(args)
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
stdout, stderr = await proc.communicate()
return proc.returncode or 0, stdout.decode(), stderr.decode()
async def start_cli_process(*args: str, log_file: str | None = None) -> asyncio.subprocess.Process:
cmd = [_gniza_bin(), "--cli"] + list(args)
if log_file:
fh = open(log_file, "w")
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=fh,
stderr=asyncio.subprocess.STDOUT,
start_new_session=True,
)
fh.close()
return proc
return await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
start_new_session=True,
)
async def stream_cli(callback, *args: str) -> int:
cmd = [_gniza_bin(), "--cli"] + list(args)
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.STDOUT,
)
while True:
line = await proc.stdout.readline()
if not line:
break
callback(line.decode().rstrip("\n"))
await proc.wait()
return proc.returncode or 0