- 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
310 lines
8.1 KiB
Markdown
310 lines
8.1 KiB
Markdown
# 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/node` para Node.js
|
|
- `/usr/bin/npm` para 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)
|
|
```ini
|
|
[Service]
|
|
ExecStart=/usr/bin/npm start # ❌ No existe en el sistema
|
|
```
|
|
|
|
### Servicio Correcto (Esperado)
|
|
```ini
|
|
[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:
|
|
```rust
|
|
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)
|
|
|
|
```rust
|
|
/// 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`:
|
|
```ini
|
|
WorkingDirectory=/ruta/al/proyecto # Raíz del proyecto (donde está package.json)
|
|
ExecStart=/ruta/absoluta/npm start
|
|
```
|
|
|
|
Cuando `use_npm_start = false`:
|
|
```ini
|
|
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.json` existe si `use_npm_start = true`
|
|
- ✅ Loggear la ruta detectada para debugging
|
|
- ✅ Proporcionar mensajes de error claros
|
|
|
|
---
|
|
|
|
## 📊 Comparación: Antes vs Después
|
|
|
|
### Antes (Incorrecto)
|
|
```rust
|
|
impl AppType {
|
|
pub fn get_executable(&self) -> &str {
|
|
match self {
|
|
AppType::NodeJs => "/usr/bin/node", // ❌ Hardcoded
|
|
AppType::Python => "/usr/bin/python3",
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Después (Correcto)
|
|
```rust
|
|
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_executable` y `use_npm_start` a `ServiceConfig`
|
|
- [ ] Implementar función `detect_user_executable()`
|
|
- [ ] Modificar `generate_service_content()` para usar detección automática
|
|
- [ ] Agregar validación de `package.json` cuando `use_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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```ini
|
|
[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
|
|
|
|
1. **Validar rutas retornadas por `which`:**
|
|
- No permitir rutas fuera de directorios seguros
|
|
- Verificar que el archivo es ejecutable
|
|
- Loggear cualquier detección sospechosa
|
|
|
|
2. **Ejecución de comandos como otro usuario:**
|
|
- Usar `sudo -u` requiere configuración en sudoers
|
|
- Alternativa: Leer el PATH del usuario desde archivos de configuración
|
|
|
|
3. **Fallbacks seguros:**
|
|
- Si no se detecta, fallar explícitamente
|
|
- No asumir rutas por defecto silenciosamente
|
|
|
|
### Casos Edge a Considerar
|
|
|
|
1. Usuario con múltiples versiones de Node.js
|
|
2. Ejecutables en rutas personalizadas
|
|
3. Usuarios sin shell (system users)
|
|
4. 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** 🔧
|