Custom-Script-Check-Referenz

Feldreferenz für den Custom-Script-Check — Wrapper-Vertrag, Helper, Eingabe-/Ausgabe-Schema, Statuscodes und Ausführungsgrenzen.

Geschrieben von Erdinc Akay

Zuletzt aktualisiert Vor 25 Tagen

octoja kennt zwei Wege, ein Skript als Check auszuliefern — und unter der Haube sind das nicht dasselbe Plugin. Diese Referenz trennt beide klar, damit du den richtigen ohne Überraschungen konfigurierst.

  • Eingebauter Custom-Script-Check — ein vorgefertigtes Check-Plugin, das du über ein Konfigurationspaket einem Gerät zuweist. Du fügst ein einzelnes PowerShell- oder bash-Skript in die Check-Definition ein; der Agent führt es unverändert aus und wandelt den Exit-Code in einen Status um.
  • Selbstdefinierte Custom-Checks — Checks, die du selbst auf der Seite Custom Checks im Dashboard schreibst. Jedes Skript wird zum Zeitpunkt der Auslieferung von octoja in einen Wrapper umhüllt, damit es typisierte Eingaben deklarieren, typisierte Ausgaben emittieren und den gebündelten SNMP-Worker verwenden kann.

Die beiden Wege teilen weder den Status-Mechanismus noch den Output-Vertrag. Lies den Abschnitt, der zum konfigurierten Check passt.

Eingebauter Custom-Script-Check

Plugin-Kennung octo/custom-script. Der Agent führt das Skript direkt aus — über powershell.exe unter Windows oder /bin/bash -s unter Linux und macOS. Kein Wrapper, keine Helper, keine Sentinel-Marker — der Check stützt sich vollständig auf den Exit-Code und eine kleine stdout/stderr-Erfassung.

Statuscodes (Exit-Code-Mapping)

Der Exit-Code bestimmt das Ergebnis. Jeder Custom-Script-Check trägt einen SuccessExitCode, eine WarningExitCodes-Liste und eine CriticalExitCodes-Liste:

FeldStandardBedeutung
SuccessExitCode0Status Success.
WarningExitCodes["1"]Status Warning.
CriticalExitCodes["2"]Status Critical.
Jeder andere Exit-CodeStatus Critical (unbekannte Exit-Codes fallen auf Critical, nicht auf Failure).

Du kannst jede Liste pro Check überschreiben — etwa 0 und 3 als Success akzeptieren, wenn du ein Legacy-Werkzeug umhüllst. Die Critical-Liste wird vor der Warning-Liste ausgewertet — ein Exit-Code, der in beiden Listen steht, ergibt also Critical. Es gibt für dieses Plugin keinen Helper im Skript; das Ergebnis ist immer der Exit-Code des Prozesses.

Was du zurückbekommst

Bei jedem Lauf liefert der Check diese Felder an octoja:

FeldInhalt
ExitCodeDer ganzzahlige Exit-Code; -1, wenn das Skript per Timeout abgebrochen wurde oder der Prozess abgestürzt ist.
StdoutDie ersten 2 KB von stdout. Längere Ausgaben werden abgeschnitten und mit ... (truncated) versehen.
StderrErste Zeile von stderr, max. 500 Zeichen. Truncated-Suffix wie oben.
ExecutionTimeMsWanduhr-Laufzeit in Millisekunden.

Ausführungsgrenzen

GrenzeWertQuelle
Skriptgröße64 K Zeichen (65.536) — längere Skripte werden vor der Ausführung mit Status Warning abgewiesenFestes Limit
TimeoutPro Check über TimeoutSeconds; Standard 30 s, gekappt auf 5–300 sEinstellung pro Check
Erfasste stdout-Menge2 KB (der Rest wird verworfen, kein Failure)Festes Limit
Erfasste stderr-MengeErste Zeile, max. 500 ZeichenFestes Limit

Was den Check zerstört

MusterErgebnis
Leerer Skript-BodyFailure vor der Ausführung
Skript länger als 64 K ZeichenWarning vor der Ausführung (der Agent führt es nicht aus)
Laufzeit übersteigt das konfigurierte TimeoutSecondsFailure; der Agent killt den Prozess und meldet ExitCode = -1
Prozessstart schlägt fehl (Interpreter fehlt, fehlende Rechte usw.)Failure

Selbstdefinierte Custom-Checks

