
Descubre cómo diseñar una interfaz TUI en Go con marcos Unicode (┌─┐ / ╔═╗), auto-descubrimiento de clusters Oracle RAC y flujos de mantenimiento guiados por flechas sin depender de Oracle Instant Client.
Son las 3:15 AM de una guardia de producción. Te conectas por SSH a un nodo de Oracle RAC en Oracle Linux porque ha saltado una alerta crítica. En cuestión de segundos tienes que:
CRS, CSSD, EVMD, ASM) están ONLINE en todos los nodos (crsctl check cluster -all y crsctl status resource -t).grid al usuario oracle para abrir sqlplus / as sysdba.gv$session (enq: TX - row lock contention) o qué tablespace acaba de lanzar un ORA-01654 porque llegó al 93% sin AUTOEXTEND.srvctl relocate service), parar la instancia local y detener la pila CRS sin provocar ni un segundo de caída en las aplicaciones.Después de repetir este ritual cientos de veces, decidí construir ora-tui: una herramienta interactiva de terminal (TUI) escrita en Go, empaquetada como un único binario estático (CGO_ENABLED=0) e instalable vía dnf install ora-tui.
En este artículo te cuento cómo funciona por dentro, cómo resolví los retos de arquitectura en servidores Oracle y cómo puedes probar su modo simulador (--mock) en tu propio portátil.
┌─┐ y ╔═╗) y Navegación con FlechasUno de los objetivos principales era que la herramienta se sintiera rápida y clara sobre cualquier sesión SSH, utilizando una jerarquía visual de marcos Unicode:
┌ ─ ┐ │ └ ┘) para los paneles secundarios y tablas de datos.╔ ═ ╗ ║ ╚ ╝) para la cabecera principal, el panel que tiene el foco activo, las ventanas emergentes de mantenimiento y los diálogos de confirmación.[█████████░] 93.0%) coloreadas según criticidad (verde $<80%$, amarillo $80\text{–}90%$, rojo $>90%$).Así se ve ora-tui en una sesión de terminal:
╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ ══ ORA-TUI :: ORACLE CLUSTER & DATABASE MANAGER ══ ║
╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
║ Modo: [ORACLE RAC] [MOCK DESIGN] │ Host: ora-rac01.corp.local │ Cluster: crs-prod-cluster │ Ver: 19.24.0.0.0 ║
║ ORACLE_HOME: /u01/app/oracle/product/19.0.0/dbhome_1 │ GRID_HOME: /u01/app/19.0.0/grid ║
║ Estado: 2 Inst OPEN │ 4 PDBs │ 3 Sesiones (1 Lock TX) │ 1 Tablespace >90% │ 3 Inválidos │ 1 Alerta Crítica ORA-01654 ║
╠═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════╣
║ MENU [Flechas ↑↓ + Enter] ║ PANTALLA ACTIVA: VISTA INTEGRAL + VENTANA EMERGENTE (Borde Simple ┌─┐ y Doble ╔═╗) ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════╣
║ ▸ 1. Cluster & DB Estado ║ ┌─ NODOS DEL CLUSTER & INSTANCIAS (ORACLE RAC / SINGLE) ─────────────────────────────┐ ║
║ 2. Usuarios Conectados ║ │ NODO ESTADO CRS CSSD ASM INST MODO FRA_USO │ ║
║ 3. Tablespaces & Files ║ │ ora-rac01 ONLINE ONLINE ONLINE ONLINE(+ASM1) PRODCDB1 READ WRITE [████░░░░]│ ║
║ 4. Tablas & Objetos ║ │ ora-rac02 ONLINE ONLINE ONLINE ONLINE(+ASM2) PRODCDB2 READ WRITE [████░░░░]│ ║
║ 5. ASM & Red Listeners ║ └────────────────────────────────────────────────────────────────────────────────────┘ ║
║ 6. RMAN, Flashback & DG ║ ┌─ USUARIOS CONECTADOS (gv$session) ───────────┬─ TABLESPACES & BACKUPS RMAN ────────┐ ║
║ 7. Alert Log & Errores ║ │ SID,SER# USUARIO ESTADO EVENTO / LOCK │ RECURSO ESTADO / USO % │ ║
║ 8. Centro Mantenimiento ║ │ 142,48219 ERP_APP ACTIVE db file seq rd │ ERP_DATA_TBS [█████████░] 93.0% !! │ ║
║ b. Cambiar Marcos ┌─┐/╔═╗ ║ │ 289,11042 CRM_BATCH ACTIVE enq: TX lock │ SYSAUX [████████░░] 84.4% │ ║
║ t. Cambiar Topologia ║ │ 512,9931 CRM_ADMIN INACT BLOCKER (289) │ RMAN INCR L0 COMPLETED (498.4 GB) │ ║
║ q. Salir (Quit) ║ │ 604,33105 BI_REPORT ACTIVE ON CPU (512MB) │ GRP_RELEASE GUARANTEED (18.4 GB) │ ║
║ ║ └──────────────────────────────────────────────┴─────────────────────────────────────┘ ║
║ ║ ║
║ ║ ╔══════════════════════════════════════════════════════════════════════════╗ ║
║ ║ ║ ══ VENTANA DE MANTENIMIENTO [Seleccione con Flechas ↑↓ + Enter] ══ ║ ║
║ ║ ╠══════════════════════════════════════════════════════════════════════════╣ ║
║ ║ ║ ▸ [1] Drenar / Aislar Nodo Cluster (Relocate Services + Stop CRS) ║ ║
║ ║ ║ [2] Parar / Arrancar Instancia o Base de Datos (srvctl / sqlplus) ║ ║
║ ║ ║ [3] Ampliar Tablespace Crítico (+Datafile 32G a ERP_DATA_TBS 93%) ║ ║
║ ║ ║ [4] Matar Sesión Bloqueante (KILL SESSION '512,9931,@2' IMMEDIATE) ║ ║
║ ║ ║ [5] Actualizar Estadísticas (DBMS_STATS) & Shrink Tablas Online ║ ║
║ ║ ║ [6] Recompilar Objetos Inválidos (UTL_RECOMP / COMPILE_SCHEMA) ║ ║
║ ║ ║ [7] Backup RMAN Archivelog + Crear Punto Restauración Garantizado ║ ║
║ ║ ║ [8] Analizar Errores ORA- en Alert Log & Purgar Trazas ADRCI ║ ║
║ ║ ║ [Esc] Cancelar / Cerrar Ventana ║ ║
║ ║ ╚══════════════════════════════════════════════════════════════════════════╝ ║
╠═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════╣
║ ┌─ CONSOLA DE EJECUCION & AUDITORIA EN VIVO ───────────────────────────────────────────────────────────────────────┐ ║
║ │ [08:05:01] Auto-Discovery: Modo=ORACLE RAC │ Cluster=crs-prod-cluster │ Release=19.24.0.0.0 │ ║
║ │ [08:05:02] ALERTA ORA-01654: Tablespace ERP_DATA_TBS al 93.0% │ Bloqueo TX detectado en SID 512 -> SID 289 │ ║
║ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ║
╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
CGO_ENABLED=0 y cero librerías de cliente C?La mayoría de los drivers de Oracle requieren CGO y enlazar dinámicamente contra libclntsh.so (Oracle Instant Client). En entornos empresariales con RHEL / Oracle Linux 7, 8 y 9 y distintas versiones de glibc, distribuir binarios con dependencias dinámicas es una fuente constante de problemas.
En ora-tui, el binario se compila 100% estático (CGO_ENABLED=0 GOOS=linux GOARCH=amd64) y se comunica directamente con las herramientas nativas que ya residen en $ORACLE_HOME/bin y $GRID_HOME/bin (sqlplus -s / as sysdba, srvctl, crsctl, olsnodes, lsnrctl, rman, adrci).
Nada más ejecutarse, ora-tui descubre qué tipo de instalación Oracle tiene delante sin pedir un solo archivo .yaml o .env:
/etc/oracle/ocr.loc y /etc/oracle/olr.loc:
local_only=false $\rightarrow$ ORACLE RAClocal_only=true $\rightarrow$ ORACLE RESTART (Standalone Grid)/proc:
Además de leer /etc/oratab e inventory.xml, escanea /proc/[0-9]*/cmdline para localizar procesos ora_pmon_<SID>, db_pmon_<SID> (Oracle 21c/23ai) y asm_pmon_+ASM*. Así detecta bases de datos levantadas aunque nadie las haya registrado en /etc/oratab.func ExtractSIDFromPMON(cmdline string) (sid string, isASM bool) {
fields := strings.Fields(cmdline)
if len(fields) == 0 {
return "", false
}
proc := filepath.Base(fields[0])
switch {
case strings.HasPrefix(proc, "ora_pmon_"):
return strings.TrimPrefix(proc, "ora_pmon_"), false
case strings.HasPrefix(proc, "db_pmon_"):
return strings.TrimPrefix(proc, "db_pmon_"), false
case strings.HasPrefix(proc, "asm_pmon_"):
return strings.TrimPrefix(proc, "asm_pmon_"), true
}
return "", false
}
root $\rightarrow$ oracle / grid)En un cluster RAC con separación de roles, grid es dueño de $GRID_HOME y oracle es dueño de $ORACLE_HOME. Ejecutar sqlplus o srvctl como root falla o ensucia permisos.
ora-tui lee el uid y gid propietarios de cada directorio con os.Stat y lanza cada subproceso con las credenciales exactas de ese usuario mediante syscall.Credential, reservando root únicamente para crsctl start/stop crs:
if !asRoot && targetOwner != nil && targetOwner.UID != 0 && currentUID == 0 {
cmd.SysProcAttr = &syscall.SysProcAttr{
Credential: &syscall.Credential{
Uid: targetOwner.UID,
Gid: targetOwner.GID,
},
}
}
┌─┐) y Dobles (╔═╗) en tviewLa librería rivo/tview permite definir globalmente los runas de dibujo de cajas, distinguiendo entre ventanas normales y ventanas con foco activo. Configurando tview.Borders, conseguimos que cualquier tabla o menú emergente resalte automáticamente con borde doble cuando el usuario lo selecciona con las flechas:
// Borde simple (┌ ─ ┐ │ └ ┘) para contenedores y tablas estándar
tview.Borders.Horizontal = '─'
tview.Borders.Vertical = '│'
tview.Borders.TopLeft = '┌'
tview.Borders.TopRight = '┐'
tview.Borders.BottomLeft = '└'
tview.Borders.BottomRight = '┘'
// Borde doble (╔ ═ ╗ ║ ╚ ╝) para la ventana con foco y modales emergentes
tview.Borders.HorizontalFocus = '═'
tview.Borders.VerticalFocus = '║'
tview.Borders.TopLeftFocus = '╔'
tview.Borders.TopRightFocus = '╗'
tview.Borders.BottomLeftFocus = '╚'
tview.Borders.BottomRightFocus = '╝'
Además, pulsando la tecla b en cualquier momento, puedes alternar en caliente entre el modo mixto (┌─┐ + ╔═╗), todo borde doble (╔═╗), todo borde simple (┌─┐) o ASCII clásico de 7 bits (+ - = |) si entras desde una consola serie antigua.
En lugar de memorizar comandos, te mueves con las flechas del teclado (↑/↓) por las 8 vistas y pulsas Enter sobre cualquier fila para abrir su menú contextual de mantenimiento:
CRS, CSSD, EVMD, ASM), VIPs, instancias, PDBs y Drenado Seguro de Nodo (Graceful Node Drain) en 4 pasos:
ONLINE.srvctl relocate service).srvctl stop instance -stopoption IMMEDIATE).crsctl stop crs).gv$session): Detección instantánea de bloqueos TX/TM, SQL_ID, evento de espera y texto SQL actual, con opción para ejecutar KILL SESSION IMMEDIATE o DISCONNECT SESSION POST_TRANSACTION.+DATA), activar AUTOEXTEND ON o hacer COALESCE.STALE o alta fragmentación para lanzar DBMS_STATS.GATHER_TABLE_STATS, SHRINK SPACE CASCADE, REBUILD ONLINE de índices o recompilar objetos inválidos con UTL_RECOMP.v$asm_diskgroup) y control de listeners locales y SCAN (lsnrctl start/stop/reload).ORA-: Lectura directa sobre v$diag_alert_ext con salto automático al módulo que resuelve el error y purgado de trazas con adrci.--mock)No necesitas tener un cluster Oracle RAC instalado en tu máquina para probar la interfaz. ora-tui incluye un modo simulador (--mock) con datos realistas de un cluster RAC en producción (incluyendo sesiones bloqueadas, un tablespace al 93% y alertas ORA-01654):
git clone https://github.com/mario/ora-tui.git
cd ora-tui
# Compilar y lanzar el simulador interactivo en modo Oracle RAC:
make mock
# O ver la captura estática directamente en tu terminal:
make preview
¿Qué otra tarea repetitiva de administración Oracle te gustaría automatizar desde un menú de consola? ¡Te leo en los comentarios!
discussTL;DR Welcome back to Dev Opportunity Radar! This is a weekly series where I share opportunities,...
devchallengeWe are so excited to announce the winners of the Hacktoberfest Open-Source AI Challenge: Touch...
googlecloudHow I designed, connected, scaled, governed, evaluated, and QLoRA fine-tuned an enterprise SecOps & FinOps agent on Google Cloud.
gemmaYes. Speculative decoding with Google's 59 MB QAT multi-token prediction (MTP) drafters speeds up Gemma 4 E4B 1.72x and E2B 1.40x on an 8 GB RTX 3050, and 1.49x and 1.18x on a 4 GB laptop GTX 1650 Ti, served by llama.cpp one request at a time, with unchanged GSM8K and BFCL scores.
nvidiaThe same Tesla T4 on the same Google Cloud VM decoded Gemma 4 E2B at 115 tokens/s at 45 °C and 107 at 77 °C. The card sits at its 70 W limit, a hotter chip draws more power at the same clock, so the clock drops. No thermal throttle fires, and no spec sheet mentions it.
oracleHow I pair-programmed with Google Antigravity powered by Gemini 4 Argon to build a zero-dependency Go TUI and OpenTelemetry/Prometheus observability stack for Oracle Databases and Linux SAN storage.
Workflows from the Neura Market marketplace related to this DeepSeek resource