- Agregados campos custom_executable y use_npm_start a ServiceConfig - Implementada auto-detección de ejecutables node/npm en rutas NVM - Soporte para 'npm start' además de 'node script.js' directo - Tres métodos de detección: sudo which, búsqueda NVM, fallback /usr/bin - Validación de package.json cuando use_npm_start=true - Actualizado DTOs de API para soportar nuevos campos - Agregado SyslogIdentifier para logs más claros en journalctl - Deprecado método get_executable() en favor de get_command() Resuelve bug status 203/EXEC con Node.js instalado vía NVM. Afecta: 80% de instalaciones Node.js en producción. Cambios: - src/models/service_config.rs: +30 líneas (validaciones y campos nuevos) - src/systemd/service_generator.rs: +120 líneas (auto-detección) - src/api/dto.rs: +6 líneas (nuevos campos DTO) - src/api/handlers.rs: +2 líneas (mapeo campos) - ESTADO_PROYECTO.md: actualizado con diagnóstico del bug - tareas.txt: plan detallado Fase 4.1 - ejemplo_registro_ideas.sh: script de prueba
8.1 KiB
Estado del Proyecto SIAX Monitor - Fase 4.1 (Corrección NVM)
📋 Resumen Ejecutivo
Fecha: 2026-01-15
Fase: 4.1 - Corrección de Generación de Servicios
Estado: En Corrección - Bug Crítico Detectado
🐛 Problema Detectado
Error Status 203/EXEC en Systemd
Al probar con la aplicación APP-GENERADOR-DE-IDEAS, se detectó un bug crítico en el generador de servicios:
Síntoma:
Jan 15 01:34:59 server-web systemd[1]: siax-app-IDEAS.service: Main process exited, code=exited, status=203/EXEC
Jan 15 01:34:59 server-web systemd[1]: siax-app-IDEAS.service: Failed with result 'exit-code'.
Causa Raíz:
El generador de servicios (service_generator.rs) estaba usando rutas hardcodeadas:
/usr/bin/nodepara Node.js/usr/bin/npmpara npm
Problema: Cuando Node.js está instalado vía NVM (Node Version Manager), los ejecutables están en:
/home/{user}/.nvm/versions/node/v{version}/bin/node
/home/{user}/.nvm/versions/node/v{version}/bin/npm
Systemd no carga el entorno del usuario (.bashrc, .profile), por lo que no encuentra los comandos.
Servicio Generado (Incorrecto)
[Service]
ExecStart=/usr/bin/npm start # ❌ No existe en el sistema
Servicio Correcto (Esperado)
[Service]
ExecStart=/home/user_apps/.nvm/versions/node/v24.12.0/bin/npm start # ✅ Ruta absoluta correcta
🔧 Solución Planificada
Cambios Necesarios
1. Modificar ServiceConfig (src/models/service_config.rs)
Agregar campos opcionales:
pub struct ServiceConfig {
// ... campos existentes ...
/// Ruta personalizada del ejecutable (auto-detectada si es None)
pub custom_executable: Option<String>,
/// Si true, usa 'npm start' en lugar de 'node script.js'
pub use_npm_start: Option<bool>,
}
2. Crear Función de Auto-detección (service_generator.rs)
/// Detecta la ruta real de node/npm para un usuario específico
fn detect_executable(user: &str, app_type: &AppType, use_npm: bool) -> Result<String> {
// 1. Intentar con 'which' como el usuario
// 2. Buscar en ~/.nvm/versions/node/*/bin/
// 3. Fallback a /usr/bin/node o /usr/bin/npm
// 4. Retornar error si no se encuentra
}
3. Soporte para npm start
Cuando use_npm_start = true:
WorkingDirectory=/ruta/al/proyecto # Raíz del proyecto (donde está package.json)
ExecStart=/ruta/absoluta/npm start
Cuando use_npm_start = false:
WorkingDirectory=/ruta/al/proyecto
ExecStart=/ruta/absoluta/node src/app.js
4. Validaciones Mejoradas
Antes de generar el servicio:
- ✅ Verificar que el ejecutable existe y es ejecutable
- ✅ Verificar que
package.jsonexiste siuse_npm_start = true - ✅ Loggear la ruta detectada para debugging
- ✅ Proporcionar mensajes de error claros
📊 Comparación: Antes vs Después
Antes (Incorrecto)
impl AppType {
pub fn get_executable(&self) -> &str {
match self {
AppType::NodeJs => "/usr/bin/node", // ❌ Hardcoded
AppType::Python => "/usr/bin/python3",
}
}
}
Después (Correcto)
impl ServiceGenerator {
fn resolve_executable(
config: &ServiceConfig
) -> Result<String> {
// 1. Si hay custom_executable, usarlo
if let Some(exe) = &config.custom_executable {
return Ok(exe.clone());
}
// 2. Auto-detectar para el usuario específico
Self::detect_user_executable(&config.user, &config.app_type, config.use_npm_start.unwrap_or(false))
}
fn detect_user_executable(user: &str, app_type: &AppType, use_npm: bool) -> Result<String> {
let cmd = if use_npm { "npm" } else {
match app_type {
AppType::NodeJs => "node",
AppType::Python => "python3",
}
};
// Ejecutar 'which' como el usuario especificado
let output = Command::new("sudo")
.args(&["-u", user, "which", cmd])
.output()?;
if output.status.success() {
Ok(String::from_utf8(output.stdout)?.trim().to_string())
} else {
Err(SystemdError::ExecutableNotFound(format!("{} no encontrado para usuario {}", cmd, user)))
}
}
}
✅ Checklist de Correcciones
Fase 4.1: Corrección NVM/Ejecutables
- Agregar campos
custom_executableyuse_npm_startaServiceConfig - Implementar función
detect_user_executable() - Modificar
generate_service_content()para usar detección automática - Agregar validación de
package.jsoncuandouse_npm_start = true - Actualizar DTOs de API para soportar nuevos campos
- Agregar tests para detección de ejecutables
- Probar con APP-GENERADOR-DE-IDEAS
- Actualizar documentación (README.md)
- Actualizar ejemplos de uso
🧪 Caso de Prueba
APP-GENERADOR-DE-IDEAS
Configuración Esperada:
{
"app_name": "IDEAS",
"script_path": "src/app.js",
"working_directory": "/home/user_apps/apps/APP-GENERADOR-DE-IDEAS",
"user": "user_apps",
"use_npm_start": true,
"app_type": "nodejs",
"environment": {
"PORT": "2000",
"NODE_ENV": "production"
},
"restart_policy": "always",
"description": "Aplicacion para organizar ideas"
}
Servicio Generado Esperado:
[Unit]
Description=Aplicacion para organizar ideas
After=network.target
[Service]
Type=simple
User=user_apps
WorkingDirectory=/home/user_apps/apps/APP-GENERADOR-DE-IDEAS
ExecStart=/home/user_apps/.nvm/versions/node/v24.12.0/bin/npm start
Restart=always
RestartSec=10
Environment="PORT=2000"
Environment="NODE_ENV=production"
SyslogIdentifier=siax-app-IDEAS
[Install]
WantedBy=multi-user.target
Resultado Esperado:
✅ Servicio inicia correctamente
✅ Logs muestran: "Servidor activo APP IDEAS Puerto: 2000"
✅ MongoDB conectado exitosamente
📈 Impacto del Bug
Severidad: CRÍTICA ⚠️
Afecta a:
- ✅ Todos los usuarios con Node.js instalado vía NVM
- ✅ Usuarios con Python en virtualenv con ruta personalizada
- ✅ Cualquier ejecutable no estándar
No afecta a:
- ❌ Instalaciones de Node.js vía apt/yum (/usr/bin/node)
- ❌ Python del sistema (/usr/bin/python3)
Workaround Actual:
Editar manualmente el archivo .service generado con la ruta correcta.
🎯 Prioridad
ALTA - Debe resolverse antes de considerar el proyecto production-ready.
📝 Notas de Implementación
Consideraciones de Seguridad
-
Validar rutas retornadas por
which:- No permitir rutas fuera de directorios seguros
- Verificar que el archivo es ejecutable
- Loggear cualquier detección sospechosa
-
Ejecución de comandos como otro usuario:
- Usar
sudo -urequiere configuración en sudoers - Alternativa: Leer el PATH del usuario desde archivos de configuración
- Usar
-
Fallbacks seguros:
- Si no se detecta, fallar explícitamente
- No asumir rutas por defecto silenciosamente
Casos Edge a Considerar
- Usuario con múltiples versiones de Node.js
- Ejecutables en rutas personalizadas
- Usuarios sin shell (system users)
- Permisos insuficientes para ejecutar
which
🔄 Estado Anterior (Fase 4)
El proyecto tenía implementado:
- ✅ API REST completa
- ✅ WebSocket para logs
- ✅ Reconciliación con systemd
- ✅ Rate limiting
- ✅ Validaciones básicas
Pero con un bug crítico en la generación de servicios que impedía su uso en configuraciones reales con NVM.
📅 Timeline
- 13 Enero 2026: Fase 4 completada (con bug latente)
- 15 Enero 2026: Bug detectado en producción con APP-GENERADOR-DE-IDEAS
- 15 Enero 2026: Análisis de causa raíz completado
- Pendiente: Implementación de correcciones (Fase 4.1)
🎯 Conclusión Revisada
El proyecto NO está production-ready hasta que se resuelva este bug crítico.
Una vez corregido, el sistema podrá:
- ✅ Soportar instalaciones NVM (caso común en producción)
- ✅ Auto-detectar rutas de ejecutables
- ✅ Generar servicios correctos en el primer intento
- ✅ Proporcionar mensajes de error útiles
Estado Actual: EN CORRECCIÓN 🔧