
Essa tarefa trivial surgiu em uma das sextas-feiras e deveria levar de 2 a 3 minutos. No geral, como sempre.
Um colega pediu para corrigir um script no servidor dele. Fiz, entreguei a ele e deixei escapar: "O tempo está adiantado em 5 minutos". O servidor dele, que se vire com a sincronização. Meia hora, uma hora se passou, e ele ainda está lá, suando e xingando baixinho.
"Idiota!" — pensei, mudando para o console. servidor — bem, vou me deter por mais alguns minutos.
Vamos ver, ntp, rdate, sdwdate não estão instalados, timesyncd está desativado e não iniciado.
# 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
Aqui, já vou notar que o tempo de hardware está correto: isso facilitará a referência posteriormente.
Daqui começaram uma série de erros.
Erro um. Autoconfiança
Clique, clique…
# 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
Tudo ótimo, o tempo sincronizou, o tempo do sistema coincide com o de hardware. "Leve", - deixei escapar e voltei ao que estava fazendo.
"O que levar?" — se indignou o colega. — "O tempo é o mesmo!"
Quanto mais você resolve tarefas típicas, mais sua mente fica estreita e você não pensa que a centésima ou milésima situação será diferente, mas não desta vez.
# 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
O tempo do sistema novamente está incorreto.
Vamos tentar novamente:
# 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
Vamos fazer diferente:
# 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 assim:
# 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 é definido em uma fração de segundo e logo começa a "adiantar" novamente.
Neste momento, nos logs, na ocasião de tal alteração manual, vemos apenas relatórios do sistema, de que o tempo mudou, respectivamente em direções corretas/incorretas e ocasionalmente Resincronizando do systemd-timesyncd.
25 de ago 21:18:51 wisi systemd[1]: O tempo foi alterado
25 de ago 21:18:51 wisi systemd-timesyncd[29258]: O tempo do sistema foi alterado. Resincronizando.
25 de ago 21:18:51 wisi systemd[1187]: O tempo foi alterado
25 de ago 21:18:51 wisi systemd[1]: O tempo foi alterado
25 de ago 21:18:51 wisi systemd[1187]: O tempo foi alterado
aqui
# ps afx | grep "[1]187"
1187 ? Ss 0:02 /lib/systemd/systemd --user
Nesse momento, já era preciso procurar a causa, mas o cérebro, após 18 anos de administração, já acumulou a estatística dos erros de "tempo" e, por hábito, culpa novamente a sincronização.
Desconectamos completamente.
# 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 logs
25 de ago 21:25:40 wisi systemd[1]: O tempo foi alterado
25 de ago 21:25:40 wisi systemd[1187]: O tempo foi alterado
25 de ago 21:29:30 wisi systemd[1]: O tempo foi alterado
25 de ago 21:29:30 wisi systemd[1187]: O tempo foi alterado
Resincronizando desapareceu e os demais logs estão imaculadamente limpos.
Verificamos as saídas tcpdump pelo porta 123 em todas as interfaces. Não há nenhuma solicitação, mas o tempo ainda assim "foge".
Erro dois. Pressa
Faltam apenas uma hora até o fim da semana de trabalho, e eu não quero sair para o fim de semana com uma tarefa não resolvida (não preste atenção ao tempo no código, o artigo foi escrito nos dias seguintes).
E aqui novamente, em vez de buscar a causa, comecei a tentar criar uma explicação para o resultado. Digo 'criar', porque apesar de as explicações do resultado serem lógicas, essa é uma abordagem errônea para resolver o problema.
Este servidor é de streaming e converte o fluxo DVB-S2 em IP. No fluxo DVB-S, existem marcas de tempo, portanto receptores, multiplexadores, descrambadores e TVs frequentemente as utilizam para sincronizar os relógios do sistema. Os drivers das placas DVB-S estão compilados no kernel, portanto a maneira mais rápida de remover garantidamente o fluxo DVB-S2 é desconectar os cabos que vão das 'antenas'. Felizmente, o servidor está do outro lado da parede, então assim deve ser.
Claro, se os logs contivessem o que deveriam, isso não teria acontecido, mas sobre isso, novamente, no final do artigo.
Bem, uma vez que já removemos todos os sinais de satélite, vamos remover também os terrestres — ao mesmo tempo, desconectamos todos os cabos de rede. O servidor fica isolado do mundo externo e opera de forma absolutamente autônoma, mas os relógios do sistema ainda avançam.
A semana de trabalho terminou, e a questão da data/hora não é crítica, portanto posso simplesmente ir para casa, mas aqui cometo um novo erro.
Erro três. Conselheiros.
Nunca! Nunca faça perguntas em fóruns e sites especializados (como o Stack Overflow) se a resposta exigir mais do que estudar os resultados da primeira página do Google e ler uma página do manual.
Você será enviado de volta ao Google, para ler aquele mesmo manual e receberá explicações populares sobre as regras do fórum/site, mas não receberá a resposta.
Aqui existem tanto fatores objetivos:
- ninguém além de você pode entender o problema tão bem;
- ninguém pode realizar testes nas mesmas condições que você;
quanto fatores subjetivos:
- você pode não fornecer todas as informações necessárias para a resolução do problema, porque já придумou uma 'direção correta' e baseia a essência da pergunta nele;
- o sargento (moderador, veterano, admin) sempre está certo, se o sargento estiver errado... bem, você sabe...
Se ao responder a comentários você se manteve dentro dos limites da linguagem adequada, então você tem nervos fortes.
Solução
Não é necessário dividir as tarefas em simples e complexas.
Vamos parar de confiar em nossa experiência, estatísticas, conselheiros e começar a não 'explicar' o resultado final, mas buscar a causa de forma sequencial.
Se alguém está definindo o tempo, deve ocorrer a chamada do sistema correspondente.
Assim como na documentação do software os melhores documentos são os códigos-fonte, na administração de sistemas o melhor auxiliar é a auditoria, neste caso. auditd.
Um momento de dúvidaRevisei os manuais, mas não estava completamente certo de que o tempo no Linux poderia ser configurado apenas por clock_settime e settimeofday, então para o primeiro teste escolhi todas as chamadas 'adequadas':
# 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 não reconheci, eu inicialmente inicie a auditoria na forma de: auditctl 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
Certificando-me de que não havia outrassyscalls além desses dois, utilizei apenas eles. Iniciamos a auditoria das chamadas de sistema
e tentamos mudar a data: clock_settime e settimeofday Uma pausa de cinco segundos foi adicionada para que nosso 'parasita' garantisse a correção do tempo.
# auditctl -a exit,always -S clock_settime -S settimeofday && date -s "2019-08-22 12:10:00" && sleep 5 && auditctl -D
Vejamos o relatório:
Aqui vemos nosso
# 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
e desconhecido para nós date chkcache_proces . Ele apareceu no relatório acima, pois o aureport ordenou a saída pela data ao converter de formato binário, e o evento ocorreu na hora que configuramosdate -s '2019-08-22 12:10:00' Quem o originou?.
— nosso parasita foi encontrado. Apesar de seu comportamento 'malicioso', não podemos nos desfazer do sistema de acesso condicional, mas ainda assim gostaríamos de saber,
# 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 oscam , WTF?A resposta foi rapidamente encontrada em
Como este trecho se apresenta tão bonitinho :
#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");
}
linhas comentadas de warning Essa tarefa trivial surgiu em uma das sextas-feiras. 🥇 Quanto mais simples a tarefa, mais frequentemente erro | ProHoster…
Fonte: habr.com
