Node.js
Process, entorno y graceful shutdown
Uso de process, variables de entorno, señales, códigos de salida y cierre ordenado de servidores, conexiones y tareas activas en Node.js.
- Última actualización
- Actualizada
- Nivel
- Fundamentos
Node.js
Uso de process, variables de entorno, señales, códigos de salida y cierre ordenado de servidores, conexiones y tareas activas en Node.js.
const [, , command, ...args] = process.argv;
console.log({ command, args });process.argv[0] suele ser el ejecutable de Node y [1] el archivo principal. No confíes en posiciones sin validar cuando construyes una CLI.
const port = Number.parseInt(process.env.PORT ?? "3000", 10);
if (!Number.isInteger(port)) {
throw new Error("PORT must be an integer");
}process.env contiene strings o valores ausentes. Valida al iniciar y convierte a tipos explícitos.
Configuración no es igual a secreto. Un secreto puede llegar por entorno, pero requiere controles de almacenamiento, rotación y acceso.
console.log(process.cwd());cwd depende del lugar desde donde se lanzó el proceso. No lo confundas con el directorio del módulo. Usa rutas relativas al módulo para assets empaquetados y cwd para entradas deliberadamente relativas al proyecto o usuario.
process.exitCode = 1;Asignar exitCode permite que el event loop termine después de vaciar trabajo pendiente. process.exit(1) finaliza de inmediato y puede cortar logs, respuestas o escrituras.
SIGINT: interrupción interactiva, común con Ctrl+C.SIGTERM: solicitud normal de terminación en entornos de despliegue.Windows y Unix no exponen todas las señales exactamente igual.
let closing = false;
async function shutdown(signal) {
if (closing) return;
closing = true;
console.log(`Received ${signal}`);
server.close();
const deadline = setTimeout(() => {
process.exitCode = 1;
}, 10_000);
deadline.unref();
await closeDatabase();
process.exitCode = 0;
}
process.once("SIGINT", () => void shutdown("SIGINT"));
process.once("SIGTERM", () => void shutdown("SIGTERM"));El cierre seguro normalmente sigue este flujo:
dejar de aceptar trabajo
↓
esperar trabajo en curso
↓
cerrar conexiones y recursos
↓
terminar con código correctoToda espera debe tener un límite.
Un error no controlado puede dejar memoria y recursos en un estado desconocido. Registrar contexto y comenzar un cierre controlado es distinto a “recuperarse y seguir normalmente”.
No realices trabajo complejo indefinido dentro de estos handlers. Asegura que un supervisor pueda reiniciar el proceso.
Sockets, servidores, timers referenciados y otros handles mantienen vivo el proceso. Si una CLI “no termina”, busca recursos abiertos antes de forzar process.exit().
beforeExit: aparece cuando el loop queda sin trabajo; no se dispara en todas las terminaciones.exit: solo permite trabajo síncrono muy limitado.warning: expone advertencias del runtime.No bases cleanup asíncrono principal en exit.
process.env por toda la aplicación sin validación central.process.exit() para ocultar handles abiertos.cwd con import.meta.url.exitCode permite terminar naturalmente.¿Por qué una aplicación puede no terminar después de completar su función principal?
Porque todavía existen handles referenciados, como un servidor, socket, watcher o timer, que mantienen activo el event loop.
Paths, URLs y filesystem muestra cómo el proceso accede de forma segura a recursos persistentes.