D-Link DSL-G624T: Script para autoreiniciar si se cuelga el ADSL
28 de Junio de 2007 en Sistemas, Linux
Lecturas: 10,425

D-Link DSL-G624TPara conectarme a internet uso un router Wifi D-Link DSL-G624T regalado al contratar el ADSL con Ya.com. No es un mal router una vez configurado un poco, pero sufre algunos problemas para mantener la conexión a internet cuando se calienta en exceso o cuando la mula está encendida.

Sus cuelgues son curiosos, pues la Wireless sigue funcionando, pero la conexión a internet se cierra y el acceso al router por Web también. En cambio el acceso por telnet sigue operativo. Normalmente lo reseteo físicamente y en un par de minutos todo vuelve a la normalidad. El problema viene cuando no estoy en casa y no tengo acceso a él, con lo que no puedo restaurar la conexión a internet de la casa hasta que no vuelvo.

Chafardeando el router me encontré con que internamente funciona con un BusyBox pequeñito, que no deja de ser un mini-Linux con sus funcionalidades básicas

En este artículo explico cómo realizar un script en nuestro servidor casero que comprueba el aceso a internet, y si no lo hay, que acceda al router y lo reinicie.

En primer lugar debo dar las gracias a i compañero Alex, pues me enseñó la forma de automatizar la conexión al router por telnet y su reseteo para embedirlo en un script Bash.

El truco consiste en un par de scripts: uno que efectúa el reseteo del router y otro que controla la lógica del programa. De hecho, se podría confeccionar un sólo script que haga todo el trabajo pero me gusta tener el script de reseteo por separado por si lo uso atómicamente en otra tarea.

Empezando por el script de reseteo, consiste en una sucesión de instrucciones que abren un telnet y le printan en su consola las instrucciones que queremos, esperando unos segundos entre instrucción e instrución para darle tiempo al shell de darnos los prompts necesarios.

En primer lugar creamos un archivo llamado restart_router.sh dentro de nuestro directorio de nuestras utilidades del sistema (en mi caso en /server/utils):

$ touch /server/utils/restart_router.sh

y entonces lo abrimos para editarlo:

$ vim /server/utils/restart_router.sh

Una vez abierto escribimos lo siguiente:

(sleep 3; echo “admin”; sleep 3; echo “contrasenya_router”; sleep 3; echo “/sbin/reboot”; sleep 3; echo “exit”) | telnet 192.168.1.1

Vamos a explicarlo… En primer lugar vemos que al final de la línea hay un telnet 192.168.1.1. Ésta es la instrucción que nos conecta con el router. A ella le pasaremos seguidamente el usuario (porque lo primero que hace es preguntarnos el usuario), la contraseña, y justo después la instrucción a ejecutar, haciendo luego un exit para que cierre la conexión. La forma de automatizar el proceso es pasarle las instrucciones mediante el pipe al telnet, hacer un echo de las instrucciones a ejecutar (deben estar entre dobles comillas) y separar las instrucciones con una pausa para darle tiempo a sacar el prompt (de ahí el sleep de 3 segundos). Deberemos sustituir la dirección IP de aquí con la IP de nuestro router y “contrasenya_servidor” con la contraseña que usamos para entrar al router. Debemos asegurarnos que está todo en una misma línea y que los parámetros están todos entre un mismo paréntesis.

Una vez guardado el archivo, debemos darle permisos de ejecución al archivo con, por ejemplo:

$ chmod +x /server/utils/restart_router.sh

A continuación, vamos a por el segundo script. Éste debe decidir si hay acceso a internet o no. Para ello haremos ping a un host de internet (por ejemplo a Google) y capturaremos la salida. De la salida nos quedamos con el número del porcentaje de paquetes perdidos que será lo que usaremos para distinguir si hay internet o no. Así que primero de todo creamos el archivo:

$ touch /server/utils/adsl_keep_online.sh

Y lo abrimos para editarlo:

$ vim /server/utils/adsl_keep_online.sh

Allí escribimos la cabecera del intérprete de comandos:

#!/bin/bash

Y ejecutamos el ping seleccionando la parte que nos interesa (el número del porcentaje de paquetes perdidos) y lo almacenamos en una variable llamada result:

result=`ping -c 5 www.google.com | grep “packet loss” | awk ‘{printf (”%d”,$6)}’`

