Creación de ventanas interactivas en terminal con dialog
, whiptail
y ncurses
Las interfaces de usuario basadas en texto (TUI) son una alternativa poderosa a las GUI gráficas, especialmente en entornos de servidor o cuando se necesita ligereza. Este manual cubre las herramientas más populares para crear TUI en Linux.
sudo apt-get install dialog whiptail ncurses-utils libncurses-dev python3
sudo yum install dialog whiptail ncurses ncurses-devel python3
sudo pacman -S dialog whiptail ncurses python
dialog --title "Título" --msgbox "Este es un mensaje" 10 30
dialog --title "Confirmación" --yesno "¿Desea continuar?" 10 30
if [ $? -eq 0 ]; then
echo "Usuario dijo Sí"
else
echo "Usuario dijo No"
fi
dialog --title "Entrada" --inputbox "Introduce tu nombre:" 10 30 2>nombre.txt
nombre=$(cat nombre.txt)
dialog --title "Seguridad" --insecure --passwordbox "Contraseña:" 10 30 2>pass.txt
dialog --title "Menú Principal" --menu "Elige una opción:" 15 40 10 \
1 "Opción 1" \
2 "Opción 2" \
3 "Opción 3" 2>opcion.txt
dialog --title "Software" --checklist "Selecciona paquetes:" 15 40 5 \
1 "Python" off \
2 "Node.js" on \
3 "Go" off 2>paquetes.txt
dialog --title "S.O." --radiolist "Elige un sistema:" 15 40 5 \
1 "Linux" on \
2 "Windows" off \
3 "MacOS" off 2>os.txt
Whiptail es compatible con dialog pero con menos características y más ligero.
whiptail --title "Ejemplo" --msgbox "Este es un mensaje" 10 30
whiptail --title "Menú" --menu "Elige:" 15 40 5 1 "Uno" 2 "Dos" 3 "Tres"
NCurses es una biblioteca para desarrollo de interfaces en terminal con control completo sobre la pantalla.
#!/bin/bash # Configuración inicial clear tput civis # Oculta cursor # Dibuja ventana tput cup 5 10 echo -e "\e[44m\e[37m┌──────────────────────────────┐" tput cup 6 10 echo -e "│ \e[1mMENÚ PRINCIPAL\e[0m\e[44m\e[37m │" tput cup 7 10 echo -e "├──────────────────────────────┤" tput cup 8 10 echo -e "│ \e[33m1)\e[0m Opción 1 │" tput cup 9 10 echo -e "│ \e[33m2)\e[0m Opción 2 │" tput cup 10 10 echo -e "│ \e[33m3)\e[0m Salir │" tput cup 11 10 echo -e "└──────────────────────────────┘\e[0m" # Espera entrada tput cup 13 10 read -p "Selecciona una opción [1-3]: " opcion # Restaura terminal tput cnorm # Muestra cursor clear
import curses def main(stdscr): # Configuración inicial curses.curs_set(0) # Oculta cursor stdscr.clear() # Configura colores curses.start_color() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) curses.init_pair(2, curses.COLOR_YELLOW, curses.COLOR_BLACK) # Dibuja ventana stdscr.bkgd(curses.color_pair(1)) stdscr.border() # Título title = "MENÚ PRINCIPAL" stdscr.addstr(2, (curses.COLS - len(title)) // 2, title, curses.A_BOLD) # Opciones options = ["1) Opción 1", "2) Opción 2", "3) Salir"] for i, option in enumerate(options): stdscr.addstr(5 + i, 10, option, curses.color_pair(2)) # Resaltar selección current_row = 0 while True: stdscr.addstr(5 + current_row, 10, options[current_row], curses.color_pair(2) | curses.A_REVERSE) key = stdscr.getch() stdscr.addstr(5 + current_row, 10, options[current_row], curses.color_pair(2)) if key == curses.KEY_UP and current_row > 0: current_row -= 1 elif key == curses.KEY_DOWN and current_row < len(options) - 1: current_row += 1 elif key == curses.KEY_ENTER or key in [10, 13]: break return current_row if __name__ == "__main__": print(f"Seleccionaste: {curses.wrapper(main) + 1}")
Para crear efectos visuales avanzados:
echo -e "\e[37m╔════════════════════════╗" echo -e "║ \e[36mTítulo de la ventana\e[37m ║" echo -e "╠════════════════════════╣" echo -e "║ \e[0mContenido aquí... \e[37m║" echo -e "╚════════════════════════╝\e[0m"
echo -e "\e[37m┌────────────────────┐\e[90m▒▒▒" echo -e "\e[37m│ \e[36mContenido \e[37m│\e[90m▒▒▒" echo -e "\e[37m└────────────────────┘\e[90m▒▒▒" echo -e " ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒\e[0m"
dialog --title "Con Ratón" --msgbox "Prueba a hacer clic" 10 30 --mouse
import curses def main(stdscr): curses.mousemask(curses.ALL_MOUSE_EVENTS) while True: key = stdscr.getch() if key == curses.KEY_MOUSE: _, x, y, _, _ = curses.getmouse() stdscr.addstr(y, x, "X")
#!/bin/bash # Instalador ejemplo con dialog # Verificar dependencias if ! command -v dialog &> /dev/null; then echo "Instalando dialog..." sudo apt-get install -y dialog fi # Menú principal while true; do choice=$(dialog --title "Instalador de Software" \ --menu "Elige una opción:" 15 50 10 \ 1 "Instalar paquetes básicos" \ 2 "Configurar sistema" \ 3 "Realizar copia de seguridad" \ 4 "Salir" 3>&1 1>&2 2>&3) case $choice in 1) packages=$(dialog --title "Instalación" \ --checklist "Selecciona paquetes:" 20 50 10 \ python "Python 3" on \ nodejs "Node.js" off \ golang "Go Language" off 3>&1 1>&2 2>&3) if [ -n "$packages" ]; then sudo apt-get install -y $packages dialog --msgbox "Paquetes instalados correctamente" 10 30 fi ;; 2) hostname=$(dialog --title "Configuración" \ --inputbox "Nuevo nombre de host:" 10 30 3>&1 1>&2 2>&3) if [ -n "$hostname" ]; then sudo hostnamectl set-hostname "$hostname" dialog --msgbox "Hostname cambiado a $hostname" 10 30 fi ;; 3) backup_dir=$(dialog --title "Copia de seguridad" \ --dselect "$HOME" 15 50 3>&1 1>&2 2>&3) if [ -n "$backup_dir" ]; then tar -czf "$backup_dir/backup_$(date +%F).tar.gz" "$HOME" dialog --msgbox "Copia de seguridad completada en $backup_dir" 10 50 fi ;; 4) break ;; esac done clear echo "Instalación completada"
#!/bin/bash # Dashboard de sistema con NCurses # Configuración inicial clear tput civis trap 'tput cnorm; clear' EXIT # Colores RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3) BLUE=$(tput setaf 4) RESET=$(tput sgr0) REVERSE=$(tput rev) # Tamaño de pantalla rows=$(tput lines) cols=$(tput cols) # Actualizar dashboard update_display() { # Obtener información del sistema local cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}') local mem_usage=$(free -m | awk '/Mem:/ {printf "%.1f", $3/$2*100}') local disk_usage=$(df -h / | awk '/\// {print $5}') local uptime=$(uptime -p) local hostname=$(hostname) # Dibujar interfaz clear # Marco tput cup 0 0 echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗" for i in $(seq 1 $((rows-3))); do tput cup $i 0; echo -e "║${RESET} ${BLUE}║" done tput cup $((rows-2)) 0 echo -e "╠════════════════════════════════════════════════════════════════╣" tput cup $((rows-1)) 0 echo -e "║ ${YELLOW}Q${RESET}:Salir ${YELLOW}R${RESET}:Actualizar ${BLUE}║" echo -e "╚════════════════════════════════════════════════════════════════╝${RESET}" # Contenido tput cup 2 5; echo -e "${REVERSE} DASHBOARD DEL SISTEMA ${RESET}" tput cup 4 5; echo -e "${GREEN}Hostname:${RESET} $hostname" tput cup 5 5; echo -e "${GREEN}Uptime:${RESET} $uptime" # CPU tput cup 7 5; echo -e "${BLUE}CPU Usage:${RESET}" tput cup 7 20; printf "[%5.1f%%] " $cpu_usage local cpu_bar=$(( (cols-30) * cpu_usage / 100 )) printf "${GREEN}%${cpu_bar}s${RESET}${RED}%$((cols-30-cpu_bar))s${RESET}" "" "" | tr ' ' '=' # Memoria tput cup 9 5; echo -e "${BLUE}Mem Usage:${RESET}" tput cup 9 20; printf "[%5.1f%%] " $mem_usage local mem_bar=$(( (cols-30) * mem_usage / 100 )) printf "${GREEN}%${mem_bar}s${RESET}${RED}%$((cols-30-mem_bar))s${RESET}" "" "" | tr ' ' '=' # Disco tput cup 11 5; echo -e "${BLUE}Disk Usage (root):${RESET}" tput cup 11 25; printf "[%5s] " "$disk_usage" local disk_value=${disk_usage%\%} local disk_bar=$(( (cols-35) * disk_value / 100 )) printf "${GREEN}%${disk_bar}s${RESET}${RED}%$((cols-35-disk_bar))s${RESET}" "" "" | tr ' ' '=' # Procesos tput cup 13 5; echo -e "${BLUE}Top Processes:${RESET}" local proc_line=15 ps -eo pid,user,pcpu,pmem,comm --sort=-pcpu | head -6 | tail -5 | while read -r line; do tput cup $proc_line 5; echo "$line" ((proc_line++)) done } # Bucle principal while true; do update_display # Esperar entrada read -t 5 -n 1 key case $key in q|Q) break ;; r|R) continue ;; *) sleep 1 ;; esac done clear