177 lines
5.9 KiB
Python
Raw Normal View History

2025-11-04 05:17:27 +01:00
import os
2025-11-04 08:09:12 +01:00
import select
2025-11-04 05:17:27 +01:00
import subprocess
import time
2025-11-04 08:09:12 +01:00
from pr.multiplexer import close_multiplexer, create_multiplexer, get_multiplexer
2025-11-04 05:17:27 +01:00
_processes = {}
2025-11-04 08:09:12 +01:00
def _register_process(pid: int, process):
2025-11-04 05:17:27 +01:00
_processes[pid] = process
return _processes
2025-11-04 08:09:12 +01:00
def _get_process(pid: int):
2025-11-04 05:17:27 +01:00
return _processes.get(pid)
2025-11-04 08:09:12 +01:00
def kill_process(pid: int):
2025-11-04 05:17:27 +01:00
try:
process = _get_process(pid)
if process:
process.kill()
_processes.pop(pid)
mux_name = f"cmd-{pid}"
if get_multiplexer(mux_name):
close_multiplexer(mux_name)
return {"status": "success", "message": f"Process {pid} has been killed"}
else:
return {"status": "error", "error": f"Process {pid} not found"}
except Exception as e:
return {"status": "error", "error": str(e)}
def tail_process(pid: int, timeout: int = 30):
process = _get_process(pid)
if process:
mux_name = f"cmd-{pid}"
mux = get_multiplexer(mux_name)
if not mux:
mux_name, mux = create_multiplexer(mux_name, show_output=True)
try:
start_time = time.time()
timeout_duration = timeout
stdout_content = ""
stderr_content = ""
while True:
if process.poll() is not None:
remaining_stdout, remaining_stderr = process.communicate()
if remaining_stdout:
mux.write_stdout(remaining_stdout)
stdout_content += remaining_stdout
if remaining_stderr:
mux.write_stderr(remaining_stderr)
stderr_content += remaining_stderr
if pid in _processes:
_processes.pop(pid)
close_multiplexer(mux_name)
return {
"status": "success",
"stdout": stdout_content,
"stderr": stderr_content,
2025-11-04 08:09:12 +01:00
"returncode": process.returncode,
2025-11-04 05:17:27 +01:00
}
if time.time() - start_time > timeout_duration:
return {
"status": "running",
"message": "Process is still running. Call tail_process again to continue monitoring.",
"stdout_so_far": stdout_content,
"stderr_so_far": stderr_content,
2025-11-04 08:09:12 +01:00
"pid": pid,
2025-11-04 05:17:27 +01:00
}
2025-11-04 08:10:37 +01:00
ready, _, _ = select.select([process.stdout, process.stderr], [], [], 0.1)
2025-11-04 05:17:27 +01:00
for pipe in ready:
if pipe == process.stdout:
line = process.stdout.readline()
if line:
mux.write_stdout(line)
stdout_content += line
elif pipe == process.stderr:
line = process.stderr.readline()
if line:
mux.write_stderr(line)
stderr_content += line
except Exception as e:
return {"status": "error", "error": str(e)}
else:
return {"status": "error", "error": f"Process {pid} not found"}
2025-11-04 07:52:36 +01:00
def run_command(command, timeout=30, monitored=False):
2025-11-04 05:17:27 +01:00
mux_name = None
try:
2025-11-04 08:09:12 +01:00
process = subprocess.Popen(
command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
2025-11-04 05:17:27 +01:00
_register_process(process.pid, process)
mux_name, mux = create_multiplexer(f"cmd-{process.pid}", show_output=True)
start_time = time.time()
timeout_duration = timeout
stdout_content = ""
stderr_content = ""
while True:
if process.poll() is not None:
remaining_stdout, remaining_stderr = process.communicate()
if remaining_stdout:
mux.write_stdout(remaining_stdout)
stdout_content += remaining_stdout
if remaining_stderr:
mux.write_stderr(remaining_stderr)
stderr_content += remaining_stderr
if process.pid in _processes:
_processes.pop(process.pid)
close_multiplexer(mux_name)
return {
"status": "success",
"stdout": stdout_content,
"stderr": stderr_content,
2025-11-04 08:09:12 +01:00
"returncode": process.returncode,
2025-11-04 05:17:27 +01:00
}
if time.time() - start_time > timeout_duration:
return {
"status": "running",
"message": f"Process still running after {timeout}s timeout. Use tail_process({process.pid}) to monitor or kill_process({process.pid}) to terminate.",
"stdout_so_far": stdout_content,
"stderr_so_far": stderr_content,
"pid": process.pid,
2025-11-04 08:09:12 +01:00
"mux_name": mux_name,
2025-11-04 05:17:27 +01:00
}
ready, _, _ = select.select([process.stdout, process.stderr], [], [], 0.1)
for pipe in ready:
if pipe == process.stdout:
line = process.stdout.readline()
if line:
mux.write_stdout(line)
stdout_content += line
elif pipe == process.stderr:
line = process.stderr.readline()
if line:
mux.write_stderr(line)
stderr_content += line
except Exception as e:
if mux_name:
close_multiplexer(mux_name)
return {"status": "error", "error": str(e)}
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
def run_command_interactive(command):
try:
return_code = os.system(command)
return {"status": "success", "returncode": return_code}
except Exception as e:
return {"status": "error", "error": str(e)}