added new scripts

This commit is contained in:
DeSqBlocki
2026-09-13 10:08:10 +02:00
parent b07b7e901f
commit 46b78816b9
17 changed files with 3391 additions and 0 deletions
+709
View File
@@ -0,0 +1,709 @@
#!/bin/bash
# /usr/lib/check_mk_agent/local/300/check_crafty
set -u
CONFIG="/etc/check_mk/crafty.conf"
OK=0
WARN=1
CRIT=2
UNKNOWN=3
#
# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
#
if [[ ! -r "$CONFIG" ]]; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - Configuration file ${CONFIG} missing or unreadable"
exit 0
fi
# shellcheck disable=SC1090
source "$CONFIG"
CRAFTY_URL="${CRAFTY_URL:-https://127.0.0.1:8443}"
CRAFTY_USER="${CRAFTY_USER:-}"
CRAFTY_PASSWORD="${CRAFTY_PASSWORD:-}"
CRAFTY_INSECURE="${CRAFTY_INSECURE:-yes}"
IGNORE_HIDDEN_SERVERS="${IGNORE_HIDDEN_SERVERS:-yes}"
CHECK_UPDATES="${CHECK_UPDATES:-yes}"
CRAFTY_RELEASE_API="${CRAFTY_RELEASE_API:-https://gitlab.com/api/v4/projects/34675721/releases/permalink/latest}"
#
# ---------------------------------------------------------------------------
# Requirements
# ---------------------------------------------------------------------------
#
if ! command -v curl >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - curl is not installed"
exit 0
fi
if ! command -v jq >/dev/null 2>&1; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - jq is not installed"
exit 0
fi
if [[ -z "$CRAFTY_USER" || -z "$CRAFTY_PASSWORD" ]]; then
printf '%s\n' "${UNKNOWN} \"Crafty\" - CRAFTY_USER or CRAFTY_PASSWORD is not configured"
exit 0
fi
#
# ---------------------------------------------------------------------------
# curl configuration
# ---------------------------------------------------------------------------
#
CURL_OPTS=(
--silent
--show-error
--connect-timeout 3
--max-time 10
)
if [[ "$CRAFTY_INSECURE" == "yes" ]]; then
CURL_OPTS+=(--insecure)
fi
#
# ---------------------------------------------------------------------------
# Login
# ---------------------------------------------------------------------------
#
LOGIN_PAYLOAD="$(
jq -n \
--arg username "$CRAFTY_USER" \
--arg password "$CRAFTY_PASSWORD" \
'{
username: $username,
password: $password
}'
)"
LOGIN_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-X POST \
-H "Content-Type: application/json" \
-d "$LOGIN_PAYLOAD" \
"${CRAFTY_URL%/}/api/v2/auth/login" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 || -z "$LOGIN_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"Crafty\" - Unable to reach Crafty login API at ${CRAFTY_URL}"
exit 0
fi
if ! printf '%s' "$LOGIN_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Crafty\" - Login API returned invalid JSON"
exit 0
fi
LOGIN_STATUS="$(
printf '%s' "$LOGIN_RESPONSE" |
jq -r '.status // empty'
)"
TOKEN="$(
printf '%s' "$LOGIN_RESPONSE" |
jq -r '.data.token // empty'
)"
if [[ "$LOGIN_STATUS" != "ok" || -z "$TOKEN" ]]; then
LOGIN_ERROR="$(
printf '%s' "$LOGIN_RESPONSE" |
jq -r '.error_data // .error // "authentication failed"'
)"
printf '%s\n' \
"${CRIT} \"Crafty\" - Authentication failed: ${LOGIN_ERROR}"
exit 0
fi
#
# ---------------------------------------------------------------------------
# Server inventory
# ---------------------------------------------------------------------------
#
SERVERS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Authorization: Bearer ${TOKEN}" \
"${CRAFTY_URL%/}/api/v2/servers" \
2>/dev/null
)"
CURL_RC=$?
if [[ $CURL_RC -ne 0 ]]; then
printf '%s\n' \
"${CRIT} \"Crafty\" - Server inventory request failed, curl exit code ${CURL_RC}"
exit 0
fi
if [[ -z "$SERVERS_RESPONSE" ]]; then
printf '%s\n' \
"${CRIT} \"Crafty\" - Server inventory API returned an empty response"
exit 0
fi
if ! printf '%s' "$SERVERS_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Crafty\" - Server inventory returned invalid JSON"
exit 0
fi
SERVERS_STATUS="$(
printf '%s' "$SERVERS_RESPONSE" |
jq -r '.status // empty'
)"
if [[ "$SERVERS_STATUS" != "ok" ]]; then
SERVER_ERROR="$(
printf '%s' "$SERVERS_RESPONSE" |
jq -r '.error_data // .error // "unknown API error"'
)"
printf '%s\n' \
"${CRIT} \"Crafty\" - Server inventory API error: ${SERVER_ERROR}"
exit 0
fi
DATA_TYPE="$(
printf '%s' "$SERVERS_RESPONSE" |
jq -r '.data | type'
)"
if [[ "$DATA_TYPE" != "array" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty\" - Server inventory returned unexpected data type: ${DATA_TYPE}"
exit 0
fi
#
# ---------------------------------------------------------------------------
# Server counts
# ---------------------------------------------------------------------------
#
TOTAL_CONFIGURED="$(
printf '%s' "$SERVERS_RESPONSE" |
jq '.data | length'
)"
if [[ "$IGNORE_HIDDEN_SERVERS" == "yes" ]]; then
SERVER_COUNT="$(
printf '%s' "$SERVERS_RESPONSE" |
jq '[.data[] | select(.show_status != false)] | length'
)"
else
SERVER_COUNT="$TOTAL_CONFIGURED"
fi
#
# ---------------------------------------------------------------------------
# Crafty installed version via /metrics
# ---------------------------------------------------------------------------
#
METRICS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Authorization: Bearer ${TOKEN}" \
"${CRAFTY_URL%/}/metrics" \
2>/dev/null
)"
METRICS_RC=$?
INSTALLED_VERSION=""
if [[ $METRICS_RC -eq 0 && -n "$METRICS_RESPONSE" ]]; then
INSTALLED_VERSION="$(
printf '%s\n' "$METRICS_RESPONSE" |
grep -m1 '^Crafty_Controller_info{' |
sed -n 's/.*version="\([^"]*\)".*/\1/p' |
tr -d '[:space:]'
)"
fi
#
# ---------------------------------------------------------------------------
# Overall Crafty service
# ---------------------------------------------------------------------------
#
if [[ -n "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${OK} \"Crafty\" servers=${SERVER_COUNT};;;0 API reachable and authenticated - version ${INSTALLED_VERSION}, ${SERVER_COUNT}/${TOTAL_CONFIGURED} servers monitored"
else
printf '%s\n' \
"${OK} \"Crafty\" servers=${SERVER_COUNT};;;0 API reachable and authenticated - ${SERVER_COUNT}/${TOTAL_CONFIGURED} servers monitored"
fi
#
# ---------------------------------------------------------------------------
# Crafty update check
# ---------------------------------------------------------------------------
#
if [[ "$CHECK_UPDATES" == "yes" ]]; then
if [[ -z "$INSTALLED_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to determine installed Crafty version from /metrics"
else
RELEASE_RESPONSE="$(
curl \
--silent \
--show-error \
--location \
--fail \
--connect-timeout 3 \
--max-time 10 \
-H "User-Agent: checkmk-crafty-local-check" \
"$CRAFTY_RELEASE_API" \
2>/dev/null
)"
RELEASE_RC=$?
if [[ $RELEASE_RC -ne 0 || -z "$RELEASE_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Installed ${INSTALLED_VERSION}, unable to query GitLab release API"
elif ! printf '%s' "$RELEASE_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - GitLab release API returned invalid JSON"
else
LATEST_VERSION="$(
printf '%s' "$RELEASE_RESPONSE" |
jq -r '.tag_name // empty'
)"
LATEST_VERSION="${LATEST_VERSION#v}"
if [[ -z "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to determine latest Crafty release"
elif [[ ! "$INSTALLED_VERSION" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to parse installed version ${INSTALLED_VERSION}"
elif [[ ! "$LATEST_VERSION" =~ ^[0-9]+([.][0-9]+)*$ ]]; then
printf '%s\n' \
"${UNKNOWN} \"Crafty Update\" - Unable to parse latest version ${LATEST_VERSION}"
else
NEWEST="$(
printf '%s\n%s\n' \
"$INSTALLED_VERSION" \
"$LATEST_VERSION" |
sort -V |
tail -n 1
)"
if [[ "$INSTALLED_VERSION" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${OK} \"Crafty Update\" - Current: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
elif [[ "$NEWEST" == "$LATEST_VERSION" ]]; then
printf '%s\n' \
"${WARN} \"Crafty Update\" - Update available: installed ${INSTALLED_VERSION}, latest ${LATEST_VERSION}"
else
printf '%s\n' \
"${OK} \"Crafty Update\" - Installed ${INSTALLED_VERSION} is newer than latest stable ${LATEST_VERSION}"
fi
fi
fi
fi
fi
#
# ---------------------------------------------------------------------------
# Individual Minecraft servers
# ---------------------------------------------------------------------------
#
while IFS= read -r SERVER; do
SERVER_ID="$(
printf '%s' "$SERVER" |
jq -r '.server_id // empty'
)"
SERVER_NAME="$(
printf '%s' "$SERVER" |
jq -r '.server_name // "Unknown"'
)"
SERVER_PORT="$(
printf '%s' "$SERVER" |
jq -r '.server_port // 0'
)"
AUTO_START="$(
printf '%s' "$SERVER" |
jq -r '.auto_start // false'
)"
CRASH_DETECTION="$(
printf '%s' "$SERVER" |
jq -r '.crash_detection // false'
)"
COUNT_PLAYERS="$(
printf '%s' "$SERVER" |
jq -r '.count_players // false'
)"
SHOW_STATUS="$(
printf '%s' "$SERVER" |
jq -r '.show_status // true'
)"
if [[ "$IGNORE_HIDDEN_SERVERS" == "yes" && "$SHOW_STATUS" == "false" ]]; then
continue
fi
SERVER_NAME="${SERVER_NAME//\"/\'}"
if [[ -z "$SERVER_ID" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Server entry does not contain a server ID"
continue
fi
#
# -----------------------------------------------------------------------
# Runtime statistics
# -----------------------------------------------------------------------
#
STATS_RESPONSE="$(
curl \
"${CURL_OPTS[@]}" \
-H "Authorization: Bearer ${TOKEN}" \
"${CRAFTY_URL%/}/api/v2/servers/${SERVER_ID}/stats" \
2>/dev/null
)"
STATS_RC=$?
if [[ $STATS_RC -ne 0 || -z "$STATS_RESPONSE" ]]; then
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Unable to retrieve Crafty server statistics"
continue
fi
if ! printf '%s' "$STATS_RESPONSE" | jq -e . >/dev/null 2>&1; then
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Statistics API returned invalid JSON"
continue
fi
STATS_STATUS="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.status // empty'
)"
if [[ "$STATS_STATUS" != "ok" ]]; then
STATS_ERROR="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.error_data // .error // "unknown API error"'
)"
printf '%s\n' \
"${UNKNOWN} \"Minecraft ${SERVER_NAME}\" - Crafty statistics API error: ${STATS_ERROR}"
continue
fi
#
# -----------------------------------------------------------------------
# Runtime values
# -----------------------------------------------------------------------
#
RUNNING="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.running // false'
)"
CRASHED="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.crashed // false'
)"
UPDATING="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.updating // false'
)"
WAITING_START="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.waiting_start // false'
)"
IMPORTING="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.importing // false'
)"
FIRST_RUN="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.first_run // false'
)"
CPU="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.cpu // 0'
)"
MEMORY="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.mem // 0'
)"
MEMORY_PERCENT="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '.data.mem_percent // 0'
)"
PLAYERS_ONLINE="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.online | type) == "number"
then .data.online
else 0
end
'
)"
PLAYERS_MAX="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.max | type) == "number"
then .data.max
else 0
end
'
)"
WORLD_NAME="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.world_name // "") == ""
then "unknown"
else .data.world_name
end
'
)"
WORLD_SIZE="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (.data.world_size // "") == ""
then "unknown"
else .data.world_size
end
'
)"
MC_VERSION="$(
printf '%s' "$STATS_RESPONSE" |
jq -r '
if (
.data.version == false or
.data.version == null or
.data.version == ""
)
then ""
else (.data.version | tostring)
end
'
)"
#
# -----------------------------------------------------------------------
# Sanitize performance values
# -----------------------------------------------------------------------
#
if ! [[ "$CPU" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
CPU=0
fi
if ! [[ "$MEMORY" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
MEMORY=0
fi
if ! [[ "$MEMORY_PERCENT" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
MEMORY_PERCENT=0
fi
if ! [[ "$PLAYERS_ONLINE" =~ ^[0-9]+$ ]]; then
PLAYERS_ONLINE=0
fi
if ! [[ "$PLAYERS_MAX" =~ ^[0-9]+$ ]]; then
PLAYERS_MAX=0
fi
#
# -----------------------------------------------------------------------
# Determine CheckMK state
# -----------------------------------------------------------------------
#
STATE=$OK
STATUS_TEXT="Stopped"
if [[ "$CRASHED" == "true" ]]; then
STATE=$CRIT
STATUS_TEXT="Crashed"
elif [[ "$UPDATING" == "true" ]]; then
STATUS_TEXT="Updating"
elif [[ "$IMPORTING" == "true" ]]; then
STATUS_TEXT="Importing"
elif [[ "$WAITING_START" == "true" ]]; then
STATUS_TEXT="Waiting to start"
elif [[ "$RUNNING" == "true" ]]; then
STATUS_TEXT="Running"
fi
#
# -----------------------------------------------------------------------
# Performance data
# -----------------------------------------------------------------------
#
PERFDATA="cpu=${CPU}%;;;0;100|memory=${MEMORY};;;0|memory_percent=${MEMORY_PERCENT}%;;;0;100"
if [[ "$COUNT_PLAYERS" == "true" ]]; then
if [[ "$PLAYERS_MAX" -gt 0 ]]; then
PERFDATA="${PERFDATA}|players=${PLAYERS_ONLINE};;;0;${PLAYERS_MAX}"
else
PERFDATA="${PERFDATA}|players=${PLAYERS_ONLINE};;;0"
fi
fi
#
# -----------------------------------------------------------------------
# Human-readable output
# -----------------------------------------------------------------------
#
DETAILS="$STATUS_TEXT"
if [[ "$RUNNING" == "true" ]]; then
if [[ "$COUNT_PLAYERS" == "true" ]]; then
if [[ "$PLAYERS_MAX" -gt 0 ]]; then
DETAILS="${DETAILS} - players ${PLAYERS_ONLINE}/${PLAYERS_MAX}"
else
DETAILS="${DETAILS} - players ${PLAYERS_ONLINE}"
fi
fi
if [[ -n "$MC_VERSION" ]]; then
DETAILS="${DETAILS}, version ${MC_VERSION}"
fi
DETAILS="${DETAILS}, CPU ${CPU}%, memory ${MEMORY_PERCENT}%"
fi
if [[ "$WORLD_NAME" != "unknown" ]]; then
DETAILS="${DETAILS}, world ${WORLD_NAME}"
fi
if [[ "$WORLD_SIZE" != "unknown" ]]; then
DETAILS="${DETAILS} (${WORLD_SIZE})"
fi
DETAILS="${DETAILS}, port ${SERVER_PORT}"
if [[ "$AUTO_START" == "true" ]]; then
DETAILS="${DETAILS}, auto-start enabled"
fi
if [[ "$CRASH_DETECTION" == "true" ]]; then
DETAILS="${DETAILS}, crash detection enabled"
fi
if [[ "$FIRST_RUN" == "true" ]]; then
DETAILS="${DETAILS}, first-run flag set"
fi
printf '%s\n' \
"${STATE} \"Minecraft ${SERVER_NAME}\" ${PERFDATA} ${DETAILS}"
done < <(
printf '%s' "$SERVERS_RESPONSE" |
jq -c '.data[]'
)
exit 0