Entrega la señal de parada

DockerBeginner
Practicar Ahora

Introducción

Paper & Pine convierte programas de eventos en cola en PDF reales. Antes de pausar la producción, debe terminar el folleto actual de tres páginas, dejar pendiente el siguiente trabajo y conservar el PDF de la mañana ya completado. El trabajador Python proporcionado ya sabe terminar su trabajo actual tras una solicitud de parada, pero su shell de entrada impide actualmente que esa solicitud le llegue.

Debes conocer las rutas de terminal, los conceptos básicos de Docker y los registros de contenedores. El pequeño archivo Compose y el comportamiento del shell usado aquí se explican antes de utilizarlos. No necesitas programar en Python ni una impresora física: el producto es un PDF descargable y decodificable.

Usa Workstation y Print Desk. Las colas independientes de práctica y entrega permiten inspeccionar un fallo controlado sin perder el progreso de entrega. El modo de práctica se pausa tras renderizar la primera página hasta que llega una solicitud de parada y luego añade una pausa declarada de 0,5 segundos entre las páginas restantes. Estas pausas permiten ver la decisión, no miden la velocidad de producción. Calcula unos 45 minutos, incluidos la lectura y los errores habituales; es una estimación del autor.

Entrega la solicitud de parada al trabajador

En este paso, observarás una parada de práctica fallida, repararás el shell de entrada y completarás una entrega real en el mismo trabajador que recibe su solicitud de parada.

Empieza con un programa real completado

Empieza en Print Desk. Bajo Delivery attempt, abre Preview text para Morning welcome handout y selecciona Download PDF. La vista previa se decodifica de ese PDF guardado de dos páginas, no se reconstruye del texto fuente. Vuelve con Back to Print Desk. El folleto actual Community open day handout está pendiente; Volunteer notes debe permanecer pendiente tras esta entrega.

El mostrador separa práctica y entrega y comienza con solo los folletos anteriores disponibles:

Print Desk antes de producir el folleto actual

La columna Practice attempt es una copia separada de la cola de práctica, no una segunda máquina. Cada columna tiene su propia salida y estado de trabajador. Un PDF actual solo se puede descargar después de finalizar todo el documento. Renderizar internamente la página 1 aún no produce un archivo PDF completo.

Observa por qué falla una parada de práctica

Cambia a Workstation, que comienza en /home/labex/project/print-signal. cd vuelve allí y cat lee un archivo:

cd /home/labex/project/print-signal
cat compose.trial.yaml

Compose agrupa ajustes bajo services.worker. Su imagen preparada contiene el trabajador y las bibliotecas PDF. user ya coincide con los ID numéricos reales de tu cuenta, por lo que la salida sigue siendo editable; no sustituyas esos valores. /input, de solo lectura, contiene los trabajos originales, /work es el estado y salida modificables de este intento y /entry.sh es su script de entrada de solo lectura. :ro significa solo lectura. entrypoint: ["/bin/sh", "/entry.sh"] inicia directamente ese shell como proceso 1 del contenedor, llamado PID 1. Un contenedor comparte el kernel de la VM, pero tiene su propia vista de procesos.

stop_grace_period: 10s da a la aplicación una ventana finita de diez segundos para apagarse. Docker envía primero SIGTERM, la solicitud normal de terminación. Una vez agotada la gracia, puede enviar SIGKILL, que termina forzosamente los procesos y no se puede manejar para acabar el trabajo. Enviar una señal a PID 1 no la reenvía automáticamente a todos sus hijos.

La entrada de práctica existente inicia Python como hijo en segundo plano con & y luego wait lo espera. El shell sigue siendo PID 1. Lee ese script proporcionado:

cat trial-entry.sh

El shell no tiene un manejador de reenvío. PID 1 de un contenedor tiene un comportamiento predeterminado especial para las señales, por lo que este shell puede seguir vivo mientras Python nunca recibe la solicitud TERM.

Inicia solo el proyecto de práctica. -f selecciona su archivo, -p agrupa sus recursos, up -d lo inicia en segundo plano y las últimas opciones usan imágenes preparadas sin descargas ni construcciones:

docker compose -f compose.trial.yaml -p print-trial up -d --pull never --no-build

Cambia a Print Desk, recarga y espera hasta que Practice attempt muestre Training pause after page 1; waiting for stop request. El trabajador ha renderizado realmente la página 1 y espera deliberadamente. No hay una ventana estrecha de tiempo.

Cambia a Workstation. docker exec ejecuta un comando en un contenedor existente. Linux expone información de procesos en /proc; /proc/1/comm dentro de este contenedor nombra su comando PID 1. Esta observación de solo lectura debe mostrar sh:

docker exec print-trial cat /proc/1/comm

stop solicita detener este servicio usando la gracia configurada:

docker compose -f compose.trial.yaml -p print-trial stop worker

El propio comando de parada puede terminar con 0 aunque el trabajador haya sido terminado por la fuerza: significa que Docker gestionó la operación de parada, no que terminara el programa. docker inspect lee el contenedor conservado. La plantilla entre comillas simples selecciona el código de salida del trabajador:

docker inspect print-trial --format '{{.State.ExitCode}}'
docker logs print-trial

Espera el código de salida 137 y ningún evento stop-received ni completed del trabajador. En esta práctica controlada, la gracia expiró y Docker forzó la parada; 137 por sí solo no es un diagnóstico general de todos los fallos de contenedores. El registro tiene un evento JSON por línea: event nombra la observación, job identifica el programa y page registra el progreso real de renderizado.

Cambia a Print Desk y recarga. La práctica no tiene un PDF actual finalizado, mientras su folleto anterior y la cola de entrega sin tocar siguen disponibles.

Sustituye el shell por el trabajador

Cambia a Workstation. Edita solo el entry.sh de entrega y conserva intactos trial-entry.sh, la entrada del programa, los PDF existentes y los demás ajustes. exec del shell sustituye el proceso shell actual por el programa nombrado. Python se convierte así en PID 1 y su manejador TERM proporcionado recibe la solicitud de Docker.

Este here-document literal escribe el script corto completo. > sustituye entry.sh; el marcador SH entre comillas impide la expansión del shell hasta la línea de cierre. El archivo no necesita permiso de ejecución porque el /bin/sh configurado lo lee:

cat > entry.sh <<'SH'
#!/bin/sh
exec python3 -B /app/worker.py
SH
cat entry.sh

Inicia el proyecto de entrega independiente, cuya gracia de diez segundos ya basta para este folleto de tres páginas:

docker compose -p print-delivery up -d --pull never --no-build

Cambia a Print Desk, recarga y espera el mensaje de pausa de práctica de Delivery attempt. Vuelve a Workstation y lee PID 1 otra vez:

docker exec print-delivery cat /proc/1/comm

Espera python3, en lugar del shell en espera. Solicita una parada normal:

docker compose -p print-delivery stop worker
docker inspect print-delivery --format '{{.State.ExitCode}}'
docker logs print-delivery

Espera el código de salida 0. El mismo trabajador registra stop-received, los eventos page-completed restantes, completed para el programa actual y worker-stopped. Un proceso nuevo que complete después el PDF que falta no demostraría que este trabajador terminó su trabajo.

Inspecciona el archivo entregado y la cola conservada

Cambia a Print Desk, recarga y abre Preview text del folleto actual bajo Delivery attempt. Deben estar presentes las tres páginas decodificadas, sus títulos de sección, el ID de programa y los números de página. Descarga el PDF real y ábrelo. Vuelve al mostrador: Morning welcome handout debe conservar sus dos páginas originales y Volunteer notes debe seguir pendiente sin PDF generado. Conserva el contenedor print-delivery detenido normalmente como evidencia nativa de inspección.

Si escribes mal un nombre, lee el error y usa el nombre de contenedor indicado; por ejemplo, docker logs print-workr no encuentra esta entrega, mientras el docker logs print-delivery mostrado la lee. No crees un PDF sustituto a mano. Las comprobaciones leen los hechos reales de parada y decodifican cada página; después reproducen tu entrada guardada en un escenario aislado de programa sin cambiar el progreso real.

Recupera una entrega fallida

Si tu intento de entrega falla, conserva el contenedor detenido el tiempo necesario para leer sus registros y estado de salida. Corrige solo la entrada o la configuración de gracia. La acción de recuperación proporcionada rechaza un contenedor en ejecución o terminado correctamente; para un trabajador del curso detenido sin éxito, vuelve a poner en cola solo el trabajo actual y conserva los archivos fallidos en delivery/attempt-history/. Conserva el PDF anterior, las entradas originales y el trabajo posterior pendiente:

python3 /opt/labex/dk05/source/retry.py

Tras esa recuperación explícita, elimina solo los contenedores del proyecto de entrega fallido con docker compose -p print-delivery down y repite la secuencia mostrada de inicio de entrega, espera de pausa y parada. No se regenera ningún PDF fuente y ninguna pestaña ni comprobación de puntuación ejecuta esta recuperación. No restablezcas la VM ni cambies el JSON de la cola para ocultar un intento fallido.

Resumen

Viste cómo un shell PID 1 en espera puede ocultar una solicitud de parada a su hijo y usaste exec para que el trabajador proporcionado recibiera TERM directamente. El trabajador de entrega original terminó su PDF de tres páginas, salió normalmente, conservó el documento de la mañana y dejó pendiente el siguiente trabajo.