Monitorizar la Wi-Fi con un alias

← Inicio

Después de los problemas que tenía con desconexiones esporádicas de la Wi-Fi y de aplicar con éxito la solución que he publicado, opté por crear un alias que monitorizara la conexión. Sin embargo, ni de lejos fue tan fácil como pensaba.

Monitorización de la señal Wi-Fi desde la terminal

La idea inicial

La intención era bastante sencilla: disponer de un pequeño monitor en la terminal que mostrara en tiempo real la intensidad de la señal Wi-Fi, tanto en dBm como mediante una barra visual y un porcentaje.

El comando utiliza iw para obtener la información de la conexión y awk para procesarla y convertir el valor de la señal en una representación más sencilla de interpretar.

Además, utilizando watch podemos actualizar la información automáticamente cada segundo.

El problema: las comillas

El problema apareció cuando intenté convertir todo el comando en un alias normal de zsh.

El comando original combina varias capas de interpretación:

zsh → watch → iw → awk

Y dentro del propio código de awk necesitamos utilizar comillas, variables como $2, cadenas de texto y otros caracteres especiales.

Al intentar introducir todo esto directamente dentro de un alias, las diferentes capas de comillas empiezan a interferirse entre sí. Es entonces cuando aparecen construcciones bastante poco amigables como:

'\''

Aunque es posible escapar correctamente todas las comillas, el resultado termina siendo difícil de leer, modificar y, sobre todo, de depurar cuando algo no funciona.

¿Por qué no utilizar una función?

Una solución bastante habitual en zsh sería convertir el comando en una función. De hecho, para este tipo de situaciones resulta mucho más cómodo que un alias.

Pero en mi caso quería utilizar específicamente un alias. Por tanto, la solución tenía que permitir mantener el comando como alias sin tener que convertirlo en una función.

La solución: separar el comando en un script

La solución que finalmente adopté fue muy sencilla: sacar la parte complicada del alias y convertirla en un pequeño script independiente.

El script se guarda en:

~/.local/bin/wifiwatch

Y el alias solamente se encarga de ejecutar ese script utilizando watch:

alias wifiwatch='watch -n 1 ~/.local/bin/wifiwatch'

De esta manera conseguimos mantener un alias de zsh, pero sin tener que introducir dentro de él todo el código de awk.

Antes de empezar: comprobar que tenemos iw

Hay un detalle importante que conviene comprobar antes de crear el script: necesitamos tener instalado iw.

iw es una utilidad de línea de comandos para trabajar con dispositivos inalámbricos mediante nl80211. En sistemas basados en Arch, como EndeavourOS, se distribuye como un paquete independiente llamado precisamente iw. El paquete proporciona el ejecutable /usr/bin/iw.

Por tanto, si al ejecutar:

iw --version

obtenemos algo parecido a:

bash: iw: orden no encontrada

no estamos ante un problema de bash ni de zsh. Simplemente, el sistema no encuentra el programa iw.

En EndeavourOS podemos instalarlo mediante:

sudo pacman -S iw

Después podemos comprobar que está disponible con:

iw --version

Una vez instalado, ya podremos continuar con el procedimiento.

¿Bash o Zsh?

Este problema también sirve para aclarar una posible confusión. El hecho de que utilicemos zsh para crear el alias no significa que iw dependa de Zsh.

Si ejecutamos:

iw dev

desde Bash, Zsh o cualquier otro shell, estamos ejecutando el mismo programa.

El alias que utilizamos sí es específico de Zsh porque lo hemos añadido a ~/.zshrc, pero el script que contiene el comando comienza con:

#!/bin/sh

Por tanto, el problema de que iw no esté instalado es independiente del shell utilizado.

¿Cómo se llama nuestra interfaz Wi-Fi?

Una vez que tenemos iw disponible, aparece otro pequeño problema: no todos los sistemas utilizan wlan0 como nombre de la interfaz Wi-Fi.

En mi caso podría haber utilizado:

wlan0

pero otro equipo puede utilizar perfectamente un nombre como:

wlp2s0

Por eso no conviene escribir directamente wlan0 en el script y asumir que será igual para todos.

Podemos comprobar el nombre de nuestra interfaz con:

iw dev

La documentación de ArchWiki también recomienda utilizar iw dev para obtener el nombre de la interfaz inalámbrica; el nombre aparece después de la palabra Interface.

Una salida típica podría ser:

phy#0
    Interface wlp2s0
        ifindex 3
        wdev 0x1
        addr xx:xx:xx:xx:xx:xx
        type managed

En este ejemplo, nuestra interfaz sería wlp2s0.

Detectar automáticamente la interfaz

Para evitar que el script dependa de que la interfaz se llame exactamente wlan0, podemos hacer que sea el propio script quien obtenga el nombre de la interfaz Wi-Fi.

De esta forma, en lugar de escribir:

iw dev wlan0 link

utilizaremos automáticamente la interfaz que encontremos mediante iw dev.

Crear el directorio

Primero creamos el directorio donde guardaremos nuestros scripts personales, si todavía no existe:

mkdir -p ~/.local/bin

Crear el script

A continuación creamos el archivo:

nano ~/.local/bin/wifiwatch

Dentro colocamos:

#!/bin/sh


IFACE=$(iw dev | awk '$1 == "Interface" {print $2; exit}')

if [ -z "$IFACE" ]; then
    echo "No se ha encontrado ninguna interfaz Wi-Fi."
    exit 1
fi

iw dev "$IFACE" link | awk '
/signal:/ {
    db=$2
    pct=2*(db+100)
    if (pct>100) pct=100
    if (pct<0) pct=0
    filled=int(pct/5)
    bar=""
    for (i=0; i<20; i++)
        bar=bar (i<filled ? "█" : "░")
    printf "       signal: %4s dBm [%s] %3d%%\n", db, bar, pct
    next
}
{print}
'

La diferencia importante respecto al script original está en esta línea:

IFACE=$(iw dev | awk '$1 == "Interface" {print $2; exit}')

En lugar de asumir que nuestra tarjeta se llama wlan0, el script consulta las interfaces disponibles y obtiene su nombre.

Así, el mismo script puede funcionar con una interfaz llamada wlan0, wlp2s0 u otro nombre.

Dar permisos de ejecución

Una vez guardado el archivo, le damos permisos de ejecución:

chmod +x ~/.local/bin/wifiwatch

Ahora podemos comprobar que el script funciona ejecutándolo directamente:

~/.local/bin/wifiwatch

Un detalle importante: los permisos de iw

Al probar este tipo de comandos en diferentes distribuciones podemos encontrarnos con otra diferencia: algunas operaciones de iw pueden requerir privilegios de root.

La propia documentación de ArchWiki advierte de que muchos comandos de iw deben ejecutarse con permisos de root, aunque esto no significa que todas las operaciones necesiten necesariamente dichos privilegios.

De hecho, un lector me comentó que en openSUSE Tumbleweed necesita ejecutar:

sudo iw dev wlp2s0 link

mientras que en mi sistema puedo realizar la consulta sin sudo.

Por tanto, si al ejecutar:

class="wp-block-code">iw dev "$IFACE" link

nuestro sistema devuelve un error de permisos, tendremos que adaptar esta parte a nuestra configuración.

No he incluido sudo directamente en el script porque watch ejecuta el comando repetidamente. Si sudo necesita solicitar la contraseña, el funcionamiento del monitor dejaría de ser completamente automático.

En ese caso, habrá que configurar los permisos necesarios de acuerdo con la distribución y la política de seguridad del sistema.

Crear el alias en Zsh

Si todo funciona correctamente, solamente queda crear el alias.

Editamos nuestro archivo ~/.zshrc y añadimos:

alias wifiwatch='watch -n 1 ~/.local/bin/wifiwatch'

Después recargamos la configuración de zsh:

source ~/.zshrc

Monitorizar la Wi-Fi

A partir de ahora solamente tenemos que ejecutar:

wifiwatch

watch ejecutará el script cada segundo y podremos ver la información de la conexión Wi-Fi actualizada en tiempo real.

El resultado muestra la señal en dBm y una barra visual que permite hacerse rápidamente una idea de la intensidad de la conexión.

¿Qué hemos conseguido?

La diferencia respecto al intento inicial es que ahora cada componente tiene una responsabilidad muy concreta:

zsh
 └── alias wifiwatch
       └── watch -n 1
             └── ~/.local/bin/wifiwatch
                   └── iw + awk

El alias se ocupa únicamente de lanzar el monitor periódicamente.

El script se encarga de localizar la interfaz Wi-Fi, ejecutar iw y procesar su salida mediante awk.

Una solución más fácil de mantener

Además de solucionar el problema de las comillas y evitar depender de un nombre concreto como wlan0, esta estructura tiene otra ventaja: podemos modificar el funcionamiento del monitor sin tocar el alias.

Si posteriormente queremos cambiar el aspecto de la barra, el cálculo del porcentaje, la información mostrada o cualquier otro detalle, solamente tenemos que editar:

~/.local/bin/wifiwatch

El alias puede permanecer exactamente igual:

alias wifiwatch='watch -n 1 ~/.local/bin/wifiwatch'

Conclusión

El problema no era que zsh no permitiera utilizar este comando como alias. El verdadero inconveniente era intentar introducir dentro de una única cadena todas las capas de interpretación necesarias para watch y awk.

Además, al convertirlo en un script descubrimos otros dos detalles que no conviene pasar por alto: no todos los sistemas utilizan wlan0 como nombre de su interfaz Wi-Fi y iw no tiene por qué estar instalado en todos los sistemas.

En sistemas basados en Arch, por ejemplo, iw es un paquete independiente que podemos instalar con pacman.

Y dependiendo de la distribución y de la operación que queramos realizar, también podemos encontrarnos con requisitos de permisos diferentes.

Separar el código en un pequeño script nos permite resolver el problema de las comillas, detectar automáticamente la interfaz y mantener el alias sencillo y fácil de modificar.

De esta forma seguimos teniendo exactamente lo que buscábamos: un alias de Zsh para monitorizar la Wi-Fi en tiempo real, sin funciones y sin tener que pelear continuamente con las comillas.


Descubre más desde Tecno y Soft

Suscríbete y recibe las últimas entradas en tu correo electrónico.

Descubre más desde Tecno y Soft

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo