🐍 Python может автоматически останавливать зависшие процессы, не оставляя дочерние задачи работать в фоне
👁 При автоматизации через
subprocess недостаточно установить тайм-аут: если команда запускает дочерние процессы, завершение родительского процесса не гарантирует остановку всей цепочки. В Linux можно запускать каждую задачу в отдельной группе процессов и при превышении лимита завершать всю группу.📝 Запускаем команду с контролем времени и всей группы процессов:
import os
import signal
import subprocess
def run_task(command: list[str], timeout: int = 30) -> str:
proc = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
start_new_session=True,
)
try:
output, _ = proc.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
try:
os.killpg(proc.pid, signal.SIGTERM)
except ProcessLookupError:
pass
try:
output, _ = proc.communicate(timeout=3)
except subprocess.TimeoutExpired:
try:
os.killpg(proc.pid, signal.SIGKILL)
except ProcessLookupError:
pass
output, _ = proc.communicate()
raise TimeoutError(
f"Команда превысила лимит {timeout} с.\n{output}"
)
if proc.returncode != 0:
raise subprocess.CalledProcessError(
proc.returncode, command, output=output
)
return output
print(run_task(["python", "-c", "print('Задача выполнена')"]))
📌 Как это работает:
•
start_new_session=True создаёт новую сессию, в которой процесс становится лидером своей группы.•
communicate(timeout=...) ограничивает время ожидания и одновременно считывает вывод, предотвращая переполнение каналов.• При тайм-ауте сначала отправляется
SIGTERM, а затем SIGKILL, если процесс не завершился за три секунды.❗️ Важно: завершение группы охватывает процессы, которые остаются в ней. Если дочерний процесс самостоятельно создаст новую сессию или группу, этот способ не гарантирует его остановку. Для жёсткой изоляции недоверенных задач лучше использовать отдельный cgroup или системный менеджер служб.
tags: #python #автоматизация #linux
🧭 @recura_tech