Введение
Теперь Paper & Pine нужно завершить двенадцатистраничную программу сообщества перед остановкой. Входной скрипт уже правильно доставляет SIGTERM, но секундный срок Compose обрывает обработчик до завершения настоящего PDF. Задайте конечный, многократно используемый срок с достаточным запасом, не начиная следующее задание.
Сначала выполните Deliver the Stop Signal либо освойте её входную оболочку, PID 1, различие TERM/KILL, наблюдения заданий и основные команды Compose. Эта независимая работа подготавливает собственную программу, более ранний PDF, тренировочную очередь и очередь поставки. Файлы предыдущей VM, программирование на Python и физический принтер не требуются.
Используйте Workstation и Print Desk. Пауза первой страницы и замедление оставшихся страниц на 0,5 секунды — явно описанное учебное поведение. Срок остановки начинается с запроса остановки, а не с первого входа обработчика в паузу. Выделите около 45 минут с учётом чтения и обычных ошибок; это оценка автора.
Дайте текущей программе время завершиться
На этом шаге вы отличите успешную доставку сигнала от достаточного времени завершения, затем закончите исходное задание поставки в пределах конечного срока Compose.
Изучите работу и текущий лимит времени
Начните в Print Desk. В Delivery attempt просмотрите и скачайте готовый Morning welcome handout. Текущему Community open day programme нужны двенадцать настоящих страниц PDF; Volunteer notes — последующее задание, которое должно остаться ожидающим. Тренировка и поставка — отдельные учебные очереди с отдельными файлами.
Переключитесь в Workstation, начиная в /home/labex/project/print-grace:
cd /home/labex/project/print-grace
cat entry.sh
cat compose.yaml
Входной скрипт уже использует exec python3 -B /app/worker.py, поэтому предоставленный обработчик заменяет оболочку и получает запрос TERM Docker. Проблема — stop_grace_period: 1s. После окончания учебной паузы одиннадцать оставшихся интервалов по 0,5 секунды и окончательное формирование PDF требуют больше времени. Более долгое ожидание до запроса остановки не увеличивает срок: обработчик намеренно ждёт TERM перед завершением текущей работы.
Сохраните подготовленный образ, ID пользователя, монтирования, входную программу и остальные настройки Compose без изменений. Вы измените только конечный лимит остановки; неограниченное ожидание не является желаемым результатом.
Увидьте настоящую оборванную тренировочную попытку
Запустите предоставленный тренировочный проект:
docker compose -f compose.trial.yaml -p print-trial up -d --pull never --no-build
Переключитесь в Print Desk, обновите страницу и дождитесь учебной паузы после первой страницы в Practice attempt. Вернитесь в Workstation и запросите остановку с секундным сроком:
docker compose -f compose.trial.yaml -p print-trial stop worker
docker inspect print-trial --format '{{.State.ExitCode}}'
docker logs print-trial
Операция остановки Docker может вернуть 0, тогда как код завершения обработчика — 137. В отличие от ошибки неправильной оболочки в предыдущей работе этот журнал содержит stop-received и может содержать некоторые события оставшихся страниц, но не полный двенадцатистраничный PDF и штатное завершение. Доставка сигнала сработала; срок истёк во время настоящей оставшейся работы.
Переключитесь в Print Desk и обновите страницу. У тренировки нет окончательного скачивания текущей программы. Более ранние PDF и нетронутая очередь поставки остаются в целости. Не заполняйте отсутствующий результат вторым обработчиком.
Сохраните конечное переопределение Compose до запуска поставки
Переключитесь в Workstation. Небольшое переопределение позволяет сохранить предоставленный базовый файл и изменить только лимит остановки. Два аргумента -f объединяют файлы по порядку; более позднее services.worker.stop_grace_period переопределяет одно это свойство. Используйте ту же пару при изучении конфигурации, запуске и остановке.
Выберите конечный срок в целых секундах не больше 30 секунд. Пятнадцать секунд даёт этой явно описанной учебной программе запас на оставшиеся страницы и обычные накладные расходы планирования. Это практический запас, а не утверждение, что любой производственный PDF завершится за это время.
Используйте буквальный here-document из первой пошаговой работы для сохранения compose.stop.yaml:
cat > compose.stop.yaml <<'COMPOSE'
services:
worker:
stop_grace_period: 15s
COMPOSE
docker compose -f compose.yaml -f compose.stop.yaml -p print-delivery config
Найдите stop_grace_period: 15s в действующей конфигурации. Подготовленный образ, числовой пользователь, входной скрипт и входные данные только для чтения остаются прежними. Если отступы YAML неверны, исправьте небольшой блок и повторите разбор до запуска. Изменённый файл не переписывает значения уже созданного контейнера, поэтому сохраните этот лимит до запуска поставки.
Запустите поставку с той же парой файлов:
docker compose -f compose.yaml -f compose.stop.yaml -p print-delivery up -d --pull never --no-build
Переключитесь в Print Desk, обновите страницу и дождитесь учебной паузы в Delivery attempt. Затем переключитесь в Workstation и используйте ту же действующую конфигурацию для остановки:
docker compose -f compose.yaml -f compose.stop.yaml -p print-delivery stop worker
docker inspect print-delivery --format '{{.State.ExitCode}}'
docker logs print-delivery
Обработчик должен завершиться с кодом 0 после stop-received, событий всех двенадцати страниц, completed текущего задания и worker-stopped. Идентичности запуска и процесса остаются прежними от получения запроса до окончания программы. Сохраните этот остановленный контейнер; не удаляйте его ради упрощённой очистки.
Используйте полный PDF и сохраните другую работу
Переключитесь в Print Desk, обновите страницу и выберите Preview text текущей программы в Delivery attempt. Он декодирует настоящий сохранённый PDF. Изучите первую и последнюю страницы, а также все промежуточные заголовки разделов и номера страниц. Скачайте программу и откройте двенадцать страниц. Вернитесь к стенду и убедитесь, что утренний материал не изменился, а Volunteer notes по-прежнему ожидает без PDF.
Теперь у поставки штатно остановленный обработчик и настоящее двенадцатистраничное скачивание. Тренировка остаётся явно неудачной, а последующее задание ожидает:

Проверки объединяют настоящие факты TERM и завершения Docker, идентичность исходного обработчика, фактическое декодированное содержимое страниц и сохранность очереди. Временное воспроизведение тестирует сохранённый входной скрипт и действующий конечный срок на другой программе. Оно не посылает сигналы обработчику в вашем учебном окружении и не исправляет его.
Восстановите неудачную поставку
Если попытка поставки не удалась, сохраните остановленный контейнер достаточно долго для чтения журналов и кода завершения. Исправляйте только входной скрипт или настройку срока. Предоставленное действие восстановления отказывает для работающего или успешно завершённого контейнера; для неудачного остановленного учебного обработчика оно возвращает в очередь только текущее задание и сохраняет неудачные артефакты в delivery/attempt-history/. Более ранний PDF, исходные входные данные и последующее ожидающее задание сохраняются:
python3 /opt/labex/dk05/source/retry.py
После этого явного восстановления удалите только контейнеры неудачного проекта поставки через docker compose -p print-delivery down, затем повторите показанную последовательность запуска поставки, ожидания паузы и остановки. Ни один исходный PDF не создаётся заново; это восстановление никогда не запускается вкладкой или оценочной проверкой. Не сбрасывайте VM и не меняйте JSON очереди для сокрытия неудачной попытки.
Резюме
Вы отличили получение запроса остановки от наличия достаточного времени на завершение задания. Сохранённый конечный срок Compose позволил исходному обработчику закончить все двенадцать страниц PDF, штатно завершиться и сохранить как более ранний результат, так и последующее ожидающее задание.



