miércoles, 24 de diciembre de 2008

Como actualizar el kernel de linux de forma remota.



(Y no morir en el intento)


Si administran servidores remotamente se habrán encontrado en esta situación al menos una vez en su vida (Y si todavía no, agenden por que les va a tocar mas tarde o mas temprano): Hay que recompilar el kernel por X motivo y reiniciar para aplicar los cambios. El servidor está a varios kilómetros de distancia...

¿Y si hago las cosas mal, reinicio y mi servidor o pc remota no vuelve mas?

Tratándose de un caso semejante voy a presuponer que saben poner a funcionar el daemon ssh de su distribución de cabecera, saben loguearse remotamente por ssh, como compilar un kernel y como ponerlo a funcionar. Me salteo toda esa parte obvia y voy a lo importante que por ahí no todos conocen: Como asegurarme de recuperar el control si algo falla.

Vamos a un caso práctico: Una pc con un kernel guardado como bzimage en /boot/ y un kernel nuevo recién compilado de nombre bzimage_nueva.
Necesito bootear con bzimage_nueva pero si algo falla necesito poder volver a bzimage automáticamente. Grub al rescate.

Si mi menu.lst de grub decía para arrancar mi pc:
Cita /boot/grub/menu.lst:

default 0
timeout 5

title Linux opción 0
root (hd0,0)
kernel (hd0,0)/boot/bzimage root=/dev/sda3


Hay que agregar el nuevo kernel, bzimage_nueva habilitando lo que se llama fallback:
Cita /boot/grub/menu.lst:
default saved #por defecto bootear desde la opción guardada
timeout 5
fallback 1 #en caso de fallo, caer a la opción 1

title Linux opción 0 #Bootear mi nuevo kernel
root (hd0,0)
kernel (hd0,0)/boot/bzimage_nueva root=/dev/sda3
savedefault fallback

title Linux opción 1 #bootear mi antiguo kernel
root (hd0,0)
kernel (hd0,0)/boot/bzimage root=/dev/sda3
savedefault



Explicación:

- Fallback 1 es autoexplicativo, en caso de que la opción que tenga memorizada grub como default sea fallback, al próximo reinicio en lugar de caer en la opción 0 al cabo de 5 segundos, caer en la opción 1

- savedefault fallback implica que si grub ejecuta esta opción, al próximo reinicio la opción por defecto será fallback y como fallback apunta a la opción 1, entonces al próximo reinicio usar la opción 1 del menú.

- savedefault es bastante obvio, hacer de esta si llega a ser usada en algún momento la opción por defecto hasta que se especifique lo contrario. Con esto me aseguro de que pase lo que pase, al segundo reinicio y de ahí en adelante vuelva al kernel viejo que sé que funcionaba.

Queda un último detalle. Necesito decirle a Grub que solo por esta vez la opción saved en lugar de ser fallback va a ser 0, la primera opción del menú. Con esto me aseguro de que el primer reinicio se haga desde mi kernel nuevo:
Cita :
neotux ~ # grub-set-default 0


Hasta ahí, por si no se entendió, el comportamiento de Grub va a ser el siguiente:
- Próximo reinicio, usar la opción cero
- Pase lo que pase, al reinicio inmediato siguiente usar siempre la opción 1 del menú.

¿Y si alguna de las opciones del kernel la puse mal, no la tuve en cuenta, me olvidé de algo? ¿Como hago para que la pc se reinicie sola?
Cita /boot/grub/menu.lst:
kernel (hd0,0)/boot/bzimage_nueva root=/dev/sda3 panic=10

La opción panic=10 en la misma línea en donde se declara el kernel hace que la pc se reinicie sola en caso de un kernel panic al cabo de 10 segundos.

Con eso casi que están prácticamente todas las posibilidades cubiertas, peeeeero (esto me pasó una vez) necesito volver a tener conectividad al proximo reinicio con mi kernel nuevo y para que esto pase tengo que tener en cuenta todos los módulos de netfilter si los usé, tun/tap si hay vpn o brdige de por medio, y obviamente drivers de placas de red... ¿Y si la pc bootea bien pero no tengo conectividad y no tengo kernel panic que me la reinicie sola?

Inittab al rescate. Primero creo un archivo que se llame reiniciar cuya única función es esa, esperar 2 minutos (120 segundos) y ejecutar el comando reboot.
Cita :
neotux ~ # echo "sleep 120 && reboot" > /usr/bin/reiniciar
neotux ~ # chmod +x /usr/bin/reiniciar

Para luego agregar este archivo reiniciar al inittab, modificando la línea que decía:
Cita /etc/inittab:
c1:12345:respawn:/sbin/agetty 38400 tty1 linux

Para que en lugar de eso diga:
Cita /etc/inittab:
c1:12345:respawn:/sbin/agetty -n -l /usr/bin/reiniciar 38400 tty1 linux


Explicación:

Inittab es el encargado de hacer respawn de los N cantidad de tty's que tu distro de cabecera tuviera por defecto. Con -n -l /usr/bin/reiniciar le estoy diciendo que antes de hacer respawn de la tty 1 (a la que accedés con ctrl + alt + F1) ejecute el comando reiniciar, el cual me da dos minutos, tiempo mas que suficiente para poder loguearme por ssh y comprobar si mi nuevo kernel se comporta como se supone que debería.

En caso de que algo falle, si la pc reinicia bien pero no tiene conectividad, al cabo de dos minutos volverá a reiniciarse sola, y como grub puso como default saved, y saved tiene a fallback y fallback es el kernel viejo donde todo funciona... Estaría de vuelta en donde empecé.

Ni falta hace que diga que si todo va bien, hay que deshacer los cambios tanto en el archivo menu.lst como en inittab, ¿no?

La única vez que me salió mal una actualización de kernel y perdí conectividad casi me arrancan la cabeza. Desde entonces vengo usando este método y me ha resultado infalible. Espero que le sirva a alguien mas. Si se les ocurre alguna otra medida paranoica de seguridad que estaría bien tener en cuenta, escucho ofertas.

Las instrucciones siempre trato de hacerlas genéricas, aplicables a linux, indistintamente la distribución de la que se trate, pero en el caso de el archivo inittab, suele variar ligeramente de una distribución a otra. La línea del inittab del ejemplo que pongo mas arriba es de Gentoo. Lo único importante es que entre getty y los baudios (38400) va el comando a ejecutar, y eso si para todas las distro es déntico.


este porte es gracias a :
Procastineitor EL PIBE ARGENTINO

No hay comentarios: