Monitorizar la Wi-Fi con un alias

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: ¿cómo se llama nuestra interfaz Wi-Fi?

Aquí apareció otro pequeño problema al compartir el script: 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

También podemos encontrar otros nombres dependiendo del hardware y de cómo haya sido configurado el sistema. Los nombres de interfaces de red en Linux moderno pueden seguir esquemas predecibles basados, entre otras cosas, en la ubicación del dispositivo; el prefijo wl se utiliza para interfaces WLAN.

Por eso, antes de dar por hecho el nombre de la interfaz, podemos comprobarlo con:

iw dev

Una salida típica puede mostrar algo parecido a:

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 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 es 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 el nombre de la primera interfaz que encuentra.

Esto permite que el mismo script pueda funcionar, por ejemplo, con una interfaz llamada wlan0 o con otra llamada wlp2s0.

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: los permisos necesarios para ejecutar determinadas operaciones de iw pueden depender de la distribución y de la configuración del sistema.

Por ejemplo, un lector me comentó que en openSUSE Tumbleweed necesita ejecutar:

sudo iw dev wlp2s0 link

mientras que en mi sistema puedo ejecutar el comando sin sudo.

Por tanto, si al ejecutar:

iw dev

o:

iw dev <interfaz> link

nuestro sistema devuelve un error de permisos, tendremos que adaptar el script a nuestra configuración y utilizar los privilegios necesarios.

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

En ese caso, una posibilidad es configurar previamente los permisos necesarios para que el usuario pueda realizar esa consulta sin tener que introducir la contraseña cada vez. La configuración concreta dependerá de la distribución y de la política de permisos 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 otro detalle importante: tampoco debemos asumir que todos los sistemas llaman wlan0 a su interfaz Wi-Fi. Una interfaz puede llamarse perfectamente wlp2s0 u otro nombre diferente.

Separar el código en un pequeño script nos permite resolver ambos problemas de una forma mucho más limpia y facilita además su adaptación a diferentes sistemas.

Eso sí, como ha demostrado el comentario de un lector, Linux no siempre se comporta exactamente igual en todas las distribuciones. Si iw requiere privilegios adicionales en nuestro sistema, tendremos que adaptar también esa parte.

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.