Canto máis sinxela é a tarefa, máis veces cometo erros

Canto máis sinxela é a tarefa, máis veces cometo erros

Esta tarefa trivial xurdiu un venres pola tarde e debería levar 2-3 minutos de tempo. En xeral, coma sempre.

Un compañeiro pediume que corrixese o script no seu servidor. Fíxeno, entreguello e sen querer dixen: "O tempo é rápido 5 minutos". Deixa que o servidor se encargue da propia sincronización. Media hora, pasou unha hora, e aínda insuflou e maldixo en silencio.

"Estúpido! - Pensei, cambiando á consola do servidor - vale, vou facer un descanso un par de minutos máis.

Vexamos ntp, rdate, sdwdate non instalado sincronización de tempos desactivado e sen executar.

# timedatectl
      Local time: Sun 2019-08-25 20:44:39 +03
  Universal time: Sun 2019-08-25 17:44:39 UTC
        RTC time: Sun 2019-08-25 17:39:52
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Aquí notarei inmediatamente que a hora do hardware é correcta: será máis fácil navegar máis.

Aquí comezou a serie de erros.

O primeiro erro. Confianza nun mesmo

Clic-clac...

# systemctl enable systemd-timesyncd.service && systemctl start systemd-timesyncd.service && ntpdate 0.ru.pool.ntp.org && timedatectl set-ntp on && timedatectl
25 Aug 21:00:10 ntpdate[28114]: adjust time server 195.210.189.106 offset -249.015251 sec
      Local time: Sun 2019-08-25 21:00:10 +03
  Universal time: Sun 2019-08-25 18:00:10 UTC
        RTC time: Sun 2019-08-25 18:00:10
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

Todo está ben, a hora está sincronizada, a hora do sistema coincide coa do hardware. "Tómao", dixen e volvín ao meu negocio.

"Levar que? - indignouse o compañeiro. "É o mesmo tempo!"

Canto máis resolvas problemas típicos, máis parpadea o teu pensamento e xa non pensas que a situación centésima ou milésima será diferente, pero esta vez non.

# timedatectl
      Local time: Sun 2019-08-25 21:09:15 +03
  Universal time: Sun 2019-08-25 18:09:15 UTC
        RTC time: Sun 2019-08-25 18:05:04
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

A hora do sistema volve ser incorrecta.

Imos tentalo de novo:

# ntpdate 0.ru.pool.ntp.org && timedatectl && sleep 1 && timedatectl
25 Aug 21:07:37 ntpdate[30350]: step time server 89.175.20.7 offset -249.220828 sec
      Local time: Sun 2019-08-25 21:07:37 +03
  Universal time: Sun 2019-08-25 18:07:37 UTC
        RTC time: Sun 2019-08-25 18:07:37
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:11:46 +03
  Universal time: Sun 2019-08-25 18:11:46 UTC
        RTC time: Sun 2019-08-25 18:07:37
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

Imos facelo doutro xeito:

# date -s "2019-08-25 21:10:30" && date && sleep 1 && timedatectl
Sun Aug 25 21:10:30 +03 2019
Sun Aug 25 21:10:30 +03 2019
      Local time: Sun 2019-08-25 21:14:36 +03
  Universal time: Sun 2019-08-25 18:14:36 UTC
        RTC time: Sun 2019-08-25 18:10:30
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

E así:

# hwclock --hctosys && timedatectl && sleep 1 && timedatectl
      Local time: Sun 2019-08-25 21:11:31 +03
  Universal time: Sun 2019-08-25 18:11:31 UTC
        RTC time: Sun 2019-08-25 18:11:31
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:15:36 +03
  Universal time: Sun 2019-08-25 18:15:36 UTC
        RTC time: Sun 2019-08-25 18:11:32
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

O tempo está configurado para unha fracción de segundo e inmediatamente comeza a "precipitarse" de novo.

Ao mesmo tempo, nos rexistros, no momento de tal cambio manual, só vemos informes do sistema que indican que a hora cambiou, respectivamente, na dirección correcta/incorrecta e ocasionalmente Resincronización desde systemd-timesyncd.

Aug 25 21:18:51 wisi systemd[1]: Time has been changed
Aug 25 21:18:51 wisi systemd-timesyncd[29258]: System time changed. Resyncing.
Aug 25 21:18:51 wisi systemd[1187]: Time has been changed
Aug 25 21:18:51 wisi systemd[1]: Time has been changed
Aug 25 21:18:51 wisi systemd[1187]: Time has been changed

aquí

# ps afx | grep "[1]187"
 1187 ?        Ss     0:02 /lib/systemd/systemd --user

Neste punto, xa había que buscar o motivo, pero ao longo de 18 anos de administración, o cerebro acumulou estatísticas sobre erros "de tempo" e, por costume, volve culpar á sincronización.
Imos apagalo por completo.

# timedatectl set-ntp off && systemctl stop systemd-timesyncd.service
# hwclock --hctosys && timedatectl && sleep 1 && timedatectl
      Local time: Sun 2019-08-25 21:25:40 +03
  Universal time: Sun 2019-08-25 18:25:40 UTC
        RTC time: Sun 2019-08-25 18:25:40
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a
      Local time: Sun 2019-08-25 21:29:31 +03
  Universal time: Sun 2019-08-25 18:29:31 UTC
        RTC time: Sun 2019-08-25 18:25:41
       Time zone: Europe/Minsk (+03, +0300)
     NTP enabled: no
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a

e nos rexistros

Aug 25 21:25:40 wisi systemd[1]: Time has been changed
Aug 25 21:25:40 wisi systemd[1187]: Time has been changed
Aug 25 21:29:30 wisi systemd[1]: Time has been changed
Aug 25 21:29:30 wisi systemd[1187]: Time has been changed

Resincronización desapareceu e, se non, os troncos están prístinos.

Comprobación das conclusións tcpdump no porto 123 en todas as interfaces. Non hai solicitudes, pero o tempo segue correndo.

Erro dous. Rush

Queda unha hora para que remate a semana laboral, e non quero marchar a fin de semana cun problema sen resolver (non fagades caso da hora do código, o artigo foi escrito nos días seguintes). ).
E aquí de novo, en lugar de buscar o motivo, comecei a tentar dar unha explicación ao resultado. Digo "inventar" porque por moi lóxica que sexa a explicación do resultado, é un enfoque defectuoso para resolver o problema.

Este servidor é un servidor de streaming e converte o fluxo DVB-S2 en IP. O fluxo DVB-S contén marcas de tempo, polo que os receptores, multiplexadores, codificadores e televisores adoitan usalas para sincronizar o reloxo do sistema. Os controladores da placa DVB-S están integrados no núcleo, polo que a forma máis rápida de asegurarse de que se elimine o fluxo DVB-S2 é desconectar os cables que veñen das "placas". Afortunadamente, o servidor está detrás da parede, así sexa.

Por suposto, se os rexistros contivesen o que debería haber, isto non sucedería, pero máis sobre iso, de novo, ao final do artigo.

Ben, xa que xa eliminamos todos os sinais de satélite, tamén eliminaremos os terrestres; ao mesmo tempo, retiramos todos os cables de rede. O servidor queda separado do mundo exterior e funciona de forma completamente autónoma, pero o reloxo do sistema aínda ten présa.

A semana laboral rematou e o problema de data/hora en si non é crítico, así que podes volver a casa, pero aquí cometo un novo erro.

Erro tres. Asesores

Nunca! Nunca fagas preguntas en foros e sitios xerais especializados (a la stackoverflow) se a resposta a ela require máis que estudar a primeira páxina de Google e ler unha páxina de manual.

Enviarano de volta a Google, lerán ao mesmo home e explicarán popularmente as regras do foro/sitio, pero non che darán resposta.

Aquí están algúns factores obxectivos:

  • ninguén, excepto ti, tamén pode coñecer o problema;
  • ninguén pode realizar probas nas mesmas condicións que a túa

e subxectiva:

  • pode que non deas todos os aportes para resolver o problema, porque xa deches a dirección "correcta" e estás presentando a esencia do problema centrándoo nel;
  • o capataz (moderador, veterano, administrador) sempre ten razón, se o capataz se equivoca... ben, xa sabes...

Se, ao responder aos comentarios, permaneceches dentro dos límites do vocabulario censurado, entón tes nervios fortes.

decisión

Non é necesario dividir as tarefas en sinxelas e complexas.

Deixamos de confiar na nosa experiencia, estatísticas, asesores e comezamos a non "explicar" o resultado final, senón a buscar constantemente o motivo.

Dado que alguén establece a hora, debe producirse a correspondente chamada ao sistema.

