
Diese triviale Aufgabe entstand an einem der Freitagstage und hätte 2-3 Minuten dauern sollen. Im Allgemeinen wie immer.
Ein Kollege hat mich gebeten, das Skript auf seinem Server zu reparieren. Er tat es, gab es ihm und ließ es versehentlich fallen: "Die Zeit hat es 5 Minuten lang eilig." Sein Server, auch wenn er Synchronisation versteht. Eine halbe Stunde, eine Stunde ist vergangen, und er pustet und schwört leise.
„Durcheinander! - Ich dachte, ich würde zur Serverkonsole wechseln - nun, ich werde noch ein paar Minuten warten. “
Wir sehen,
ntp, rdate, sdwdate sind nicht installiert,
timesyncd ist deaktiviert und läuft nicht.
# 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
Hier stelle ich sofort fest, dass die Hardwarezeit korrekt ist: Es wird einfacher sein, weiter darauf zu navigieren.
Von hier aus begann eine Reihe von Fehlern.
Erster Fehler. Selbstvertrauen
Klats-klats ...
# 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
Alles ist in Ordnung, die Zeit wurde synchronisiert, das System stimmt mit der Hardware überein. „Nimm es“, ließ ich mich fallen und kehrte zu meinem Geschäft zurück.
"Was zum Mitnehmen?" - Der Kollege war empört. "Die alte Zeit!"
Je mehr Sie typische Probleme lösen, desto mehr beginnt Ihr Denken und Sie glauben nicht, dass die hundertste oder tausendste Situation anders sein wird, aber diesmal nicht.
# 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
Die Systemzeit ist wieder falsch.
Versuchen wir es noch einmal:
# 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
Lass es uns anders machen:
# 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
Und so:
# 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
Die Zeit wird für den Bruchteil einer Sekunde eingestellt und beginnt dann wieder zu "rasen".
Darüber hinaus sehen wir in den Protokollen zum Zeitpunkt einer solchen manuellen Änderung nur die Systemberichte, dass sich die Zeit in die richtige / falsche Richtung geändert hat, und gelegentlich
Resyncing von 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
hier
# ps afx | grep "[1]187" 1187 ? Ss 0:02 /lib/systemd/systemd --user
Zu diesem Zeitpunkt war es bereits notwendig, nach der Ursache zu suchen, aber das Gehirn hat seit 18 Jahren Statistiken über Fehler der "Zeit" erstellt und aus Gewohnheit erneut die Synchronisation beschuldigt.
Schalten Sie es vollständig aus.
# 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
und in den Protokollen
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
Das erneute Synchronisieren ist weg und der Rest der Protokolle ist makellos.
Wir überprüfen die
tcpdump- Ausgaben am 123. Port aller Schnittstellen. Es gibt keine Anfragen, aber die Zeit läuft auch davon.
Der zweite Fehler. Eile
Es bleibt noch eine Stunde bis zum Ende der Arbeitswoche, aber Sie möchten nicht mit einer schlechten Aufgabe für das Wochenende abreisen (achten Sie nicht auf die Zeit im Code, der Artikel wurde in den folgenden Tagen geschrieben).
Und auch hier versuchte ich, anstatt nach einem Grund zu suchen, eine Erklärung für das Ergebnis zu finden. Ich sage „erfinden“, denn egal wie logisch die Erklärungen für das Ergebnis sind, dies ist ein fehlerhafter Ansatz zur Lösung des Problems.
Dieser Server streamt und konvertiert den DVB-S2-Stream in IP. Der DVB-S-Stream enthält Zeitstempel, sodass Empfänger, Multiplexer, Scrambler und Fernseher diese häufig zum Synchronisieren der Systemuhr verwenden. Treiber für DVB-S-Karten sind im Kernel kompiliert. Der schnellste Weg, um einen sauberen DVB-S2-Stream zu gewährleisten, besteht darin, die Kabel von den "Platten" zu trennen. Glücklicherweise befindet sich der Server also hinter der Mauer.
Wenn die Protokolle das hätten, was dort sein sollte, wäre dies natürlich nicht geschehen, aber dazu am Ende des Artikels noch einmal.
Nun, da wir bereits alle Satellitensignale gelöscht haben, werden wir auch terrestrische entfernen - auf dem Weg ziehen wir alle Netzwerkkabel heraus. Der Server wird von der Außenwelt abgeschnitten und arbeitet völlig autonom, aber die Systemuhr hat es immer noch eilig.
Die Arbeitswoche ist vorbei und die Frage nach Datum und Uhrzeit ist nicht kritisch, so dass Sie einfach nach Hause gehen können, aber hier mache ich einen neuen Fehler.
Der dritte Fehler. Berater
Niemals! Stellen Sie niemals Fragen in Foren und allgemein spezialisierten Websites (a la stackoverflow), wenn die Antwort darauf mehr erfordert, als die Ausgabe der ersten Seite von Google zu studieren und eine Seite von man'a zu lesen.
Sie werden zurück zu Google geschickt, lesen denselben Mann und erklären im Volksmund die Regeln des Forums / der Website, geben aber keine Antwort.
Es gibt beide objektiven Faktoren:
- niemand außer Ihnen kann das Problem auch kennen;
- Niemand kann unter den gleichen Bedingungen wie Sie testen
und subjektiv:
- Möglicherweise geben Sie nicht alle Eingaben zur Lösung des Problems heraus, da Sie bereits die „richtige“ Richtung gefunden haben und das Wesentliche des Problems darlegen, indem Sie sich darauf ausruhen.
- Vorarbeiter (Moderator, Oldtimer, Administrator) hat immer Recht, wenn der Vorarbeiter Unrecht hat ... na ja, wissen Sie ...
Wenn Sie als Reaktion auf Kommentare im Rahmen des Zensurvokabulars geblieben sind, haben Sie starke Nerven.
Lösung
Sie müssen Aufgaben nicht in einfache und komplexe Aufgaben unterteilen.
Wir verlassen uns nicht mehr auf unsere Erfahrungen, Statistiken und Berater und beginnen nicht, das Endergebnis zu „erklären“, sondern konsequent nach dem Grund zu suchen.
Sobald jemand die Zeit eingestellt hat, sollte ein entsprechender Systemaufruf erfolgen.
Wie in der Dokumentation der Software sind die Quellen die besten Docks. In der Systemadministration ist der beste Assistent das Audit, in unserem Fall
auditd .
Moment des ZweifelsIch habe den Mans durchlaufen, war mir aber nicht ganz sicher, ob die Uhr unter Linux nur durch
clock_settime und
settimeofday eingestellt werden kann. Für den ersten Test habe ich alle „geeigneten“ Aufrufe ausgewählt:
# 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
und das Verwerfen von
s390_runtime_instr, stime, timerfd_create , das
auditctl nicht erkannte, startete das Audit zunächst in der folgenden Form:
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
Nachdem ich sichergestellt habe, dass an den Stellen der Protokolle, die mich interessieren, keine anderen
Systemaufrufe als diese beiden vorhanden sind, habe ich nur diese verwendet.
Wir starten die Prüfung der Systemaufrufe
clock_settime und
settimeofday und versuchen, das Datum zu ändern:
# auditctl -a exit,always -S clock_settime -S settimeofday && date -s "2019-08-22 12:10:00" && sleep 5 && auditctl -D
Eine Verzögerung von fünf Sekunden wurde hinzugefügt, damit unser „Parasit“ garantiert die Zeit korrigiert.
Wir schauen uns den Bericht an:
# 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
Hier sehen wir unser
Datum und uns unbekannt
chkcache_proces . Es stellte sich heraus, dass dies im obigen Bericht enthalten ist, da aureport die Ausgabe beim Konvertieren aus der Binäransicht nach Datum sortierte und das Ereignis zu dem Zeitpunkt auftrat, als wir das
Datum "2019-08-22 12:10:00" festlegten .
Wer hat ihn geboren?
# 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 - unser Parasit wurde gefunden. Trotz seines "böswilligen" Verhaltens ist es unmöglich, das bedingte Zugriffssystem aufzugeben, aber ich würde trotzdem gerne wissen,
oscam , WTF?
Die Antwort ist schnell in der
Quelle zu finden :
#if defined(CLOCKFIX) if (tv.tv_sec > lasttime.tv_sec || (tv.tv_sec == lasttime.tv_sec && tv.tv_usec >= lasttime.tv_usec))
Wie schön sieht
die auskommentierte Warnzeile hier aus ...