#!/bin/bash # t-260929210755 / закрытие эскалации e-260929234911: рестарт демона лестницы # БЕЗ убийства живых LLM-воркеров (рестарт при живом воркере = застрявшая # running-задача, тот самый инцидент). Ждём «тихого окна» — нет процессов # harness/_llm_worker.py, с подтверждением 3с, потом systemctl restart. # # Гарантия на гонку «проверил → стартовал новый воркер → рестарт»: orphan-requeue # (commit 42743f9) возвращает running-задачи с мёртвым воркером в очередь — # даже худший случай не теряет работу, просто повторит её. # # Использование: scripts/safe-restart.sh [max_wait_sec] (по умолчанию 3600) set -u MAX_WAIT="${1:-3600}" LOG="${SIMBIOT_RESTART_LOG:-/tmp/simbiot-safe-restart.log}" SERVICE="${SIMBIOT_SERVICE:-simbiot-harness}" # якорь в конец cmdline: не матчит sh -c команды, которые лишь УПОМИНАют воркера PAT='/harness/_llm_worker\.py$' deadline=$(( $(date +%s) + MAX_WAIT )) echo "[$(date -u '+%F %T')] safe-restart: ждём тихое окно (макс ${MAX_WAIT}s), сервис ${SERVICE}" >> "$LOG" while :; do if ! pgrep -f "$PAT" > /dev/null; then sleep 3 # окно должно быть устойчивым if ! pgrep -f "$PAT" > /dev/null; then echo "[$(date -u '+%F %T')] safe-restart: тихое окно поймано" >> "$LOG" break fi fi if [ "$(date +%s)" -ge "$deadline" ]; then echo "[$(date -u '+%F %T')] safe-restart: тихого окна нет ${MAX_WAIT}s — рестарт всё равно (orphan-requeue подхватит)" >> "$LOG" break fi sleep 5 done if systemctl restart "$SERVICE"; then echo "[$(date -u '+%F %T')] safe-restart: демон ${SERVICE} перезапущен" >> "$LOG" else echo "[$(date -u '+%F %T')] safe-restart: FAIL — systemctl restart ${SERVICE}" >> "$LOG" exit 1 fi