Как получить супервизор для перезапуска висячих работников?

У меня есть несколько рабочих Python, которым управляет супервизор, который должен непрерывно печатать на stdout (после каждой завершенной задачи), если они работают правильно. Тем не менее, они, как правило, висят, и нам трудно найти ошибку. В идеале супервизор заметил бы, что они не печатали за X минут и перезапускали их; задачи являются идемпотентными, поэтому неграмотные перезагрузки в порядке. Есть ли функция супервизора или аддон, которые могут это сделать? Или другая супервизорная программа, которая имеет это из коробки?

Мы уже используем http://superlance.readthedocs.io/en/latest/memmon.html, чтобы убить, если использование памяти растет, что смягчает некоторые зависания, но зависает, что не причиной утечки памяти может все же стать причиной остановки рабочих.

Ответ 1

Одним из возможных решений было бы обернуть ваш python script в bash script, который будет контролировать его и выйти, если в течение некоторого времени не выводится на stdout.

Например:

kill-if-hung.sh

#!/usr/bin/env bash
set -e

TIMEOUT=60
LAST_CHANGED="$(date +%s)"

{
    set -e
    while true; do
        sleep 1
        kill -USR1 $$
    done
} &

trap check_output USR1

check_output() {
    CURRENT="$(date +%s)"
    if [[ $((CURRENT - LAST_CHANGED)) -ge $TIMEOUT ]]; then
        echo "Process STDOUT hasn't printed in $TIMEOUT seconds"
        echo "Considering process hung and exiting"
        exit 1
    fi
}

STDOUT_PIPE=$(mktemp -u)
mkfifo $STDOUT_PIPE

trap cleanup EXIT
cleanup() {
    kill -- -$$ # Send TERM to child processes
    [[ -p $STDOUT_PIPE ]] && rm -f $STDOUT_PIPE
}

[email protected] >$STDOUT_PIPE || exit 2 &

while true; do
    if read tmp; then
        echo "$tmp"
        LAST_CHANGED="$(date +%s)"
    fi
done <$STDOUT_PIPE

Тогда вы запустили бы python script в супервизор, например: kill-if-hung.sh python -u some-script.py (-u, чтобы отключить буферизацию вывода или установить PYTHONUNBUFFERED).

Я уверен, вы могли бы представить себе python script, который сделал бы что-то подобное.