Diese Checks schreibst du auf der Seite Custom Checks im Dashboard — der Editor deckt Skripte pro Plattform, typisierte Eingaben, typisierte Ausgaben und das Ausführungsintervall ab. (Community-Check-Repositories, die per Name und URL hinzugefügt werden, liefern fertige Checks aus einer externen Quelle — sie sind nicht der Weg, eigene Checks zu schreiben.) Jeder Check wird von octoja umhüllt, bevor er den Agent erreicht. Der Wrapper stellt dem Skript typisierte Eingaben bereit, liefert Helper zum Emittieren typisierter Ausgaben und grenzt die Result-Payload mit Sentinel-Markern ab, damit beliebige andere stdout-Ausgaben sie nicht beschädigen können.

FeldWert
Standard-Intervall5 Minuten (pro Check konfigurierbar, 5–1440 Minuten)
Maximale Laufzeit5 Minuten pro Ausführung
Plattform-UnterstützungWindows (PowerShell), Linux (bash), macOS (bash + Python 3)
Runtime-IDswin-x64, win-arm64, linux-x64, linux-arm64, osx-x64, osx-arm64
Linux-Abhängigkeitenjq — eine harte Abhängigkeit jedes Linux-Custom-Checks: Der Ausgabe-Footer des Wrappers serialisiert die Result-Payload mit jq, und auch get_input / die SNMP-Helper nutzen es
macOS-Abhängigkeitenpython3 (auf modernem macOS vorinstalliert)

Wenn du nur ein Linux-Skript hinterlegst, führt der Agent es auch auf macOS aus — über den osx-x64 / osx-arm64-Fallback.

Der Wrapper-Vertrag

Der Wrapper erledigt drei Dinge rund um dein Skript: Er dekodiert die konfigurierten Eingaben und stellt sie bereit ($checkInput / INPUT_JSON), belegt den Ausgabe-Container mit checkResult = 0 vor ($output / _OCTO_OUTPUT), und nachdem dein Skript gelaufen ist, serialisiert er die Ausgabe nach base64 und gibt sie zwischen den Result-Markern aus. Deine Aufgabe ist der mittlere Teil: Eingaben lesen, Arbeit erledigen, Ausgabefelder und den Status setzen. Der Agent extrahiert nur die Bytes zwischen <<<OCTO_RESULT_BEGIN>>> und <<<OCTO_RESULT_END>>>, sodass Write-Output, Write-Host, echo oder ConvertTo-Json aus deinem Skript den Wrapper nicht brechen.

Status — das checkResult-Sentinel

Umhüllte Checks nutzen kein Exit-Code-Mapping. Der Status ist das checkResult-Feld der serialisierten Output-Payload, das der Agent in eine CheckResultStatus-Enum decodiert. Setze es über den Helper deiner Sprache:

