Sistemas Operativos y Variables de Entorno (.env)
🚀 Clases en Vivo — Inicio: Domingo 6 de Septiembre ($200 MXN / clase). Aprende a programar desde cero con acompañamiento directo y construye el proyecto ShortURL.
En la Lección 10: Control de Versiones con Git y GitHub (L10) publicamos el código fuente de nuestro proyecto ShortURL en la nube con un repositorio profesional y documentado.
Ahora nos encontramos a un solo paso de la meta final: poner nuestra aplicación en producción en un servidor cloud público para que cualquier persona en el mundo pueda usarla.
Sin embargo, antes de enviar nuestro código a la nube, debemos resolver una pregunta crucial: ¿Cómo interactúa nuestro programa con el Sistema Operativo que lo hospeda? En tu computadora local tu servidor siempre escucha en el puerto 3000 y busca la base de datos en tu carpeta de usuario; pero en la nube, los servidores asignan puertos dinámicos y exigen proteger las contraseñas sin escribirlas dentro del código fuente.
En esta sesión intensiva de 4 horas, comprenderemos cómo el Sistema Operativo administra la memoria y los procesos de Node.js, dominaremos las Variables de Entorno (.env) y aprenderemos a apagar servidores limpiamente mediante Señales del Sistema (Graceful Shutdown).
🗺️ Estructura de la Sesión
Cada una de nuestras sesiones semanales sigue una metodología pedagógica dividida en 5 fases:
Estructura de la Sesión├── ☕ Fase 1: Revisión del Tema Anterior y Conclusiones├── 🎯 Fase 2: Introducción al Tema y Fundamentos├── 💻 Fase 3: Práctica Asistida en Vivo├── 🗣️ Fase 4: Exposición, Debate y Debugging└── 🏠 Fase 5: Reto Semanal y Práctica en Casa☕ Fase 1: Revisión del Tema Anterior y Conclusiones
Iniciamos la sesión analizando el repositorio publicado en GitHub y conectando con los entornos de producción.
1. Puesta en Común del Reto de la Lección 10
En la lección previa creamos commits atómicos, configuramos el .gitignore y publicamos el repositorio en GitHub:
- Discusión en grupo: ¿Pudiste ver tu
README.mdformateado en GitHub? - ¿Por qué nos aseguramos de que la carpeta
node_modules/no subiera a GitHub? - Si en el futuro agregamos una contraseña secreta o una llave de API a nuestro servidor… ¿deberíamos subirla a un repositorio público de GitHub?
2. El Puente Conceptual: El Código es el Mismo, el Entorno Cambia
Uno de los principios más importantes de la ingeniería de software moderna es:
“El código de tu aplicación debe ser idéntico en desarrollo y en producción; lo único que debe cambiar es su configuración.”
Tu código no debe tener escrito de forma fija (hardcoded) valores como const PUERTO = 3000;. En su lugar, debe preguntarle al Sistema Operativo: “¿En qué puerto quieres que me ejecute hoy?”. A este mecanismo de comunicación lo llamamos Variables de Entorno.
🎯 Fase 2: Introducción al Tema y Fundamentos Teóricos
Analicemos qué es un Proceso, cómo se gestiona la memoria y cómo opera process.env.
1. ¿Qué es un Proceso en el Sistema Operativo?
Cuando ejecutas node server.js en tu terminal, el Sistema Operativo (macOS, Linux o Windows) realiza tres tareas:
- Asigna un Identificador Único (PID - Process ID): Un número como
PID: 4892que identifica a tu servidor. - Reserva un bloque de Memoria RAM: Para guardar tus variables y código en ejecución.
- Le otorga acceso a los recursos: Como puertos de red y lectura del disco duro.
┌────────────────────────────────────────────────────────────┐│ 🖥️ SISTEMA OPERATIVO (Kernel) ││ ││ ┌────────────────────────────────────────────────────┐ ││ │ ⚙️ PROCESO: Node.js (PID: 5821) │ ││ │ • Memoria asignada: 45 MB │ ││ │ • Puerto de red: 3000 │ ││ │ • Variables de Entorno: { PORT: "3000", ... } │ ││ └────────────────────────────────────────────────────┘ │└────────────────────────────────────────────────────────────┘2. Variables de Entorno y el Objeto process.env
En Node.js, todas las variables de configuración del sistema operativo se leen a través del objeto global process.env:
// Si el sistema operativo define un puerto, úsalo; de lo contrario usa 3000 por defectoconst PUERTO = process.env.PORT || 3000;const AMBIENTE = process.env.NODE_ENV || "development";El Estándar del archivo .env:
Para no tener que escribir variables largas en la terminal cada vez que iniciamos el servidor, creamos un archivo local llamado .env y usamos la librería estándar dotenv:
PORT=4000NODE_ENV=developmentNOMBRE_APP=ShortURL Desde03. Señales del Sistema Operativo (Graceful Shutdown)
Cuando estás en la terminal y presionas Ctrl + C para apagar tu servidor, el Sistema Operativo le envía a Node.js un mensaje formal llamado SIGINT (Signal Interrupt).
Un servidor profesional no debe morir de golpe; debe:
- Dejar de aceptar peticiones nuevas.
- Guardar y cerrar limpiamente las conexiones a la base de datos SQLite.
- Despedirse y apagarse con orden. A esto se le conoce como Apagado Limpio (Graceful Shutdown).
🔍 Experimento en Vivo: Descubriendo tu Sistema Operativo con Node.js
Vamos a inspeccionar las entrañas de nuestra computadora con JavaScript:
- Abre tu terminal y abre el modo interactivo de Node:
Terminal window node - Ejecuta estas instrucciones una por una:
const os = require('os');console.log("Plataforma:", os.platform());console.log("Memoria Libre (MB):", Math.round(os.freemem() / 1024 / 1024));console.log("Núcleos de CPU:", os.cpus().length);console.log("PID de este proceso:", process.pid);
- Sal del modo interactivo presionando
Ctrl + Cdos veces.
💻 Fase 3: Práctica Asistida en Vivo
Adaptaremos ShortURL para configurarse con variables de entorno dinámicas y apagarse limpiamente.
🧩 Reto 1: Instalación y Configuración de dotenv
Objetivo: Instalar el paquete dotenv y crear nuestro archivo de configuración local.
Ejecuta en la terminal dentro de tu proyecto ShortURL:
# 1. Instalamos dotenvnpm install dotenv
# 2. Creamos nuestro archivo .env localecho "PORT=4000" > .envecho "NODE_ENV=development" >> .envecho "DB_PATH=./data/shorturl.db" >> .env🧩 Reto 2: Adaptando server.js para Leer process.env
Objetivo: Cargar dotenv en la primera línea de server.js y hacer que el puerto sea 100% dinámico.
Abre server.js y actualiza la cabecera:
// 1. Cargamos las variables de entorno del archivo .env inmediatamenterequire("dotenv").config();
const express = require("express");const db = require("./database");const app = express();
// 2. Leemos el puerto dinámicamente desde el entornoconst PUERTO = process.env.PORT || 3000;const AMBIENTE = process.env.NODE_ENV || "development";
app.use(express.json());app.use(express.static("public"));
// ... (Aquí van los endpoints POST /api/acortar y GET /:codigo que ya creamos)
// 3. Encendemos el servidor informando el entorno actualapp.listen(PUERTO, () => { console.log(`=========================================`); console.log(`🚀 Servidor ShortURL iniciado en modo: [${AMBIENTE.toUpperCase()}]`); console.log(`🌐 Escuchando en: http://localhost:${PUERTO}`); console.log(`=========================================`);});🧩 Reto 3: Creación de la Plantilla Segura .env.example
Objetivo: Crear una plantilla pública que indique qué variables necesita el proyecto sin revelar valores secretos.
Crea un archivo llamado .env.example en la raíz:
# Puerto en el que se ejecutará el servidor webPORT=3000
# Entorno de ejecución (development | production)NODE_ENV=development
# Ruta de almacenamiento del archivo de base de datosDB_PATH=./data/shorturl.dbVerifica en tu terminal:
# Verificamos que .env esté protegido por .gitignore y .env.example sí aparezcagit status🧩 Reto 4: Implementación de Apagado Limpio (Graceful Shutdown)
Objetivo: Escuchar la señal SIGINT (Ctrl + C) para cerrar SQLite y despedir el proceso con código de salida 0.
Agrega este bloque al final de server.js:
// Escuchamos la señal de interrupción enviada por el Sistema Operativo (Ctrl + C)process.on("SIGINT", () => { console.log("\n🛑 Recibida señal de apagado (SIGINT). Iniciando cierre seguro...");
try { // Cerramos la conexión a la base de datos para no corromper datos db.close(); console.log("📦 Base de datos SQLite desconectada con éxito."); } catch (error) { console.error("Error al cerrar base de datos:", error); }
console.log("👋 ¡Servidor ShortURL apagado limpiamente! Hasta pronto.\n"); process.exit(0); // Código 0 = Salida exitosa sin errores});🗣️ Fase 4: Exposición de Resultados, Debate y Debugging
Iniciamos el servidor con node server.js, lo probamos en el puerto 4000 definido en .env y presionamos Ctrl + C para ver el apagado limpio en la terminal.
🐞 Las 4 Trampas Clásicas de Sistemas Operativos y .env
1. Subir accidentalmente el archivo .env a GitHub
- El peligro: Si subes tu
.enva GitHub, cualquier persona podrá ver tus contraseñas y llaves de acceso. - La regla inquebrantable: El archivo
.envNUNCA se sube a Git. Se sube únicamente el.env.example.
2. Las variables de process.env SIEMPRE son Cadenas de Texto (Strings)
- La trampa: Si en
.envponesACTIVADO=false, en JavaScriptprocess.env.ACTIVADOvaldrá el string"false". En condicionales,if ("false")evalúa como verdadero (true). - La solución: Para booleanos compara con
process.env.ACTIVADO === "true". Para números usaNumber(process.env.PORT).
3. Olvidar llamar a require('dotenv').config()
- El síntoma:
process.env.PORTdevuelveundefinedaunque el archivo.envexista en la carpeta. - La solución: La primera línea ejecutable de tu
server.jsdebe serrequire('dotenv').config();.
4. Procesos colgados en segundo plano
- El síntoma: Cerraste la ventana de terminal pero al volver a iniciar dice
EADDRINUSE: port already in use. - La solución: El proceso de Node anterior no se apagó. Búscalo y mátalo en la terminal (
killall nodeen Mac/Linux o cerrando “Node.js” en el Administrador de Tareas de Windows).
🏠 Fase 5: Definición de Práctica en Casa / Reto Semanal
Configurarás los scripts oficiales de ejecución del proyecto en package.json.
🏆 Proyecto Semanal: “El Módulo de Configuración y Scripts de NPM”
Descripción del Reto:
Los proyectos profesionales no se inician escribiendo node server.js manualmente; utilizan scripts declarativos en package.json.
Especificaciones a Implementar:
-
Configurar Scripts en
package.json:- Abre tu
package.jsony define la sección"scripts":"scripts": {"start": "node server.js","dev": "node --watch server.js"}
(Nota:
node --watches una función moderna de Node.js que reinicia tu servidor automáticamente cada vez que guardas un cambio en el código). - Abre tu
-
Adaptar la Base de Datos con Variable de Entorno:
- En
database.js, haz que la ruta del archivo SQLite se lea desdeprocess.env.DB_PATH || path.join(__dirname, "data", "shorturl.db").
- En
-
Prueba de Funcionamiento:
- Inicia tu servidor ejecutando:
npm run dev. - Realiza un cambio en
server.js(ej. cambiar un mensaje de console.log) y guarda el archivo. - Observa cómo Node.js se reinicia solo al instante sin que tengas que tocar la terminal.
- Presiona
Ctrl + Cy verifica el mensaje de apagado limpio.
- Inicia tu servidor ejecutando:
-
Sube tus cambios a GitHub:
git add .git commit -m "feat: implement environment variables and graceful shutdown"git push origin main
📚 Recursos y Videos Recomendados
Para profundizar en Sistemas Operativos, procesos y variables de entorno:
🚀 Conclusión y Próximos Pasos
¡Felicidades! Ahora tu aplicación es flexible, segura, desacoplada y lista para sobrevivir en cualquier entorno de ejecución.
Hemos llegado a la cumbre de nuestro viaje formativo: En la próxima y última lección, conectaremos nuestro repositorio de GitHub con una plataforma en la nube y publicaremos ShortURL en internet con un dominio público real: Lección 12: DevOps - Despliegue en la Nube y Graduación (L12).
🚀 Clases en Vivo — Inicio: Domingo 6 de Septiembre ($200 MXN / clase). Aprende a programar desde cero con acompañamiento directo y construye el proyecto ShortURL.