Custom-Script-Check-Referenz

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

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 Eigene 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 custom-script. Der Agent schreibt dein Skript in eine kurzlebige Skriptdatei, führt sie als Kindprozess aus — powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File <script>.ps1 unter Windows, bash <script>.sh unter Linux und macOS — und löscht die Datei danach wieder. Keine Helper, keine Sentinel-Marker: Der Check stützt sich auf den Exit-Code und eine kleine stdout/stderr-Erfassung.

Unter Windows hängt der Agent eine Zeile an, die den Exit-Code aus $LASTEXITCODE und $? neu ableitet. Der -File-Modus von PowerShell endet sonst mit 0, selbst wenn die letzte Anweisung einen nicht-terminierenden Fehler ausgelöst hat — ein kaputtes Skript würde also als Success gemeldet. Ein explizites exit oder throw in deinem Skript gewinnt weiterhin; ein abschließendes Write-Error oder ein fehlschlagendes letztes Cmdlet ergibt jetzt Exit-Code 1.

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).

SuccessExitCode ist ein einzelner Code, keine Liste — genau ein Exit-Code kann Success bedeuten. Die Warning- und Critical-Listen nehmen beliebig viele Codes auf: Ein Legacy-Werkzeug, das bei einem leichten Problem 3 zurückgibt, ordnest du zu, indem du 3 in WarningExitCodes aufnimmst. 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 sein Zeitlimit erreicht hat und der Agent es beendet hat.
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 Eigene Checks im Dashboard — der Editor deckt Skripte pro Plattform, typisierte Eingaben, typisierte Ausgaben, das Ausführungsintervall und das Zeitlimit pro Check 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)
Zeitlimitstandardmäßig 5 Minuten pro Ausführung; pro Check einstellbar von 5 Sekunden bis 60 Minuten (das Editor-Feld ist in Minuten)
Plattform-UnterstützungWindows (PowerShell), Linux (bash), macOS (bash)
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. Der Agent-Installer bringt es beim Setup auf das Gerät, wenn apt, dnf oder yum verfügbar ist
macOS-AbhängigkeitenKeine über ein reguläres macOS hinaus — der Wrapper baut und liest sein JSON mit der JavaScript-Automatisierungsumgebung, die das Betriebssystem mitbringt (osascript)

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.

Melde den Status über checkResult, niemals über den Exit-Code. Der Wrapper führt dein Skript in einem try/finally (PowerShell) beziehungsweise hinter einem EXIT-Trap (bash) aus, sodass die Result-Payload auch dann geschrieben wird, wenn dein Skript exit oder return aufruft — der Agent verwirft diese Payload aber und meldet Failure, sobald der Skriptprozess mit einem Exit-Code ungleich 0 endet. exit 0 und return sind unbedenklich; exit 1 wirft alles weg, was du gesetzt hast.

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 die in macOS eingebaute JavaScript-Automatisierungsumgebung statt jq, es muss also nichts zusätzlich installiert werden. 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).

Reservierte Schlüssel bei Netzwerkgeräten. Eine string-Eingabe mit dem Namen host, ip, ipaddress, target, url, endpoint oder address (Groß- und Kleinschreibung spielt keine Rolle) gilt als das entfernte Ziel des Checks. Auf einem Netzwerkgerät — einem Gerät ohne eigenen Agenten — blendet octoja dieses Feld aus und setzt stattdessen die IP-Adresse des Geräts ein; ein Check ohne eine solche Eingabe wird im Dialog Check hinzufügen eines Netzwerkgeräts gar nicht erst angeboten (die Zuweisung über ein Konfigurationspaket wird nicht so gefiltert). Eine Eingabe namens community, v3User, authPassword oder privPassword aktiviert ebenso die SNMP-Übernahme: Diese Eingabe und jede version-, snmpVersion-, authProtocol-, privProtocol-, port- oder snmpPort-Eingabe des Checks werden aus den auf dem Gerät hinterlegten SNMP-Einstellungen gefüllt. Verwende diese Schlüsselnamen deshalb für nichts anderes — siehe Einen Custom-Script-Check konfigurieren.

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.
customFieldKeystringOptional. Das benutzerdefinierte Gerätefeld, in das dieser Wert bei jedem Lauf geschrieben wird. Bleibt es leer, verbleibt der Wert im Check-Ergebnis.

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

Ausführungsgrenzen

GrenzeWertQuelle
ZeitlimitStandard 5 Minuten; Bereich 5 Sekunden – 60 MinutenEinstellung pro Check
Maximale dekodierte Output-Größe1 MB (Standard; konfigurierbar 1 KB – 1 MB). Ein Schutz gegen ausufernde Payloads, nicht die alltägliche Anzeigegrenze — octoja zeigt die vollständige Ausgabe als aktuelles Check-Ergebnis und kürzt nur die historisierten KopienAgent-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
Dein Skript endet mit einem Exit-Code ungleich 0 (etwa exit 1)Failure — der Wrapper schreibt die Result-Payload zwar noch, der Agent verwirft sie aber und meldet stattdessen den Exit-Code. Setze den Status über checkResult und lass das Skript normal enden
Laufzeit über dem Zeitlimit des Checks (5 Minuten, sofern du es nicht geändert hast)Failure — 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 Linux-Wrapper prüft vor dem Lauf deines Skripts, ob jq vorhanden ist, und liefert ein Ergebnis, das das fehlende Paket und den Installationsbefehl nennt. In der Praxis selten: Der Agent-Installer bringt jq beim Setup mit, wenn apt, dnf oder yum verfügbar ist — betroffen sind vor allem selbstgebaute oder minimale Images

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