Do mesmo xeito que na documentación de software os mellores documentos son as fontes, así na administración do sistema o mellor asistente é a auditoría, no noso caso. auditord.

Un momento de dúbidaPasei polo mana, pero non estaba totalmente seguro de que a hora en Linux só se pode configurar clock_settime и hora fixada do día, así que para a primeira proba escollín todas as chamadas "adecuadas":

# man syscalls | col | grep -F '(2)' | grep -vE '(:|;)' | grep -E '(time|date|clock)' | sed "s/(2).*//" | xargs -I SYSCALL echo "-S SYSCALL " | xargs echo
-S adjtimex -S clock_adjtime -S clock_getres -S clock_gettime -S clock_nanosleep -S clock_settime -S futimesat -S getitimer -S gettimeofday -S mq_timedreceive -S mq_timedsend -S rt_sigtimedwait -S s390_runtime_instr -S setitimer -S settimeofday -S stime -S time -S timer_create -S timer_delete -S timer_getoverrun -S timer_gettime -S timer_settime -S timerfd_create -S timerfd_gettime -S timerfd_settime -S times -S utime -S utimensat -S utimes

e descartando s390_runtime_instr, stime, timerfd_create, que auditorctl non o recoñeceu, inicialmente lanzou unha auditoría na forma:

auditctl -a exit,always -S adjtimex -S clock_adjtime -S clock_getres -S clock_nanosleep -S clock_settime -S futimesat -S getitimer -S gettimeofday -S mq_timedreceive -S mq_timedsend -S rt_sigtimedwait -S semtimedop -S setitimer -S settimeofday -S time -S timer_create -S timer_delete -S timer_getoverrun -S timer_gettime -S timer_settime -S timerfd_gettime -S timerfd_settime -S times -S utime -S utimensat -S utimes

Despois de asegurarme de que non hai outros rexistros nas localizacións de rexistro que me interesan syscalls Ademais destes dous, só os usei máis.

Execución dunha auditoría de chamadas ao sistema clock_settime и hora fixada do día e tenta cambiar a data:

# auditctl -a exit,always -S clock_settime -S settimeofday && date -s "2019-08-22 12:10:00" && sleep 5 && auditctl -D

Engádese un atraso de cinco segundos para que o noso "parasito" teña garantía de corrixir o tempo.

Vexamos o informe:

# aureport -s -i

Syscall Report
=======================================
# date time syscall pid comm auid event
=======================================
Warning - freq is non-zero and incremental flushing not selected.
1. 08/22/2019 12:10:00 settimeofday 3088 chkcache_proces root 479630
2. 08/26/2019 09:37:06 clock_settime 1538 date root 479629

Aquí vemos o noso data e descoñecido para nós chkcache_proceses. Acabou no informe anterior porque aureport ordenou a saída por data ao converterse en binario e o evento ocorreu no momento en que definimos data -s "2019/08/22 12:10:00".
Quen o pariu?

# ausearch -sc settimeofday --comm "chkcache_proces"
----
time->Thu Aug 22 12:10:00 2019
type=PROCTITLE msg=audit(1566465000.000:479630): proctitle="/usr/local/bin/oscam"
type=SYSCALL msg=audit(1566465000.000:479630): arch=c000003e syscall=164 success=yes exit=0 a0=7fde0dfc6e60 a1=0 a2=136cf a3=713ba56 items=0 ppid=3081 pid=3088 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts20 ses=68149 comm="chkcache_proces" exe="/usr/local/bin/oscam" key=(null)

/usr/local/bin/oscam -O noso parasito foi atopado. A pesar do seu comportamento "malicioso", é imposible rexeitar o sistema de acceso condicional, pero aínda así gustaríame saber oscam, WTF?

A resposta atópase rapidamente en códigos fonte:

#if defined(CLOCKFIX)
if (tv.tv_sec > lasttime.tv_sec || (tv.tv_sec == lasttime.tv_sec && tv.tv_usec >= lasttime.tv_usec)) // check for time issues!
{
  lasttime = tv; // register this valid time
}
  else
{
  tv = lasttime;
  settimeofday(&tv, NULL); // set time back to last known valid time
  //fprintf(stderr, "*** WARNING: BAD TIME AFFECTING WHOLE OSCAM ECM HANDLING, SYSTEMTIME SET TO LAST KNOWN VALID TIME **** n");
}

Que bonito se ve aquí comentou fóra liña Aviso...

Fonte: www.habr.com

Engadir un comentario