index.html (11972B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>El tiempo Unix y NTP</title> 7 <link rel="icon" type="image/png" href="/favicon.png" /> 8 <link rel="stylesheet" type="text/css" href="../article.css" /> 9 </head> 10 <body> 11 <header> 12 <p class="title">El tiempo Unix y NTP</p> 13 <p class="date">22 de agosto de 2017 • fjbalon</p> 14 </header> 15 <p>También Epoch time, Posix time, Unix time ó time_t, es un sistema para la descripción de instantes de tiempo: se define como la cantidad de segundos transcurridos desde la medianoche UTC del 1 de enero de 1970, sin contar segundos intercalares. Es universalmente usado no solo en sistemas operativos tipo-Unix y en muchos sistemas computacionales.</p> 16 <p>No se trata ni de una representación lineal del tiempo, ni de una representación verdadera de UTC (a pesar de que frecuentemente se le confunde con ambos), pues el tiempo que representa es UTC, pero no tiene forma de representar segundos bisiestos de UTC (por ejemplo, 1998-12-31 23:59:60). El tiempo en Unix es un entero con signo que incrementa cada segundo, sin realizar cálculos necesarios para determinar el año, el día del mes, la hora y el minuto, midiendo a partir de 00:00:00 UTC del 1 de enero de 1970. Hay un problema con esta definición, puesto que UTC no existió en su forma actual sino hasta 1972, cuando se establece como referencia 1970-01-01T00:00:00Z. El viernes 13 de febrero de 2009, exactamente a las 23:31:30 (UTC), el tiempo Unix igualó a 1234567890.</p> 17 <p>Entrando ya más en código, el tipo de dato time_t es un tipo de dato de la biblioteca ISO-C definido para el almacenamiento de valores de tiempo del sistema. Estos valores se devuelven desde la función time() de la biblioteca estándar. Este tipo es un typedef definido en la cabecera <time.h>. ISO-C define time_t como un tipo aritmético, pero no especifica ningún rango, resolución, o codificación en particular de la misma. Tampoco especifica los significados de las operaciones aritméticas aplicadas a los valores de tiempo. Unix y los sistemas compatibles con POSIX, implementan time_t como un entero (generalmente de 32 o 64 bits), que representa el número de segundos de Epoch time. Los sistemas que utilizan un tipo time_t entero de 32 bits son susceptibles a los problemas del año 2038.</p> 18 <p>Usando GNU date o BSD date un valor dado time_t se puede convertir en su equivalente en la fecha del calendario:</p> 19 <pre><code>$ date +%s # GNU date 20 1638548288 21 22 $ date -ur 1234567890 # BSD date 23 Mon Oct 07 23:31:30 UTC 2016</code></pre> 24 <p>He aquí un programa C que traduce una fecha en formato humano a su valor en Epoch Unix con time_t, sea una fecha pasada como argumento o la fecha actual:</p> 25 <pre><code>#include <stdio.h> 26 #include <time.h> 27 28 time_t human_date_to_unix_time(const char *human_date) 29 { 30 struct tm tm; 31 time_t unix_time; 32 int r; 33 34 if (human_date == NULL) { 35 printf("null argument\n"); 36 return (time_t)-1; 37 } 38 r = sscanf(human_date, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); 39 if (r != 6) { 40 printf("expected %d numbers scanned in %s\n", r, human_date); 41 return (time_t)-1; 42 } 43 44 tm.tm_year -= 1900; 45 tm.tm_mon -= 1; 46 tm.tm_isdst = 0; 47 unix_time = mktime(&tm); 48 if (unix_time == (time_t)-1) { 49 printf("reading time from %s failed\n", human_date); 50 } 51 52 return unix_time; 53 } 54 55 int main(int argc, char *argv[]) 56 { 57 58 char *dateh; 59 time_t t; 60 61 if( argc > 1 ) { 62 dateh = argv[1]; 63 t = human_date_to_unix_time(dateh); 64 } else { 65 t = time(NULL); 66 } 67 68 printf("%ld\n", t); 69 70 return(0); 71 }</code></pre> 72 <p>En la web, una buena herramienta para convertir entre unidades de tiempo Epoch y humano es <a href="https://www.epochconverter.com/">epochconverter.com</a>.</p> 73 <p>Network Time Protocol (NTP) es un protocolo de Internet para sincronizar los relojes de los sistemas informáticos a través del enrutamiento de paquetes en redes con latencia variable. NTP utiliza UDP como su capa de transporte, usando el puerto 123. Está diseñado para resistir los efectos de la latencia variable.</p> 74 <p>NTP utiliza el algoritmo de Marzullo con la escala de tiempo Tiempo universal coordinado (UTC), incluyendo soporte para características como segundos intercalares. NTPv4 puede mantenerse sincronizado con una diferencia máxima de 10 milisegundos (1/100 segundos) a través de Internet, y puede llegar a acercarse hasta 200 microsegundos (1/5000 segundos) o más en redes de área local sobre condiciones ideales. NTP utiliza un sistema de jerarquía de estratos de reloj, en donde los sistemas de estrato 1 están sincronizados con un reloj externo tal como un reloj GPS o algún reloj atómico. Los sistemas de estrato 2 de NTP derivan su tiempo de uno o más de los sistemas de estrato 1, y así consecutivamente (cabe mencionar que esto es diferente de los estrato de reloj utilizados en los sistemas de telecomunicaciones).</p> 75 <p>El proceso que realiza el protocolo NTP es el siguiente:</p> 76 <ol> 77 <li>Se envía un primer mensaje (petición de sincronización) en el instante T0 del lado del cliente que comprueba si el desfase de tiempo entre el servidor y el solicitante es mayor de 17 minutos.</li> 78 <li>El mensaje llega en el instante T1 al servidor: </li> 79 <ol> 80 <li>En caso de que el desfase sea mayor que 17 minutos el proceso no continuaría, finalizando sin sincronización.</li> 81 <li>Si por el contrario el tiempo es menor que 17 minutos la sincronización continúa. El servidor envía un mensaje con su tiempo en el instante T2.</li> 82 </ol> 83 <li>El paquete se recibe en el cliente en el instante T3. Se realiza un ajuste gradual del tiempo cada minuto hasta aproximarse a 128 ms del tiempo del servidor. El retardo (θ) entre ambos relojes se calcula como: 84 <math xmlns="http://www.w3.org/1998/Math/MathML" alttext="0=\frac{(T1-T0)+(T2-T3)}{2}" display="block"> 85 <mrow> 86 <mn>0</mn> 87 <mo>=</mo> 88 <mfrac> 89 <mrow> 90 <mrow> 91 <mo stretchy="false">(</mo> 92 <mrow> 93 <mrow> 94 <mi>T</mi> 95 <mo></mo> 96 <mn>1</mn> 97 </mrow> 98 <mo>-</mo> 99 <mrow> 100 <mi>T</mi> 101 <mo></mo> 102 <mn>0</mn> 103 </mrow> 104 </mrow> 105 <mo stretchy="false">)</mo> 106 </mrow> 107 <mo>+</mo> 108 <mrow> 109 <mo stretchy="false">(</mo> 110 <mrow> 111 <mrow> 112 <mi>T</mi> 113 <mo></mo> 114 <mn>2</mn> 115 </mrow> 116 <mo>-</mo> 117 <mrow> 118 <mi>T</mi> 119 <mo></mo> 120 <mn>3</mn> 121 </mrow> 122 </mrow> 123 <mo stretchy="false">)</mo> 124 </mrow> 125 </mrow> 126 <mn>2</mn> 127 </mfrac> 128 </mrow> 129 </math> 130 </li> 131 <li>A partir de los 128 ms el desfase va ajustándose cada 17 minutos.</li> 132 </ol> 133 <p>Cuando dos dispositivos se sincronizan entre ellos se genera un desfase de tiempo entre ambos, ya que la precisión se establece en unos 128 ms. La sincronización en cadena de múltiples dispositivos resulta inexacta a partir de la decimosexta vez debido al desfase acumulado cercano a los dos segundos (16 x 0,128=2,048 seg).</p> 134 <p>Una ventaja que presenta este protocolo es la posibilidad de implementar cifrado para tener una conexión segura entre servidor y cliente, y así asegurarse de la autenticidad de la fuente.</p> 135 <p>Comprobar el estado de NTP en la máquina es sencillo utilizando el programa ntpdq, que monitoriza las operaciones del demonio NTP (ntpd) y determina su rendimiento. Para imprimir la lista de los pares conocidos por el servidor y ver su estado use el parámetro -p y para mostrar las direcciones de host en formato numérico de cuatro puntos en lugar de convertirlas a los nombres de host canónicos use -n, así:</p> 136 <pre><code>$ ntpq -p 137 remote refid st t when poll reach delay offset jitter 138 ============================================================================== 139 ns4.turbodns.co 94.130.184.193 3 u 2 64 1 47.387 -129744 0.000 140 190.pool90-165- 150.214.94.5 2 u 4 64 1 22.167 -129743 0.000 141 rs-project.org 185.102.185.67 3 u 1 64 1 86.338 -129735 0.000 142 time.cloudflare 10.89.8.6 3 u 4 64 1 19.047 -129744 0.000 143 144 145 $ ntpq -pn 146 remote refid st t when poll reach delay offset jitter 147 ============================================================================== 148 81.21.65.169 94.130.184.193 3 u 10 64 1 47.387 -129744 0.000 149 90.165.120.190 150.214.94.5 2 u 12 64 1 22.167 -129743 0.000 150 213.231.2.124 185.102.185.67 3 u 9 64 1 86.338 -129735 0.000 151 162.159.200.123 10.89.8.6 3 u 12 64 1 19.047 -129744 0.000</code></pre> 152 <p>Otra fuente fiable es:</p> 153 <pre><code>$ ntpq -c rv 154 associd=0 status=c018 leap_alarm, sync_unspec, 1 event, no_sys_peer, 155 version="ntpd 4.2.8p15@1.3728-o Wed Jul 1 17:02:17 UTC 2020 (1)", 156 processor="x86_64", system="Linux/5.15.5-arch1-1", leap=11, stratum=16, 157 precision=-24, rootdelay=0.000, rootdisp=2.070, refid=STEP, 158 reftime=(no time), 159 clock=e554ba53.4a2d4ec5 Fri, Dec 3 2021 16:46:27.289, peer=0, tc=6, 160 mintc=3, offset=+0.000000, frequency=+0.000, sys_jitter=0.000060, 161 clk_jitter=0.000, clk_wander=0.000</code></pre> 162 <p>Donde debe buscar el código leap de tal forma que:</p> 163 <pre><code>Code Message Description 164 ----------------------------------------------------------------------- 165 0 leap_none normal synchronized state 166 1 leap_add_sec insert second after 23:59:59 of the current day 167 2 leap_del_sec delete second 23:59:59 of the current day 168 3 leap_alarm never synchronized</code></pre> 169 <p>Sincronizar manualmente el reloj del sistema con NTP -omitiendo las desviaciones grandes entre UTC local y UTC de red- mediante ntpd y después pasar el horario UTC obtenido al reloj hardware del clock, es tal que:</p> 170 <pre><code># ntpd -qg 171 [sudo] password for balon: 172 9 Dec 09:25:05 ntpd[3196]: ntpd 4.2.8p15@1.3728-o Wed Jul 1 17:02:17 UTC 2020 (1): Starting 173 9 Dec 09:25:05 ntpd[3196]: Command line: ntpd -qg 174 9 Dec 09:25:05 ntpd[3196]: ---------------------------------------------------- 175 9 Dec 09:25:05 ntpd[3196]: ntp-4 is maintained by Network Time Foundation, 176 9 Dec 09:25:05 ntpd[3196]: Inc. (NTF), a non-profit 501(c)(3) public-benefit 177 9 Dec 09:25:05 ntpd[3196]: corporation. Support and training for ntp-4 are 178 9 Dec 09:25:05 ntpd[3196]: available at https://www.nwtime.org/support 179 9 Dec 09:25:05 ntpd[3196]: ---------------------------------------------------- 180 9 Dec 09:25:05 ntpd[3196]: proto: precision = 0.186 usec (-22) 181 9 Dec 09:25:05 ntpd[3196]: basedate set to 2020-06-19 182 9 Dec 09:25:05 ntpd[3196]: gps base set to 2020-06-21 (week 2111) 183 9 Dec 09:25:05 ntpd[3196]: Listen and drop on 0 v6wildcard [::]:123 184 9 Dec 09:25:05 ntpd[3196]: Listen and drop on 1 v4wildcard 0.0.0.0:123 185 9 Dec 09:25:05 ntpd[3196]: Listen normally on 2 lo 127.0.0.1:123 186 9 Dec 09:25:05 ntpd[3196]: Listen normally on 3 wlo1 192.168.0.143:123 187 9 Dec 09:25:05 ntpd[3196]: Listen normally on 4 tun0 172.16.0.75:123 188 9 Dec 09:25:05 ntpd[3196]: Listen normally on 5 lo [::1]:123 189 9 Dec 09:25:05 ntpd[3196]: Listen normally on 6 wlo1 [fdd9:cbf6:173c::ced]:123 190 9 Dec 09:25:05 ntpd[3196]: Listen normally on 7 wlo1 [fdd9:cbf6:173c:0:51f5:b559:1c03:c0b2]:123 191 9 Dec 09:25:05 ntpd[3196]: Listen normally on 8 wlo1 [fe80::3b09:cd24:2c89:1e1c%3]:123 192 9 Dec 09:25:05 ntpd[3196]: Listen normally on 9 tun0 [fe80::1180:2123:b7da:b824%4]:123 193 9 Dec 09:25:05 ntpd[3196]: Listening on routing socket on fd #26 for interface updates 194 9 Dec 09:25:00 ntpd[3196]: ntpd: time set -12.974225 s 195 ntpd: time set -12.974225s 196 197 # hwclock --systohc</code></pre> 198 </body> 199 </html>