Numerischer WertString-WertStatus
0"Success"Success
1"Warning"Warning
2"Critical"Critical
3"Failure"Failure (sparsam einsetzen — vorgesehen für „der Check selbst konnte nicht laufen")

Die bash- und macOS-Wrapper liefern set_result 0|1|2 als Kurzform zum Setzen von checkResult. String-Werte sind beim Decodieren case-insensitive.

PowerShell — $checkInput und $output

VariableTypInhalt
$checkInputObjectDekodiertes JSON der konfigurierten Eingabeparameter. Zugriff per Punktsyntax: $checkInput.MaxAge. Der Wrapper vermeidet bewusst den Namen $input, weil das eine automatische PowerShell-Variable ist.
$outputHashtableVorbelegt mit checkResult = 0. Felder hinzufügen mit $output["key"] = value.

Alles, was du an $output hängst, wird serialisiert und an octoja gesendet. Mappe deine Output-Keys auf die Ausgabefelder, die du in der Check-Definition deklariert hast — sonst kann der Dashboard-Renderer sie nicht an UI-Bausteine binden.

Der Wrapper injiziert außerdem zwei SNMP-Helper, die an den im Agent gebündelten SNMP-Worker delegieren. Beide nehmen benannte Parameter:

HelperSignaturZweck
Get-SnmpGet-Snmp -TargetHost <host> -Oid <oid[]> [-Port 161] [-Version v2c|v3] [-Community public] [-User <u>] [-AuthProtocol <p>] [-AuthPassword <pw>] [-PrivProtocol <p>] [-PrivPassword <pw>] [-TimeoutMs 5000]SNMP GET gegen eine oder mehrere OIDs; gibt eine Hashtable OID → Wert zurück.
Get-SnmpWalkGet-SnmpWalk -TargetHost <host> -BaseOid <oid> [-Port 161] [-Version v2c|v3] [-Community public] [-User <u>] [-AuthProtocol <p>] [-AuthPassword <pw>] [-PrivProtocol <p>] [-PrivPassword <pw>] [-TimeoutMs 5000]SNMP WALK über einen Teilbaum; gibt ein geordnetes Array von [pscustomobject]@{ Oid; Value } zurück.

Beachte den Parameternamen: -TargetHost, nicht -Host. $Host ist eine automatische PowerShell-Variable, also vermeidet der Wrapper ihn. Beide Helper sind nur verfügbar, wenn der Agent seinen SNMP-Worker über die Umgebungsvariable OCTOJA_WORKER_BIN bereitstellt; ist die Variable nicht gesetzt, werfen die Helper eine Ausnahme und dein Skript sollte sauber zurückfallen.

Bash (Linux) — Helper

HelperSignaturZweck
get_inputget_input "key"Gibt den Eingabeparameter als String zurück. Benötigt jq auf dem Gerät.
set_outputset_output "key" valueSetzt ein Ausgabefeld. Numerische / boolesche / JSON-Array- / JSON-Object-Werte werden anhand ihrer Form erkannt und als entsprechender JSON-Typ ausgegeben; alles andere wird escaped und als String ausgegeben.
set_resultset_result 0|1|2Kurzform für set_output "checkResult" <n> (0 = OK, 1 = Warning, 2 = Critical, 3 = Failure — dieselbe Enum wie CheckResultStatus).
snmp_getsnmp_get --host <host> [--port 161] [--version v2c|v3] [--community public] [--user <u>] [--auth-protocol <p>] [--auth-password <pw>] [--priv-protocol <p>] [--priv-password <pw>] <oid> [<oid>...]SNMP GET über den gebündelten Worker. Gibt den JSON-Envelope des Workers auf stdout aus; benötigt OCTOJA_WORKER_BIN und jq.
snmp_walksnmp_walk --host <host> [--port 161] [--version v2c|v3] [--community public] [--user <u>] [--auth-protocol <p>] [--auth-password <pw>] [--priv-protocol <p>] [--priv-password <pw>] <baseOid>SNMP WALK über den gebündelten Worker. Die Base-OID ist das letzte positionale Argument; die Ausgabe ist ein geordnetes Array aus {Oid, Value}.

Die SNMP-Helper sind flag-basiert (--host, --community, …), nicht positional. Das Output-Array heißt _OCTO_OUTPUT (assoziativ). Verwende die Helper; das Array direkt anzufassen ist nicht Teil des Vertrags.

Bash (macOS) — Helper

Identische Schnittstelle wie unter Linux — get_input, set_output, set_result und dieselben flag-basierten snmp_get / snmp_walk, wenn OCTOJA_WORKER_BIN gesetzt ist — aber die Implementierung verwendet Python 3 statt jq. Selbst wenn dein Skript mitten im Lauf beendet wird oder abstürzt, entsteht noch ein sauberer Result-Envelope. Wenn du kein macOS-spezifisches Skript hinterlegst, wird das Linux-Skript wiederverwendet.

Eingabeschema

Eingaben werden auf der Check-Definition deklariert (Art, Label, Standardwert, erforderlich) und erreichen das Skript als JSON-Objekt. Die unterstützten Feldarten entsprechen dem InputFieldDefinition-Modell der Plattform — string, number, boolean, list und so weiter. Lies sie mit $checkInput.Key (PowerShell) oder get_input "key" (bash/macOS).

Ausgabeschema

Ausgaben werden auf der Check-Definition als Liste von OutputFieldDefinition deklariert. Jeder Eintrag hat:

FeldTypBeschreibung
keystringProperty-Name, wie er im JSON-Output erscheint (camelCase).
typeenumString, Number, Boolean, Array oder Object.
labellokalisierter StringAnzeige-Label im Dashboard-Renderer.
unitstringOptionale Einheit wie %, ms, GB.
itemsrekursivFür Array-Typ — das Schema jedes Elements.
propertiesListeFür Object-Typ — verschachtelte Felddefinitionen.

checkResult ist implizit; deklariere zusätzliche Felder, die du tatsächlich im Dashboard verwendest.

Ausführungsgrenzen

GrenzeWertQuelle
Maximale Laufzeit5 MinutenFestes Limit
Maximale dekodierte Output-Größe16 KB (Standard; konfigurierbar 1 KB – 1 MB)Instanz-Einstellung
Status-MappingAus dem checkResult-Feld der dekodierten JSON-Payload, nicht aus dem Exit-Code des SkriptsFestes Verhalten
Wrapper-stdout-DekodierungDie Payload wird aus dem Bereich zwischen <<<OCTO_RESULT_BEGIN>>> und <<<OCTO_RESULT_END>>> extrahiert und base64-dekodiert; Benutzer-stdout außerhalb der Marker wird ignoriertFestes Verhalten

Was den Check zerstört

MusterErgebnis
Eigene <<<OCTO_RESULT_BEGIN>>> / <<<OCTO_RESULT_END>>>-Marker ausgebenFailure — der Parser extrahiert die falschen Bytes; gewöhnliches Write-Output / Write-Host / echo / ConvertTo-Json außerhalb der Marker ist harmlos
Fehlendes oder nicht parsbares checkResult in der PayloadFailure — der Agent meldet anstelle eines Status den Parse-Fehler
Laufzeit > 5 MinutenFailure — der Agent terminiert den Prozess
Dekodierte Ausgabe > GrößenlimitDer gemeldete Status bleibt erhalten, das Ergebnis wird aber mit Truncated = true markiert und die Data-Payload verworfen; das Dashboard rendert den Status ohne Detailfelder
Linux-Gerät ohne installiertes jqFailure — der Ausgabe-Footer des Wrappers kann die Result-Payload nicht serialisieren, es entsteht kein gültiger Result-Envelope und der gesamte Check schlägt fehl

Diagnose-Ausgabe während der Entwicklung gehört auf stderr — Write-Error / >&2 echo — und wird vom Agent erfasst, ohne den Wrapper-Vertrag zu brechen.

Encoding

Beide Check-Varianten übertragen und führen Skripte durchgehend als UTF-8 aus. Du musst nichts konvertieren und keine Byte-Order-Mark setzen — füge das Skript im Dashboard ein, octoja kümmert sich um das Encoding.

  • Was octoja garantiert: Das Skript wird zeichengetreu als UTF-8 übertragen. Unter Windows wird es aus einer Skriptdatei mit UTF-8-Byte-Order-Mark ausgeführt, sodass Windows PowerShell 5.1 und PowerShell 7 es als UTF-8 lesen — Umlaute, ° und andere Nicht-ASCII-Zeichen kommen exakt so im Skript an, wie du sie geschrieben hast, und werden nie in einer Legacy-Codepage wie Windows-1252 uminterpretiert. Unter Linux und macOS wird das Skript als UTF-8 ohne BOM ausgeliefert, Windows-Zeilenenden werden normalisiert, damit die Shebang-Zeile gültig bleibt.
  • Ausgabe: Beim eingebauten Custom-Script-Check erzwingt der Agent vor dem Lauf deines Skripts UTF-8 als PowerShell-Ausgabe-Encoding und erfasst stdout/stderr als UTF-8 — Nicht-ASCII-Ausgaben wie °C oder Umlaute erreichen das Dashboard unverändert. Bei selbstdefinierten Custom-Checks wird die Result-Payload als UTF-8-JSON serialisiert und Base64-kodiert zwischen den Result-Markern transportiert — konstruktionsbedingt immun gegen Output-Encoding-Probleme.
  • Worauf du weiterhin achten musst: octoja ersetzt niemals Zeichen — was du einfügst, ist exakt das, was PowerShell oder bash parst. Editoren, Chat-Tools und Textverarbeitungen ersetzen gern gerade Anführungszeichen durch typografische ( ) und - oder -- durch Halbgeviert-/Geviertstriche ( ). Das sieht richtig aus, sind aber andere Zeichen; je nach Stelle im Skript führt das zu Syntaxfehlern oder still zu anderem Verhalten. Ersetze typografische Anführungszeichen und Striche durch ihre einfachen ASCII-Gegenstücke, bevor du den Check speicherst.

Skripte, die du über den Check-Importer übernimmst, können dieselben typografischen Zeichen aus ihrer ursprünglichen Quelle mitbringen — dort gilt derselbe Rat.

Verwandte Artikel