En primer lugar, notemos que no hay espacios antes y después del signo igual. Luego, toda la línea del comando (lo que va después del igual) va encerrado entre acentos abiertos sin carácter (dándole al acento y luego un espacio). No confundirlo con comilla simple! La instrución ping la ponemos con el parámetro -c 5, que significa que sólo enviará 5 paquetes (si no ponemos nada, va enviando paquetes hasta el infinito). La salida la dirigimos al grep para que seleccione la línea que contiene “packet loss” (encerrado entre comillas dobles). La salida de ésto la dirigimos al awk, que nos saque sólamente la columna 6, formateándolo en decimal para quitar el símbolo del porcentaje.

A continuación, miramos con un if si el resultado del ping es mayor al 50% en paquetes perdidos. Si es así ejecutamos nuestro primer script para reiniciar el router. Además, aprovecho la salida para redirigirla a un archivo log situado en /server/logs/adsl.log y dejar constancia así de las verificaciones que se lleban a cabo cada vez que se ejecuta el programa. El archivo queda finalmente así:

#!/bin/bash

result=`ping -c 5 www.google.com | grep “packet loss” | awk ‘{printf (”%d”,$6)}’`
if [ “$result” -gt “50″ ]; then
echo “`date` [KO]: $result% perdido. Rebotando Router” >> /server/logs/adsl.log
echo “————————————>>>>>>>>>>>>>” >> /server/logs/adsl.log
/home/utils/restart_router.sh >> /server/logs/adsl.log
echo “<<<<<<<<<<<<<------------------------------------" >> /server/logs/adsl.log
else
echo “`date` [OK]: $result% perdido” >> /server/logs/adsl.log
fi

Después de guardar debemos setar el archivo como ejecutable:

$ chmod +x /server/utils/adsl_keep_online.sh

Y ya por último queda por incluir este script en la lista de tareas a realizar periódicamente. Yo lo tengo ejecutando cada media hora. Así, debemos editar el archivo de cron:

$ crontab -e

Y añadir una línea de la siguiente forma:

0,30 * * * * /server/utils/adsl_keep_online.sh

Y ya lo tenemos funcionando. Ahora, cada media hora se va a ejecutar un ping de 5 paquetes. Si el resultado en paquetes perdidos es mayor que el 50% se reiniciará el router.

Los más sibaritas en sistemas me podrán decir que reiniciar el router entero por haber perdido la conexión a internet es demasiado bruto. Es verdad, pero aún no he hecho suficientes pruebas para encontrar cuál sería la mejor forma de llevar el objetivo a cabo. Si entramos por telnet al router y ejecutamos un ipconfig podremos ver que existe una interfície llamada ppp0 que es la relativa a el ADSL, pero reiniciar dicha interfície no solucionaría el cuelgue de la administración Web. Seguiré investigando.

Salud!

Tags: , , , , , ,
 Enviar a Fresqui

Leer los Comentarios

