Cron-Ausdrücke Best Practices: Von Fallstricken bis Produktion
Dienstprogramme赵婉清
Cron-Ausdrücke: 5 Felder zur Zeitsteuerung
┌───────── Minute (0-59)
│ ┌───────── Stunde (0-23)
│ │ ┌───────── Tag (1-31)
│ │ │ ┌───────── Monat (1-12)
│ │ │ │ ┌───────── Wochentag (0-7, 0 und 7 sind Sonntag)
│ │ │ │ │
* * * * *
I. Syntax-Schnellreferenz
| Ausdruck | Bedeutung | Ausführungshäufigkeit |
|---|---|---|
* * * * * |
Jede Minute | 1440 Mal/Tag |
*/5 * * * * |
Alle 5 Minuten | 288 Mal/Tag |
0 * * * * |
Jede volle Stunde | 24 Mal/Tag |
0 9 * * * |
Täglich um 9:00 | 1 Mal/Tag |
0 9 * * 1-5 |
Werktags um 9:00 | 5 Mal/Woche |
30 2 1 * * |
Am 1. jedes Monats um 2:30 | 1 Mal/Monat |
0 0 1 1 * |
Am 1. Januar um 0:00 | 1 Mal/Jahr |
Sonderzeichen
| Zeichen | Bedeutung | Beispiel |
|---|---|---|
* |
Beliebiger Wert | * * * * * |
, |
Aufzählung | 0 9,12,18 * * * (9/12/18 Uhr) |
- |
Bereich | 0 9-17 * * 1-5 (Werktags 9-17 Uhr) |
/ |
Schrittweite | */15 * * * * (alle 15 Minuten) |
L |
Letzter | 0 0 L * * (letzter Tag des Monats) |
W |
Nächster Werktag | 0 0 1W * * (nächster Werktag zum 1.) |
# |
N-ter Wochentag | 0 0 * * 5#3 (dritter Freitag) |
II. Häufige Fallstricke
Fallstrick 1: Tag und Wochentag gleichzeitig angeben
# Falsches Verständnis: Am 15. jedes Monats UND an einem Freitag
0 0 15 * 5
# Tatsächliche Bedeutung: Am 15. jedes Monats ODER jeden Freitag (Vereinigung!)
# Korrekte Schreibweise erfordert zusätzliche Logik
Regel: Wenn Tag und Wochentag gleichzeitig angegeben werden, wird die Vereinigung genommen, nicht die Schnittmenge.
Fallstrick 2: Zeitzonenprobleme
# Erwartet: Ausführung um 9:00 Peking-Zeit
0 9 * * *
# Server in UTC-Zeitzone → tatsächliche Ausführung um 17:00 Peking-Zeit!
# Lösung: Zeitzone explizit angeben
// node-cron Zeitzone angeben
cron.schedule('0 9 * * *', task, {
scheduled: true,
timezone: 'Asia/Shanghai',
});
Fallstrick 3: 60-Sekunden-Schreibfehler
# Falsch: Das Minutenfeld hat keine 60
0 0 60 * * *
# Richtig: Jede Stunde ausführen
0 * * * *
Fallstrick 4: 30. Februar
# Februar hat keinen 30., dieser Ausdruck wird im Februar nicht ausgeführt
0 0 30 2 *
Fallstrick 5: Sommerzeit
Bei der Sommerzeitumstellung können bestimmte Zeiten nicht existieren oder doppelt vorkommen:
Frühling vorstellen: 2:00 → 3:00 (2:30 existiert nicht)
Herbst zurückstellen: 2:00 → 1:00 (1:30 wird zweimal ausgeführt)
Empfehlung: UTC-Zeitzone verwenden, um Sommerzeitprobleme zu vermeiden.
III. Cron-Ausdrücke mit ToolsKu verifizieren
Bedienungsschritte
- Öffnen Sie das Cron-Ausdruck-Tool
- Geben Sie den Cron-Ausdruck ein
- Lesen Sie die deutsche Interpretation:
0 9 * * 1-5→ "Montag bis Freitag um 09:00"*/30 8-18 * * *→ "Jeden Tag alle 30 Minuten von 08:00-18:00"
- Zeigen Sie die Liste der nächsten Ausführungen an (5-10 nächste)
- Überprüfen Sie, ob der Ausdruck gültig ist
IV. Produktionsreifes Design zeitgesteuerter Aufgaben
Nebenläufigkeitskontrolle
import { CronJob } from 'cron';
let isRunning = false;
const job = new CronJob('0 */5 * * * *', async () => {
if (isRunning) {
console.log('Vorherige Runde noch nicht abgeschlossen, diese Ausführung überspringen');
return;
}
isRunning = true;
try {
await processData();
} finally {
isRunning = false;
}
});
Verteilte Sperre (Multi-Instanz-Bereitstellung)
import { Redis } from 'ioredis';
const redis = new Redis();
async function acquireLock(key, ttl = 300) {
const acquired = await redis.set(key, '1', 'EX', ttl, 'NX');
return acquired === 'OK';
}
const job = new CronJob('0 2 * * *', async () => {
const lockKey = `cron:daily-report:${new Date().toISOString().slice(0, 10)}`;
if (!(await acquireLock(lockKey))) {
console.log('Andere Instanz hat die Sperre bereits, überspringen');
return;
}
try {
await generateDailyReport();
} finally {
await redis.del(lockKey);
}
});
Fehler-Wiederholung
async function runWithRetry(task, maxRetries = 3, delay = 5000) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await task();
} catch (error) {
console.error(`Versuch ${attempt} fehlgeschlagen:`, error.message);
if (attempt < maxRetries) {
await sleep(delay * attempt); // Inkrementelle Verzögerung
} else {
throw error;
}
}
}
}
const job = new CronJob('0 */10 * * * *', () => {
runWithRetry(syncData, 3, 5000);
});
Timeout-Kontrolle
async function runWithTimeout(task, timeoutMs = 60000) {
return Promise.race([
task(),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Aufgabe hat das Zeitlimit überschritten')), timeoutMs)
),
]);
}
V. Aufgabenüberwachung
Ausführungsprotokoll
const job = new CronJob('0 2 * * *', async () => {
const startTime = Date.now();
const context = { job: 'daily-sync', startedAt: new Date().toISOString() };
try {
await runWithRetry(syncData);
context.status = 'success';
} catch (error) {
context.status = 'failed';
context.error = error.message;
await sendAlert(context); // Warnung
} finally {
context.duration = Date.now() - startTime;
await logExecution(context); // Protokoll aufzeichnen
}
});
Gesundheitsprüfung
// Letzte erfolgreiche Ausführungszeit speichern
await redis.set('cron:last-success:daily-sync', Date.now());
// Gesundheitsprüfung: Wenn seit über 25 Stunden nicht ausgeführt, Warnung auslösen
const lastSuccess = await redis.get('cron:last-success:daily-sync');
if (Date.now() - lastSuccess > 25 * 3600 * 1000) {
await sendAlert({ type: 'cron_stale', job: 'daily-sync' });
}
VI. Häufige Muster zeitgesteuerter Aufgaben
| Anforderung | Cron-Ausdruck | Beschreibung |
|---|---|---|
| Stündliche Datensynchronisation | 0 * * * * |
Zur vollen Stunde |
| Werktags-Morgenbericht | 0 9 * * 1-5 |
Montag bis Freitag um 9:00 |
| Tägliche Sicherung | 0 2 * * * |
Um 2:00 Uhr nachts |
| Wöchentliche Bereinigung | 0 3 * * 0 |
Sonntags um 3:00 |
| Monatlicher Abgleich | 0 6 1 * * |
Am 1. jedes Monats um 6:00 |
| Heartbeat alle 15 Minuten | */15 * * * * |
Hochfrequenzprüfung |
| Quartalsbericht | 0 8 1 1,4,7,10 * |
Erster Tag des Quartalsmonats |
VII. Liste der Best Practices
- Immer UTC-Zeitzone verwenden, es sei denn, das Geschäft erfordert zwingend lokale Zeit
- Tag und Wochentag nicht gleichzeitig angeben, Vereinigungs-Falle vermeiden
- Nebenläufigkeitskontrolle: Nur eine Instanz führt zur gleichen Zeit aus
- Verteilte Sperre: Doppelte Ausführung bei Multi-Instanz-Bereitstellung verhindern
- Fehler-Wiederholung + Warnungen: Nicht stillschweigend fehlschlagen
- Timeout-Kontrolle: Verhindern, dass Aufgaben unbegrenzt hängen
- Idempotentes Design: Wiederholte Ausführung liefert gleiche Ergebnisse
- Ausführungsprotokoll: Zeit, Dauer und Status jeder Ausführung aufzeichnen
- Ausdrücke mit Tools verifizieren: Korrekte Semantik vor Bereitstellung bestätigen
#Cron#定时任务#crontab#时区#运维