Hora en Linux y diferencias con Windows
Estos últimos días estuve experimentando problemas con la hora en Linux. Algo se rompió después de una actualización y el reloj estaba tomando mal la hora.
Igualmente esto ya me había pasado hace un tiempo, entre reiniciada en Linux y Windows, tenía problemas con la hora. Después de un poco de búsqueda, encontré la razón del problema, así que decidí compartir con ustedes cómo se maneja la hora en Linux.

El problema es básicamente que en Linux el sistema se configura para utilizar el reloj de hardware como hora universal (UTC o GMT) y calcula la hora local realizando la conversión correspondiente a nuestro país utilizando zonas horarias (timezone); mientras que Windows toma la hora de hardware directamente como hora local.
Y entonces qué?... bueno, si por ejemplo colocamos nuestro reloj de hardware para ser hora UTC, seteamos el timezone correspondiente a nuestro país, en Linux la hora estará bien, pero en Windows tenemos la hora UTC como hora local, y si colocamos la hora bien en Windows, tendremos mal la hora en Linux.

En Linux al bootear se lee la hora del reloj de hardware, se coloca en el reloj del sistema y luego se calcula la hora local en base al timezone que tengamos seteado. Por esto es que tenemos dos relojes, el de hardware y el de sistema, los cuales almacenarán horas diferentes y se modifican con comandos diferentes.

Para modificar la hora podemos utilizar el comando date, el cual modifica el reloj del sistema, por lo que las modificaciones no serán visibles luego de reiniciar, esto es algo que me hizo perder bastante tiempo...
El comando date no sólo nos permite setear la hora local, sino también ver la hora actual. Si corremos date sin argumentos, podemos ver la hora actual. Ahora, el funcionamiento básico para setear la hora con date es date <mes><dia><hora en formato 24><minutos>, así por ejemplo, si queremos decir que es 5 de septiembre a las 18:57, deberemos escribir date 09051857. date permite otros argumentos para poder decirle en qué formato le estamos pasando la hora, pero ese es el funcionamiento más básico y a mi me alcanza.
Una forma tal vez más visible, es utilizar el parámetro set, así podemos lograr setear el año también. Para el ejemplo anterior, el formato sería el siguiente: date --set "2009-09-05 18:57".

Como menciono en el párrafo anterior, date setea la hora del sistema, no la de hardware. Si queremos setear la hora de hardware, deberemos utilizar el comando hwclock. La forma más sencilla de setear la hora de hardware es acomodarla según la hora del sistema, es decir, sincronizamos el reloj de hardware con el del sistema. Para lograr esto, debemos ejecutar "hwclock --systohc", si es que no deseamos utilizar UTC, o bien "hwclock --systohc --utc
" si queremos que el reloj de hardware mantenga la hora UTC, el comando hará la conversión acorde al timezone.
Si le queremos dar la hora directamente al hardware (sin importar qué hora tengamos en el sistema), para el ejemplo del 5 de Septiembre a las 18:57, deberemos utilizar el comando: hwclock --set --date "2009-09-05 18:17"

Es interesante destacar el hecho de mantener la hora de hardware en UTC, todos los manuales UNIX aconsejan esto, dado que tendremos varias ventajas, como coordinar la hora con relojes de internet (o intranet), que el reloj se acomode a los cambios de hora en verano sin intervención, o el hecho de que muchos programas utilizan conversiones horarias para enviar datos a otros países.
Utilizar timezones en Linux es muy sencillo. Para ello tendremos que acomodar el valor /etc/localtime para que mantenga la zona adecuada. Hay dos formas de setear /etc/localtime, la más utilizada es crear un link simbólico a la zona correspondiente en /usr/share/zoneinfo. Si por ejemplo viven en Argentina provincia de Buenos Aires, deberían ejecutar el siguiente comando: ln -sf /usr/share/zoneinfo/America/Argentina/Buenos_Aires /etc/localtime. Cabe destacar que en algunas distribuciones, las zonas se encuentran en /usr/lib/zoneinfo en lugar de /usr/share/zoneinfo, así que presten atención.
Algo a tener muy en cuenta, y es el problema que estuve teniendo, es que en debian cambiaron la idea de linkear /etc/localtime a la zona correcta, y decidieron hacer que /etc/localtime sea una copia de la zona. El cambio surgió a raíz de un bug reportado a las listas de debian, donde si mantenemos el directorio /usr en una partición diferente a la raíz, tendremos un problema. El problema es que si se setea la hora antes de montarse la partición /usr, el sistema arrojará un error, dado que no puede seguir el link. Por esto, se decidió copiar la zona en /etc/localtime. Igual la solución es simple, ejecutar el comando "dpkg-reconfigure tzdata" y elegir en las pantallas subsiguientes la zona que deseamos utilizar.

El problema, para variar, es el maldito Windows, el cual por defecto no le da bola a los timezones y toma la hora de hardware como hora de sistema, rompiéndonos los esquemas. Por esto, si tenemos un esquema de boot dual (Linux/Windows), dependiendo el sistema que iniciemos, veremos una hora diferente. Para solucionar esto desde linux, si no nos importa utilizar hora basada en UTC, deberemos modificar la variable UTC leída al iniciar el sistema cuando se carga el valor del reloj de sistema. Esta variable se encuentra en /etc/default/rcS en sistemas debian o basados en debian, y en /etc/sysconfig/clock en Red Hat y derivados. Si no queremos utilizar UTC, será necesario colocar UTC=no dentro de los citados archivos, los cuales son archivos de texto editables con cualquier editor.
Ahora, esa es la idea, hacer UTC=no dentro de dichos archivos, pero a mi no me funcionó!, por lo que decidí utilizar como timezone UTC+0, osea, sin desfasaje UTC, como si viviera en Londres. Así que luego de solucionar el problema de que en debian no sirve linkear /etc/localtime a la zona UTC, terminé utilizando "dpkg-reconfigure tzdata" y elegir Etc -> UTC. Ahora tengo el problema solucionado.
En un foro leí que se puede utilizar la variable HWCLOCKPARS="--directisa" dentro de /etc/default/rcS y que de esa forma se solucionó el problema de muchos, pero a mi no me sirvió. Si alguno tiene alguna otra sujerencia, son bienvenidos a comentarla =D

Como siempre, espero que esto les ayude a comprender mejor el manejo del reloj en Linux y les permita configurar sus relojes para que marquen la hora que desean.


Algunas referencias:
Debian GNU/Linux System Administrator's Manual: Chapter 16 - Time
Linux Tips - Linux, Clocks, and Time
Debian Wiki - TimeZoneChanges
HowTo: Clock, Time, UTC, Dual boot with Windows

4 comentarios:

JaviZ dijo...

Gracias por la data, la única "técnica" que conocía es la del link simbólico (una vez más demuestro lo viejo que estoy! :).

salu2,
j

Dami@n dijo...

Gracias che, caí googleando por acá. Muy buena explicación.
Saludos ;)

Anónimo dijo...

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation] "RealTimeIsUniversal"=dword:00000001

Anónimo dijo...

Exelente info! hacia rato estaba rengando con este problema, muchas gracias!

Publicar un comentario