diff --git a/scripts/safe-restart.sh b/scripts/safe-restart.sh new file mode 100755 index 0000000..1dc16d8 --- /dev/null +++ b/scripts/safe-restart.sh @@ -0,0 +1,39 @@ +#!/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 \ No newline at end of file