Es ist eine plötzliche Frage, aber wie verwalten Sie die Jobs, die Sie regelmäßig ausführen? Selbst im Jahr 2018, wenn Serverless beliebt ist, gibt es möglicherweise einige Leute, die immer noch das altmodische "Cron" verwenden.
In diesem Artikel möchte ich eine Möglichkeit vorschlagen, einen Server, auf dem die Stapelverarbeitung ausgeführt wird, durch "cron" ohne Ausfallzeiten zu ersetzen. Außerdem möchte ich erklären, warum dies möglich ist, indem ich auf den Quellcode von "cron" schaue. (Aus Zeitgründen behandeln wir "cronie" nur auf "CentOS7".)
Im tatsächlichen Betrieb sollten Sie ein ordnungsgemäßes Jobverwaltungssystem entwerfen. In diesem Artikel wird jedoch eine schlammige Methode vorgestellt.
TL; DR
crond
gestoppt istcron
ist ein zeitbasierter Job Scheduler, der in UNIX-basierten Betriebssystemen verwendet wird und zum Planen regelmäßig ausgeführter Aufgaben geeignet ist. Es wird auch zur Systemverwaltung und zur Ausführung von Aufgaben tatsächlicher Dienste verwendet.
Wenn Sie beispielsweise einen Job wie den folgenden mit "crontab -e" registrieren, wird der Aggregationsstapel stündlich mit 0 Minuten ausgeführt.
0 * * * * /bin/bash -l -c '/home/vagrant/bin/execute_hourly_aggregation'
Weitere Informationen finden Sie in den folgenden Wikipedia-Artikeln und in den verschiedenen Dokumenten, die als Referenz dienen.
https://ja.wikipedia.org/wiki/Crontab
Bei dieser vorgeschlagenen Methode möchten wir in einer Umgebung, in der immer ein Stapel ausgeführt wird, beispielsweise einen Stapel, der lange dauert, oder eine große Anzahl von Stapeln, keine Ausfallzeiten verursachen.
Beachten Sie jedoch, dass die vorgeschlagene Methode auf einem Server, auf dem jede Minute neue Jobs gekickt werden, keine strikte Ausfallzeit von Null erreichen kann.
Ich werde in der folgenden Umgebung erklären, die in Vagrant eingerichtet wurde. Die Version unterscheidet sich geringfügig vom zu erklärenden Quellcode, es gibt jedoch keine wesentlichen Änderungen. Ich hoffe, Sie verstehen den Mechanismus.
[vagrant@localhost ~]$ cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[vagrant@localhost ~]$ yum list installed | grep cron
Failed to set locale, defaulting to C
cronie.x86_64 1.4.11-19.el7 @anaconda
cronie-anacron.x86_64 1.4.11-19.el7 @anaconda
crontabs.noarch 1.11-6.20121102git.el7 @anaconda
Bereiten wir zunächst einen neuen Server vor. Was die Dateistruktur betrifft, gibt es kein Problem mit der gleichen Dateistruktur wie der alte Server, aber bitte machen Sie es so, dass die folgenden beiden erfüllt sind.
Verwenden Sie beispielsweise in der CentOS7-Serie den Befehl service
, um sie zu stoppen.
[vagrant@localhost ~]$ sudo service crond stop
Redirecting to /bin/systemctl stop crond.service
[vagrant@localhost ~]$ service crond status
Redirecting to /bin/systemctl status crond.service
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Tue 2018-09-11 17:44:33 UTC; 11s ago
Process: 3406 ExecStart=/usr/sbin/crond -n $CRONDARGS (code=exited, status=0/SUCCESS)
Main PID: 3406 (code=exited, status=0/SUCCESS)
Warten Sie, bis die Cron-Jobs nicht mehr treten. Das Wichtigste dabei ist nicht, wann der Job abgeschlossen ist, sondern wann der Job nicht mehr gekickt wird. Schauen Sie sich den Prozess unter "crond" mit "ps aux f" usw. an und stellen Sie sicher, dass der letzte Batch-Prozess auf dem alten Server gestartet wurde.
root 3492 0.0 0.3 26096 1704 ? Ss 17:45 0:00 /usr/sbin/crond -n
root 3921 0.0 0.4 82144 2488 ? S 18:05 0:00 \_ /usr/sbin/CROND -n
vagrant 3924 0.0 0.3 12992 1568 ? Ss 18:05 0:00 | \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant 3937 0.0 0.0 7764 352 ? S 18:05 0:00 | | \_ sleep 120
Schließlich werden wir mit den Ersatzarbeiten fortfahren. Stoppen Sie zuerst "crond" auf dem alten Server und starten Sie "crond" auf dem neuen Server. Zu diesem Zeitpunkt startet der alte Server keine neuen Stapeloperationen mehr.
crond
hat aufgehört, aber es gibt immer noch Jobs, die crond
gekickt haben. Warten wir, bis der Stapelprozess abgeschlossen ist. Zu diesem Zeitpunkt hat der von crond
gekickte Job seinen Hauptelternteil verloren und hängt nun unter / usr / sbin / CROND
.
root 4199 0.0 0.4 82144 2488 ? S 18:18 0:00 /usr/sbin/CROND -n
vagrant 4201 0.0 0.3 12992 1564 ? Ss 18:18 0:00 \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant 4214 0.0 0.0 7764 352 ? S 18:18 0:00 | \_ sleep 120
Warten Sie, bis der endgültige Stapelprozess abgeschlossen ist, und hören Sie dann höflich auf.
Warum ist das möglich? Lassen Sie uns den Status des Prozesses zur Laufzeit erneut überprüfen, während wir den Cron-Code für einen Moment lesen.
Zuerst durchläuft "cron" den folgenden Vorgang "während", bis ein Signal von "SIGINT" oder "SIGTERM" empfangen wird.
while (!got_sigintterm) {
int timeDiff;
enum timejump wakeupKind;
/* ... wait for the time (in minutes) to change ... */
do {
cron_sleep(timeRunning + 1, &database);
set_time(FALSE);
} while (!got_sigintterm && clockTime == timeRunning);
if (got_sigintterm)
break;
timeRunning = clockTime;
// ~Unterlassung~
handle_signals(&database);
}
https://github.com/cronie-crond/cronie/blob/40b7164227a17058afb4f3d837ebb3263943e2e6/src/cron.c#L354-L481
Mit anderen Worten, Sie können sehen, dass der neue Stapel jede (ungefähr) Minute ausgeführt wird, in der diese Prüfung ausgeführt wird.
Der neue Stapel wird von "find_jobs ()" erkannt und als Nachkomme des ursprünglichen "crond" über "job_runqueue ()", "do_command ()", "child_process ()" ausgeführt.
root 3492 0.0 0.3 26096 1704 ? Ss 17:45 0:00 /usr/sbin/crond -n
root 3921 0.0 0.4 82144 2488 ? S 18:05 0:00 \_ /usr/sbin/CROND -n
vagrant 3924 0.0 0.3 12992 1568 ? Ss 18:05 0:00 | \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant 3937 0.0 0.0 7764 352 ? S 18:05 0:00 | | \_ sleep 120
Was passiert also, wenn Sie hier mit "SIGTERM" aufhören? Werfen wir einen Blick auf den Code für das letzte Reinigungsteil.
#if defined WITH_INOTIFY
if (inotify_enabled && (EnableClustering != 1))
set_cron_unwatched(fd);
if (fd >= 0 && close(fd) < 0)
log_it("CRON", pid, "INFO", "Inotify close failed", errno);
#endif
log_it("CRON", pid, "INFO", "Shutting down", 0);
(void) unlink(_PATH_CRON_PID);
return 0;
https://github.com/cronie-crond/cronie/blob/40b7164227a17058afb4f3d837ebb3263943e2e6/src/cron.c#L482-L495
Hast du bemerkt? Anstatt auf den Prozess des Kindes oder Enkels zu warten oder ihn zu töten, ist der Elternteil stillschweigend tot und beauftragt das Kind mit der Bearbeitung des Enkels.
root 4199 0.0 0.4 82144 2488 ? S 18:18 0:00 /usr/sbin/CROND -n
vagrant 4201 0.0 0.3 12992 1564 ? Ss 18:18 0:00 \_ /bin/bash -l -c echo "start at $(date)" && sleep 120 && echo "end at $(date)"
vagrant 4214 0.0 0.0 7764 352 ? S 18:18 0:00 | \_ sleep 120
Infolgedessen werden neue Jobs nicht gekickt, während bereits geknickte Jobs bis zum Ende abgeschlossen werden können. (Es ist ein wenig schmerzhaft)
Da "crond" sehr einfach implementiert ist, ist es möglich, es selbst bei einer groben Methode wie der vorgeschlagenen Methode durch keine Ausfallzeit zu ersetzen. Natürlich ist es im tatsächlichen Betrieb ein Bereich, der ordnungsgemäß systematisiert werden sollte, aber ich hoffe, dass Sie sich für das vertraute "Cron" interessieren.
Recommended Posts