English summary: Small, dependency-free Python tool that queries the Checkmk REST API and sends an SMTP mail when hosts in selected Checkmk folders have been DOWN/UNREACHABLE for longer than a per-folder threshold. Built for unattended operation on Windows Server (Task Scheduler + gMSA). Documentation is in German. MIT licensed, created with AI assistance - see AI-NOTICE.md.
Fragt Checkmk (REST-API, getestet mit 2.3.0p20) ab und verschickt eine SMTP-Mail, sobald Hosts in bestimmten Checkmk-Ordnern laenger als konfiguriert offline sind. Gedacht fuer den unbeaufsichtigten Betrieb auf einem Windows Server in der Aufgabenplanung unter einem gMSA-Konto.
- Pro Ordner eine eigene Zeitspanne (z. B. Produktion 30 Min., Aussenstellen 4 Std.)
- Filter auf Custom-Attribute: nur melden, wenn z. B.
ueberwachung = 24x7gesetzt ist - Eine Mail je Host (alternativ eine Sammelmail je Ordner oder eine Gesamtmail)
- Hostname, IP-Adresse und beliebige Custom-Attribute als Variablen in Betreff und Mailtext
- Zwei Konfigurationsdateien: Steuerung (
config.toml) und Mailinhalt (mailtemplate.toml) - Merkt sich versendete Meldungen - kein Mail-Spam bei jedem Lauf, optionale Erinnerung
- Ignoriert wahlweise Wartungszeiten, quittierte Stoerungen und stummgeschaltete Hosts
- Keine externen Python-Pakete noetig (nur Standardbibliothek)
| Windows | Server 2016 oder neuer |
| Python | 3.11 oder neuer, maschinenweit installiert ("Install for all users", z. B. C:\Program Files\Python313) - siehe Warnung in 2.2 |
| Ablage | ein frei waehlbarer Basisordner, z. B. C:\FIRMA\cmkoffline2mail |
| Checkmk | 2.3.x, erreichbar per HTTPS, Automationsbenutzer vorhanden |
| SMTP | Relay/Smarthost erreichbar (mit oder ohne Anmeldung) |
| AD | gMSA-Konto fuer die Aufgabenplanung |
Die gesamte Installation liegt in einem frei waehlbaren Basisordner. In dieser
Anleitung ist das C:\FIRMA\cmkoffline2mail - FIRMA steht dabei fuer Ihren
eigenen Ordnernamen. Programm, virtuelle Umgebung, Konfiguration, Status und
Protokolle liegen alle darunter:
C:\FIRMA\cmkoffline2mail\
├─ .venv\ virtuelle Python-Umgebung (Schritt 2.2)
├─ cmkoffline2mail\ Python-Paket (cli.py, config.py, checkmk.py, ...)
├─ config\ config.toml + mailtemplate.toml
├─ data\ state.json (wird angelegt)
├─ logs\ Protokolle (werden angelegt)
├─ deploy\ PowerShell-Skripte, Run-Task.cmd
├─ tests\
├─ run.cmd Handaufruf mit der venv
├─ pyproject.toml
├─ LICENSE
├─ AI-NOTICE.md
└─ README.md
Ausserhalb dieses Ordners wird nichts abgelegt. Alle Pfadangaben in der
Konfiguration duerfen relativ sein und gelten dann relativ zur config.toml -
der Basisordner laesst sich also spaeter umbenennen oder verschieben.
# Auf dem Windows Server, administrative PowerShell
New-Item -ItemType Directory "C:\FIRMA\cmkoffline2mail" -Force
# Inhalt dieses Repositories dorthin kopieren (git clone, Copy-Item oder ZIP entpacken)Beim ZIP-Download von GitHub steckt alles noch einmal in einem Ordner wie
cmkoffline2mail-main\. Es muss dessen Inhalt in den Basisordner - nicht der Ordner selbst.
Schnelltest - muss True liefern:
Test-Path "C:\FIRMA\cmkoffline2mail\cmkoffline2mail\cli.py"Das Programm braucht keine Fremdpakete, eine venv ist trotzdem sinnvoll: sie bindet die Ausfuehrung an eine bestimmte Python-Version und macht sie unabhaengig von spaeteren Aenderungen am System-Python.
Das Basis-Python muss maschinenweit installiert sein. Eine venv ist kein vollstaendiges Python - ihre
pyvenv.cfgverweist dauerhaft auf den Interpreter, mit dem sie erzeugt wurde:home = C:\Users\Admin\AppData\Local\Python\pythoncore-3.14-64 <- unbrauchbar home = C:\Program Files\Python313 <- richtigEin Python aus dem eigenen Benutzerprofil (Microsoft Store,
winget, Python Install Manager oder Installer ohne "for all users") funktioniert interaktiv tadellos, aber das gMSA kommt an das fremde Profil nicht heran - die Aufgabe endet dann sofort mit einem Zugriffsfehler.
Install-ScheduledTask.ps1sucht deshalb nur maschinenweite Installationen (HKLM-Registrierung,C:\Program Files\Python3*,C:\Python3*), prueft auch eine bereits vorhandene.venvund bricht mit Klartextmeldung ab, wenn das Basis-Python im Benutzerprofil liegt.
cd "C:\FIRMA\cmkoffline2mail"
& "C:\Program Files\Python313\python.exe" -m venv .venv
.\.venv\Scripts\python.exe -m cmkoffline2mail --version
# Kontrolle - hier darf kein Pfad unter C:\Users stehen:
Get-Content .venv\pyvenv.cfg | Select-String "home|executable"Ist bereits eine venv aus einem Benutzerprofil-Python vorhanden, hilft nur neu
anlegen: .venv loeschen, Python maschinenweit installieren, Schritt wiederholen.
Paket in der venv bekanntmachen. python -m cmkoffline2mail findet das Paket
sonst nur, wenn das Arbeitsverzeichnis zufaellig der Basisordner ist - sonst kommt
No module named cmkoffline2mail. Ein Eintrag im Suchpfad der venv loest das
dauerhaft (kein pip, kein Internetzugang noetig):
.\deploy\Register-PackagePath.ps1Das Skript schreibt <Basisordner> in
.venv\Lib\site-packages\cmkoffline2mail.pth und prueft anschliessend den
Import aus einem fremden Verzeichnis. Install-ScheduledTask.ps1 erledigt das
ebenfalls automatisch.
Install-ScheduledTask.ps1 (Schritt 2.7) legt die venv bei Bedarf selbst an.
Wichtig fuer die Aufgabenplanung: Ein
activategibt es dort nicht und wird auch nicht gebraucht. Die Aufgabe ruft direktC:\FIRMA\cmkoffline2mail\.venv\Scripts\python.exeauf - diesepython.exeerkennt ihre Umgebung ueber die daneben liegendepyvenv.cfgselbst. Wichtig ist nur, dass nicht das System-Python eingetragen wird und dass das Arbeitsverzeichnis der Basisordner ist.
-
In Checkmk: Setup → Users → Add user
-
Haken bei Automation secret for machine accounts setzen, Geheimnis notieren
-
Rolle zuweisen. Minimal noetige Berechtigungen:
- See all hosts and services (
general.see_all) - Use Setup (
wato.use) - fuer das Auslesen von Ordner und Custom-Attributen - Read access to all hosts and folders (
wato.see_all_folders)
Am einfachsten: eine Kopie der Rolle Monitoring user mit diesen drei Rechten. Die Rolle Administrator funktioniert ebenfalls, ist aber mehr als noetig.
- See all hosts and services (
Kurzer Test von der Kommandozeile des Servers aus:
curl.exe -H "Authorization: Bearer automation DAS-GEHEIMNIS" `
"https://cmk.example.internal/produktion/check_mk/api/1.0/version"Auf einem Domaincontroller (einmalig, falls noch kein KDS-Rootkey existiert):
Add-KdsRootKey -EffectiveImmediately # im Labor: -EffectiveTime ((Get-Date).AddHours(-10))
New-ADServiceAccount -Name svc-cmkmail `
-DNSHostName svc-cmkmail.example.internal `
-PrincipalsAllowedToRetrieveManagedPassword "SRV-MONITOR$"Auf dem Windows Server, der die Aufgabe ausfuehrt:
Install-ADServiceAccount svc-cmkmail
Test-ADServiceAccount svc-cmkmail # muss True liefern
# Recht "Als Stapelverarbeitungsauftrag anmelden" vergeben:
cd "C:\FIRMA\cmkoffline2mail\deploy"
.\Grant-BatchLogonRight.ps1 -Account "FIRMA\svc-cmkmail$"Ohne dieses Recht startet die Aufgabe nicht, endet mit
0x1und erzeugt keinerlei Ausgabe - auch keine Protokolldatei.
cd "C:\FIRMA\cmkoffline2mail"
Copy-Item config\config.example.toml config\config.toml
Copy-Item config\mailtemplate.example.toml config\mailtemplate.toml
notepad config\config.tomlMindestens anzupassen: checkmk.url, checkmk.username, checkmk.secret,
die [[folders]]-Abschnitte, mail.from, mail.to und smtp.host.
Status- und Protokolldatei brauchen keine Angabe - ohne state.file bzw.
logging.file landen sie in data\ und logs\ unter dem Basisordner.
Die vorhandenen Ordnerpfade und Attributnamen liefern:
.\run.cmd --list-folders
.\run.cmd --show-attributes srv-a01Die Konfiguration enthaelt Zugangsdaten. Install-ScheduledTask.ps1 erledigt das
automatisch; von Hand:
$Base = "C:\FIRMA\cmkoffline2mail"
$Gmsa = "FIRMA\svc-cmkmail$"
icacls $Base /inheritance:r
icacls $Base /grant:r "*S-1-5-18:(OI)(CI)F" # SYSTEM
icacls $Base /grant:r "*S-1-5-32-544:(OI)(CI)F" # Administratoren
icacls $Base /grant:r "$Gmsa:(OI)(CI)RX" # gMSA: lesen/ausfuehren
icacls "$Base\data" /grant:r "$Gmsa:(OI)(CI)M" # ... und schreiben
icacls "$Base\logs" /grant:r "$Gmsa:(OI)(CI)M"Alternativ das Geheimnis aus einer separaten Datei oder Umgebungsvariablen lesen
(secret_file / secret_env, ebenso password_file / password_env).
cd "C:\FIRMA\cmkoffline2mail"
.\run.cmd --validate # Konfiguration + Vorlage pruefen
.\run.cmd --dry-run # Checkmk abfragen, Mails nur anzeigen
.\run.cmd --test-mail ich@example.com # eine Testmail verschickenrun.cmd verwendet automatisch die venv aus dem Basisordner.
cd "C:\FIRMA\cmkoffline2mail\deploy"
.\Install-ScheduledTask.ps1 -GmsaAccount "FIRMA\svc-cmkmail$" -IntervalMinutes 15 -RunNowOhne -InstallDir wird der Ordner ueber dem Skript verwendet - das Skript laeuft
also einfach dort, wo es liegt. Es legt bei Bedarf die venv an, erstellt
config\, data\ und logs\, setzt die NTFS-Rechte, registriert die Aufgabe und
schreibt einen Mitschnitt nach logs\install-<Zeitstempel>.log. Mit -RunNow
startet direkt ein Testlauf und die Ausgabe wird angezeigt.
Weitere Schalter: -InstallDir, -TaskName, -PythonExe, -TimeLimitMinutes,
-SkipVenv.
Die Aufgabe startet nicht direkt python.exe, sondern deploy\Run-Task.cmd.
Dieser Wrapper leitet alle Ausgaben nach logs\task-run.log um - auch
Fehler, die auftreten, bevor das Programmprotokoll ueberhaupt existiert
(fehlende venv, falsche Rechte, falscher Pfad). Ohne diesen Umweg verschluckt
die Aufgabenplanung solche Meldungen vollstaendig.
Die Befehlszeile der Aufgabe lautet bewusst nur:
cmd.exe /c "C:\FIRMA\cmkoffline2mail\deploy\Run-Task.cmd"
ohne --config. Stehen hinter /c mehr als zwei Anfuehrungszeichen,
entfernt cmd.exe das erste und das letzte (siehe cmd /?) und zerlegt die
Zeile falsch - Pfade landen dann als lose Argumente beim Programm
(error: unrecognized arguments: ...). Die Konfiguration wird ohnehin
automatisch unter <Basisordner>\config\config.toml gefunden.
Kontrolle:
Start-ScheduledTask -TaskName cmkoffline2mail
Get-ScheduledTaskInfo -TaskName cmkoffline2mail # LastTaskResult 0 = in Ordnung
Get-Content "C:\FIRMA\cmkoffline2mail\logs\task-run.log" -Tail 40
Get-Content "C:\FIRMA\cmkoffline2mail\logs\cmkoffline2mail.log" -Tail 30Wenn etwas nicht laeuft:
.\deploy\Test-Installation.ps1Das Skript prueft Struktur, venv, Konfiguration, Aufgabe, Anmelderecht,
NTFS-Rechte und zeigt die letzten Protokollzeilen samt Bedeutung des
LastTaskResult. Es aendert nichts.
Intervall und Schwellwert: Die Aufgabe sollte deutlich haeufiger laufen als der kleinste
offline_for-Wert - sonst wird die Meldung entsprechend spaeter zugestellt.
Vollstaendig kommentiert in config/config.example.toml.
| Schluessel | Bedeutung |
|---|---|
url |
Site-URL, z. B. https://cmk.example.internal/produktion |
username |
Automationsbenutzer |
secret / secret_env / secret_file |
Automationsgeheimnis direkt, aus Umgebungsvariable oder aus Datei |
verify_tls, ca_bundle |
TLS-Pruefung, eigenes CA-Zertifikat |
timeout, retries |
Zeitlimit je Anfrage, Wiederholungen bei Netz-/5xx-Fehlern |
sites |
nur bestimmte Livestatus-Sites abfragen |
custom_attributes |
Liste der Attribute, die als {{ attr_... }} verfuegbar sein sollen |
effective_attributes |
auch am Ordner vererbte Attributwerte lesen (Standard: true) |
folder_lookup_threshold |
ab wie vielen Offline-Hosts die komplette Hostliste statt Einzelabfragen geladen wird |
| Schluessel | Standard | Bedeutung |
|---|---|---|
group_by |
"host" |
host = eine Mail je Host, folder = Sammelmail je Ordner, single = eine Gesamtmail |
include_unreachable |
true |
UNREACHABLE wie DOWN behandeln |
skip_in_downtime |
true |
geplante Wartung ignorieren |
skip_acknowledged |
false |
quittierte Stoerungen ignorieren |
skip_notifications_disabled |
true |
Hosts mit abgeschalteten Benachrichtigungen ignorieren |
skip_pending |
true |
noch nie geprueft |
repeat_after |
"24h" |
Erinnerung, solange der Host offline bleibt; "off" = nur einmal melden |
max_hosts_per_mail |
0 |
teilt lange Listen auf mehrere Mails auf (0 = kein Limit) |
datetime_format |
"%d.%m.%Y %H:%M" |
Zeitformat in der Mail |
offline_since_source |
"auto" |
last_time_up, last_state_change oder auto |
[[folders]]
path = "/produktion/aussenstellen"
offline_for = "4h" # Zeiteinheiten: s, m/min, h, d, w - auch "1d12h"
include_subfolders = true
recipients = ["aussendienst@example.com"] # optional statt mail.to
subject = "[Checkmk] {{ host }} in {{ attr_standort }} offline" # optional
repeat_after = "12h" # optional
enabled = truePasst mehr als eine Regel auf einen Host, gewinnt die genaueste (laengste) Pfadangabe.
Ordner ohne Regel werden nicht gemeldet. Gross-/Kleinschreibung ist egal, ~ und /
sind gleichwertig.
Ohne Filter wird jeder Host der konfigurierten Ordner gemeldet. Mit Filtern wird nur benachrichtigt, wenn ein Custom-Attribut den erwarteten Inhalt hat:
# Nur Hosts mit Attribut "ueberwachung" = 24x7 melden
[[attribute_filters]]
attribute = "ueberwachung"
equals = ["24x7", "rund um die Uhr"]
# Testsysteme grundsaetzlich nicht melden
[[attribute_filters]]
attribute = "umgebung"
contains = ["Test", "Labor"]
mode = "exclude"| Schluessel | Bedeutung |
|---|---|
attribute |
Name des Custom-Attributs, Labels oder Host-Tags (Pflicht) |
equals |
Wert ist genau einer aus der Liste |
contains |
Wert enthaelt eine der Zeichenketten |
regex |
Wert passt auf den regulaeren Ausdruck |
not_empty |
Wert ist ueberhaupt gesetzt |
mode |
include = nur bei Treffer melden (Standard), exclude = dann nicht melden |
ignore_case |
Gross-/Kleinschreibung ignorieren (Standard true) |
on_missing |
Attribut leer: skip oder notify (Standard: include → skip, exclude → notify) |
- Mindestens eine Bedingung ist noetig; mehrere Bedingungen in einem Filter wirken als ODER.
- Mehrere
[[attribute_filters]]wirken als UND - es muessen alle zutreffen. - Das Attribut wird automatisch mit ausgelesen, es muss nicht zusaetzlich unter
checkmk.custom_attributesstehen. - Filter gelten fuer alle Ordner. Sollen sie nur fuer einen Ordner gelten, direkt
unter dessen
[[folders]]-Abschnitt schreiben:
[[folders]]
path = "/produktion"
offline_for = "30m"
[[folders.attribute_filters]]
attribute = "kritisch"
equals = ["ja"]--validate listet alle aktiven Filter im Klartext auf, --log-level DEBUG
protokolliert je uebersprungenem Host den Grund samt gefundenem Wert.
mail.from, mail.to, mail.subject (mit Platzhaltern) und mail.template
(Pfad zur zweiten Konfigurationsdatei; relativ zur config.toml erlaubt).
smtp.security ist none, starttls oder ssl; username/password nur ausfuellen,
wenn der Relay eine Anmeldung verlangt. Bei einem internen Relay, der die Server-IP
freigibt, bleiben beide leer - das gMSA meldet sich dann nicht am SMTP an.
state.file merkt sich, wer bereits benachrichtigt wurde (Schreibrecht fuer das gMSA noetig -
im Basisordner selbst hat das Dienstkonto absichtlich nur Leserechte, deshalb data\ und logs\);
ohne Angabe <Basisordner>\data\state.json. logging.file rotiert automatisch
(max_bytes, backup_count); ohne Angabe <Basisordner>\logs\cmkoffline2mail.log.
Alle Pfadangaben (template, state.file, logging.file, ca_bundle,
secret_file, password_file) duerfen relativ angegeben werden - sie gelten dann
relativ zur config.toml. Umgebungsvariablen wie %PROGRAMDATA% werden aufgeloest.
Enthaelt nur den Mailinhalt - siehe config/mailtemplate.example.toml.
format = "both" # "text" = nur Text, "html" = nur HTML, "both" = beides
[text]
body = "..." # Rumpf der Textmail, enthaelt {{ host_rows }}
host_row = "..." # eine Zeile je Host
[html]
body = "..." # Rumpf der HTML-Mail, enthaelt {{ host_rows }}
host_row = "..." # eine Tabellenzeile je HostSchreibweise {{ name }}. HTML-Werte werden automatisch maskiert.
In body und im Betreff (mail.subject):
| Platzhalter | Inhalt |
|---|---|
{{ host }}, {{ ip }}, {{ alias }} |
Hostname, IP-Adresse und Alias (bei group_by = "host" genau dieser Host) |
{{ hosts }}, {{ addresses }} |
alle Hostnamen bzw. IP-Adressen der Mail, kommagetrennt |
{{ host_count }} |
Anzahl der Hosts in der Mail |
{{ folder }}, {{ folder_path }} |
Ordner der Regel |
{{ state }} |
DOWN oder UNREACHABLE |
{{ offline_since }}, {{ offline_for }} |
Offline-Zeitpunkt und -Dauer |
{{ threshold }} |
konfigurierte Wartezeit des Ordners |
{{ now }}, {{ date }}, {{ time }} |
Zeitpunkt des Laufs |
{{ site }}, {{ checkmk_url }}, {{ url }} |
Site-Name, Link zur Oberflaeche, Link zum Host |
{{ attr_<name> }} |
Custom-Attribut aus checkmk.custom_attributes |
{{ host_rows }} |
die zusammengesetzten Hostzeilen (im body erforderlich) |
Zusaetzlich in host_row (je Host):
{{ offline_seconds }}, {{ last_check }}, {{ output }} (Checkmk-Meldung), {{ folder }}.
Custom-Attribute: Der Name unter checkmk.custom_attributes ist die ID aus
Setup → Hosts → Custom host attributes; auch Labels und Host-Tags werden gefunden.
Aus standort wird der Platzhalter {{ attr_standort }}. Bei Sammelmails enthaelt der
Platzhalter die verschiedenen Werte kommagetrennt. Ein unbekannter Platzhalter fuehrt zu
einem Fehler - --validate zeigt ihn vor dem Produktivbetrieb an.
run.cmd [Optionen] # nutzt die venv aus dem Basisordner
.venv\Scripts\python.exe -m cmkoffline2mail [-c KONFIG] [Optionen]
-c, --config PFAD Konfigurationsdatei. Ohne Angabe wird der Reihe nach gesucht in
%CMKOFFLINE2MAIL_CONFIG%, <Basisordner>\config\config.toml,
<Basisordner>\config.toml
-t, --template PFAD andere Mail-Vorlage verwenden
--validate nur Konfiguration und Vorlage pruefen (keine Verbindung)
-n, --dry-run Checkmk abfragen, Mails nur anzeigen, Status nicht veraendern
--test-mail [ADR] Testmail mit Beispieldaten versenden
--list-folders alle Checkmk-Ordner auflisten
--show-attributes HOST alle Setup-Attribute eines Hosts anzeigen
--state-file PFAD abweichende Statusdatei
--no-state-update Statusdatei nicht schreiben
--log-level STUFE DEBUG | INFO | WARNING | ERROR
--version Version anzeigen
Rueckgabewerte (in der Aufgabenplanung als Letztes Ausfuehrungsergebnis sichtbar):
| Wert | Bedeutung |
|---|---|
0 |
Lauf erfolgreich (auch wenn nichts zu melden war) |
1 |
Laufzeitfehler (Checkmk nicht erreichbar, SMTP-Fehler, ...) |
2 |
Fehler in der Konfiguration oder der Mail-Vorlage |
- Checkmk liefert alle Hosts im Zustand DOWN (und optional UNREACHABLE).
- Hosts in Wartung, quittierte oder stummgeschaltete Hosts werden je nach
[behaviour]uebersprungen. - Ueber den Setup-Ordner wird die passendste
[[folders]]-Regel gesucht; Hosts in nicht konfigurierten Ordnern werden ignoriert. 3a. Konfigurierte[[attribute_filters]]muessen zutreffen - sonst wird der Host uebersprungen. - Ist der Host laenger offline als
offline_for, wird eine Mail faellig. - Die Statusdatei verhindert, dass dieselbe Stoerung erneut gemeldet wird.
Erst nach
repeat_afterfolgt eine Erinnerung; ist der Host wieder online, wird sein Eintrag entfernt - eine neue Stoerung wird also wieder gemeldet.
Es gibt bewusst keine Entwarnungsmail: gemeldet wird nur das Ausbleiben von Hosts.
| Meldung / Symptom | Ursache und Abhilfe |
|---|---|
Anmeldung an Checkmk fehlgeschlagen (HTTP 401/403) |
Benutzername oder Automationsgeheimnis falsch, oder der Rolle fehlt Use Setup / See all hosts |
Checkmk-Endpunkt nicht gefunden (HTTP 404) |
checkmk.url ohne oder mit falschem Site-Namen |
certificate verify failed |
eigenes CA-Zertifikat unter ca_bundle hinterlegen (oder notfalls verify_tls = false) |
Fuer N Host(s) war kein Setup-Ordner ermittelbar |
Der Rolle fehlt der Setup-Zugriff, oder der Host existiert nur im Monitoring |
Ordner nicht konfiguriert im Protokoll |
erwartetes Verhalten - Ordner mit --list-folders pruefen |
SMTP-Anmeldung ... fehlgeschlagen |
smtp.username/password pruefen; bei IP-Freigabe beide leer lassen |
Aufgabe endet mit 0x1, keine Protokolldatei |
gMSA fehlt Als Stapelverarbeitungsauftrag anmelden (Grant-BatchLogonRight.ps1) |
Aufgabe endet mit 0x2 / 0x80070002 |
Pfad in der Aufgabe stimmt nicht - Aufgabe neu registrieren |
Aufgabe endet mit 0x8007010B |
Arbeitsverzeichnis der Aufgabe ist ungueltig |
Aufgabe endet mit 2 |
--validate von Hand ausfuehren, die Meldung nennt den Schluessel |
Aufgabe endet mit 9 |
Wrapper findet .venv\Scripts\python.exe nicht |
Aufgabe endet mit 0xC0000135 / Zugriff verweigert |
venv wurde aus einem Python im Benutzerprofil erzeugt - pyvenv.cfg pruefen (siehe 2.2) |
error: unrecognized arguments: C:\... |
Befehlszeile der Aufgabe enthaelt mehr als zwei Anfuehrungszeichen - Aufgabe mit Install-ScheduledTask.ps1 neu registrieren |
No module named cmkoffline2mail |
Suchpfad-Eintrag fehlt - .\deploy\Register-PackagePath.ps1 ausfuehren. Kommt die Meldung danach weiter, liegt das Paket nicht unter dem Basisordner (ZIP-Doppelordner, siehe 2.1) |
| Es kommen keine Mails mehr | Host wurde bereits gemeldet - repeat_after pruefen oder Statusdatei loeschen |
Protokolldatei ... Permission denied |
logging.file zeigt in einen Ordner ohne Schreibrecht - Angabe entfernen (dann logs\) oder Rechte setzen |
ist kein gueltiges TOML |
Die Meldung zeigt Zeile und Stelle an. Meist fehlen Anfuehrungszeichen (format = "html", nicht format = html) oder ein abschliessendes """ |
Es gibt drei Protokolle - in dieser Reihenfolge nachsehen:
| Datei | Inhalt |
|---|---|
logs\task-run.log |
Ausgabe jedes Aufgabenlaufs, inklusive Fehlern vor dem Programmstart |
logs\cmkoffline2mail.log |
Programmprotokoll (rotierend) |
logs\install-*.log |
Mitschnitt der Installation |
Existiert logs\task-run.log gar nicht, hat die Aufgabenplanung den Wrapper nie
gestartet - dann liegt es am Konto (Anmelderecht), nicht am Programm.
Alles auf einmal pruefen:
cd "C:\FIRMA\cmkoffline2mail"
.\deploy\Test-Installation.ps1Zusaetzlich hilft der Verlauf der Aufgabenplanung, falls er abgeschaltet ist:
wevtutil sl Microsoft-Windows-TaskScheduler/Operational /e:trueFuer Details --log-level DEBUG setzen - dann werden auch die angefragten URLs protokolliert
(das Automationsgeheimnis wird nie protokolliert).
python -m unittest discover -s tests -t .Die Tests kommen ohne Netzwerk, Checkmk und SMTP-Server aus.
cmkoffline2mail/ Python-Paket
├─ cli.py Kommandozeile und Hauptablauf
├─ config.py Einlesen und Pruefen von config.toml
├─ checkmk.py REST-API-Client (Monitoring + Setup)
├─ evaluate.py Ordnerregeln, Schwellwerte, Gruppierung, Platzhalter
├─ render.py Mail-Vorlage (mailtemplate.toml)
├─ mailer.py SMTP-Versand
├─ state.py Statusdatei gegen wiederholte Mails
├─ duration.py Zeitangaben wie "1d12h"
└─ logging_setup.py Datei- und Konsolenprotokoll
deploy/
├─ Install-ScheduledTask.ps1 venv, Verzeichnisse, Rechte, Aufgabe
├─ Test-Installation.ps1 Diagnose: warum laeuft die Aufgabe nicht?
├─ Register-PackagePath.ps1 behebt "No module named cmkoffline2mail"
├─ Grant-BatchLogonRight.ps1 Recht "Anmelden als Stapelverarbeitungsauftrag"
└─ Run-Task.cmd Startskript der Aufgabe (protokolliert alles)
run.cmd Handaufruf mit der venv
Die Tests laufen bei jedem Push automatisch per GitHub Actions
(.github/workflows/tests.yml).
Lizenz: MIT - Nutzung, Aenderung und Weitergabe (auch kommerziell) sind erlaubt, solange der Lizenzhinweis erhalten bleibt.
KI-Nutzung: Dieses Projekt wurde mit Unterstuetzung von KI erstellt (Claude Code von Anthropic). Code, Tests, Skripte und Dokumentation wurden ueberwiegend KI-generiert und vom Maintainer angeleitet, geprueft und getestet. Details in AI-NOTICE.md.
Haftung: Die Software wird ohne jede Gewaehrleistung bereitgestellt. Vor
dem Produktiveinsatz bitte selbst pruefen und testen - insbesondere die
PowerShell-Skripte unter deploy\, die NTFS-Rechte und lokale
Sicherheitsrichtlinien aendern.
Marken: Checkmk ist eine Marke der Checkmk GmbH. Dieses Projekt ist ein unabhaengiges Community-Werkzeug und steht in keiner Verbindung zur Checkmk GmbH.
Beitraege: Issues und Pull Requests sind willkommen. Bitte vorher
python -m unittest discover -s tests -t . ausfuehren und im Pull Request
kurz angeben, ob KI genutzt wurde. Keine echten Zugangsdaten, Hostnamen oder
Mailadressen in Issues, Logs oder Beispielen veroeffentlichen.