[ # 3350 ] Comment desde Miki [05 de Agosto de 2007, 07:05]

No se que tipo de pruebas de calidad deben hacer los de D-LINK a los equipos de red de gama baja, pero el caso es que en la empresa donde trabajaba adquirimos 8 el año pasado, los cuales iban aparentemente bién hasta que dejaban de funcionar (el mismo dia). Después de hacer mil pruebas para asegurar que no era nada nuestro descubrimos que efectivamente era por la temperatura así que los devolvimos todos reportando la incidencia.
Dos meses más tarde nos llegaron los nuevos más un firewall de regalo, supongo que por la espera, lo cual es de agradecer, no obstante aunque aguantan un poco más no podíamos apilarlos ya que volvían a fallar.
Muy buena la explicación de los scripts, un saludo.

[ # 3362 ] Comment desde Xavi [06 de Agosto de 2007, 08:02]

En mi caso es desesperante. Con el verano ha llegado la calor, y con él cuelgues casi diários del router. A veces se cuelga sin posibilidad de que el script haga su trabajo…
Saludos!

[ # 6791 ] Comment desde Yo [10 de Octubre de 2007, 08:28]

¿Y si en vez de “/sbin/reboot” pones “/sbin/init”?

::restart:/sbin/init

‘restart’ is the action taken to restart the init process

[ # 6819 ] Comment desde Xavi [11 de Octubre de 2007, 07:40]

Pues hombre, la vía fácil era el reboot. puedes usar el init, pero debes asegurarte si está soportado por el sistema. Ahora mismo uso otro router así que no lo puedo comprobar.

Saludos.

[ # 10934 ] Comment desde sQalo [05 de Diciembre de 2007, 07:32]

Con reboot me queda claro que reinicia el router, pero como puedo mediante telne resetear el router a los valores de fábrica???? gracias

[ # 12307 ] Comment desde ramoncio [20 de Diciembre de 2007, 08:24]

Muy buena jugada!
Y no habria manera de poner ese script dentro del propio router?
Por lo que tengo entendido, tienes que tener un equipo linux corriendo el script continuamente…
Si el router tiene linux igual se podria meter en el firmware o en la flash, no se como funciona este router en particular.
Asi no tendrias que tener un equipo encargado de la faena, seria el propio router el que lo hiciera todo, y tambien valdria para los windowseros sin cygwin, que por desgracia son la mayoria.

[ # 12331 ] Comment desde Xavi [21 de Diciembre de 2007, 09:05]

No he probado de poner el script dentro. De hecho, se podría hacer que el par de scripts estuviera dentro… seria, como dices, más lógico y menos dependiente de un PC externo. Sólo es necesario un cron ;) Y no miré si lo lleva.

Salu10

[ # 16973 ] Comment desde ANTONIO [04 de Febrero de 2008, 08:28]

Tengo un amigo que ha intentado actualizar el firmware y se le ha quedado frito. Hay alguna forma de hacer algo?
Gracias por adelantado.

[ # 17022 ] Comment desde Xavi [05 de Febrero de 2008, 09:31]

No lo sé… Y éso se escapa del tema del artículo…

[ # 17197 ] Comment desde ahs [06 de Febrero de 2008, 10:49]

El script adsl_keep_online.sh me da problemas al escribirlo en un documento, podrías colgar el tuyo.

[ # 17253 ] Comment desde ahs [08 de Febrero de 2008, 01:16]

a costa de repetirme me gustaría pedir a alguien que tenga el script adsl_keep_online.sh que me lo enviara por correo si puede a la direción ahs_rodrigez1@hotmail.com, os lo agradecería. mucho

[ # 17257 ] Comment desde Xavi [08 de Febrero de 2008, 09:34]

ahs: El script te da problemas por el tema de las comillas. Te pasaría el mío pero ahora tengo el server jodido (un DIMM de RAM muerto) y no puedo acceder a él.

Léete el artículo y pon especial atención a las comillas (en el artículo está explicado). Cuando pueda colgaré el script para descarga.

[ # 17330 ] Comment desde ahs [10 de Febrero de 2008, 07:50]

Xavi: e intentado lo que dices de las comillas pero sigue dándome error

[ # 18448 ] Comment desde Pedro [12 de Marzo de 2008, 04:36]

Yo tambien estoy intentando meterle el script a mi busybox basado en ash y no bash…y no acabo de hacerlo funcionar: 2: Syntax error: “(” unexpected

Por favor, alguien que lo tuviera podria enviarmelo a este email?

Gracias y un saludo.

[ # 19444 ] Comment desde david [07 de Abril de 2008, 11:45]

el problema seguramente lo tendreis con este trozo :

result=`ping -c 5 www.google.com | grep “packet loss†| awk ‘{printf (â€Â%dâ€Â,$6)}’`

que ha de ir junto en una sola linea y os detecta el (â€Â%dâ€Â,$6)}’` como otra linea , editad el fichero , todo este trozo ha de ir en un sola linea.

[ # 22291 ] Comment desde Tass [19 de Mayo de 2008, 04:00]

En el script adsl_keep_online.sh en la línea del if si dejamos la comparación entre comillas trata de ejecutar el $result como comando en vez de comparar los números (debian):

if [ “$result†-gt “50″ ]; then
por
if [ $result -gt 50 ]; then

Igualmente gracias por el script :)

[ # 24502 ] Comment desde Miquel Adrover [12 de Junio de 2008, 09:28]

FYI

En esta página hay mucha información de como administrar el router via telnet:

http://pukadiary.ranmachan.dyndns.org/D-Link_DSL380T

[ # 24505 ] Comment desde Miquel Adrover [12 de Junio de 2008, 09:35]

Para obtener la velocidad de bajada del router:

(sleep 3; echo “admin”; sleep 3; echo “admin”; sleep 3; echo “echo ’sar:status/dsl_ds_rate’ | cm_cli -l “; sleep 3; echo “exit”) | telnet 192.168.1.1 | grep dsl_ds_rate | awk -F”=” ‘{print $2}’

[ # 24545 ] Comment desde Xavi [13 de Junio de 2008, 09:57]

Gracias Miquel.

[ # 31591 ] Comment desde Peperfus [09 de Agosto de 2008, 05:50]

Hola, el script va de PM, una excelente solución. Lo utilizo para el router conceptronic.

El problema que tengo, es que no se me ejecuta en el cron y no sé por que. Lo tengo puesto igual, a cada media hora. Uso Debian 4 (etch). ¿Alguna idea de por qué puede ser?

[ # 31772 ] Comment desde Xavi [11 de Agosto de 2008, 07:55]

Verifica que la ruta de acceso al script sea la correcta. Si no te dió problemas al editar el crontab, diría que debes tenerlo funcionando… pero puede que la ruta esté mal.

Pruébalo y nos dices.

Salu2

[ # 32326 ] Comment desde Peperfus [16 de Agosto de 2008, 02:04]

Ok, ya está arreglado lo del cron. El problema era que tenía que añadir la ejecución cron manualmente en /etc/cron.d. Además, para invocar al script, tuve que hacerlo mediante sh y el usuario.

Pero ahora creo que tenemos un problema, bastante lógico que acabo de descubrir. Es un pequeño bug del script que creo que se puede corregir fácilmente, aunque necesito pulir un detalle.

El bug consiste en esto:
Si no hay internet, el comando ping no va a conseguir resolver la IP de la petición www.google.es, por lo tanto dará error y la variable result no coge valor. Luego el test falla porque no existe result.
Creo que deberíamos reemplazar www.google.es por una IP (una de las IPs de google, por ejemplo), así no necesita dns para resolver.
En los casos en que funciona supongo que será porque ya tiene la petición resuelta en la caché y por eso no pregunta al dns.
Bueno, yo lo he probado y avanza ese paso, el ping va bien, pero el problema es que la variable result me coge un valor un poco extraño y sospecho que tiene que ver con el formato de printf.

¿Al variar la longitud de la cadena del ping supongo que cambiará el “recorte de la cadena” para extraer el porcentaje de paquetes perdidos…?
En tal caso, cuál sería la orden printf correcta para que recortara el % si cambiamos www.google.es por 66.249.91.147 (que es la IP que me resuelve mi dns por www.google.es).

Gracias y perdón por el comentario tan largo.

[ # 32329 ] Comment desde Peperfus [16 de Agosto de 2008, 02:21]

Ok, ya veo lo que pasa con la salida del ping…
en caso de éxito de los pings, la salida del packet loss muestra:
“5 packets transmitted, 5 received, 0% packet loss, time 3998ms”
Ahí funciona bien, porque (según creo), el $6 del printf recoge la 6ª palabra, que es el 0%
Pero en caso de fallo de los pings, la salida del packet loss es distinta, muestra:
“5 packet transmitted, 0 received, +5 errors, 100% packet loss, time 3997ms”
Así que el $6 recoge +5, (5) que es menor que 50 (supuesto 50%) de paquetes perdidos y por eso no me reiniciaba el router.
De momento, como parche provisional (hasta mejor solución) creo que se podría arreglar cambiando el test, simplemente a -gt 2 (por ejemplo), que en caso de acierto (0% packet loss) será falso y en caso de fallo (más de 2 packets loss) será verdadero y reiniciará el router.

Bueno, es una sugerencia, que alguien me corrija si me equivoco en algo o hay una mejor solución (supongo que sí).

Saludos y perdón otra vez por el comentario tan largo
Espero que esté bien explicado, si no lo está, pedid aclaración o preguntad lo que sea
xD

[ # 32651 ] Comment desde Xavi [18 de Agosto de 2008, 08:17]

Buenas Peperfus.

He estado fuera y no he podido atenderte a tiempo ;)

Tu mismo ya has encontrado la solución ;) El problema principal es la toma de valores según el número de la columna y usar éso como variable a analizar para decidir si reiniciar el router o no. Puedes jugar con la salida del ping, para que te de un formato con el que puedas contar siempre.

Tu solución me parece perfecta… de momento. A ver si tengo un rato y pruebo algunas soluciones más ;)

Salu10

[ # 46374 ] Comment desde TunLuek [25 de Noviembre de 2008, 06:32]

mas corto >:

#!bin/sh
/bin/ping -c 5 rediris.es || /home/utils/restart_router.sh

Escribe un Comentario





Estadísticas