Created
June 11, 2026 11:26
-
-
Save Jensderond/c802f24e7852f1b0883cb3dcff7bf501 to your computer and use it in GitHub Desktop.
meili-status.sh — Check Meilisearch indexes and document counts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # meili-status.sh — Check Meilisearch indexes and document counts. | |
| # | |
| # Talks directly to the Meilisearch HTTP API using the master key, so it needs | |
| # nothing from Craft/DDEV. Use it to verify a migration/reindex finished: | |
| # it lists every index, how many documents each holds, and whether any index | |
| # is still indexing. | |
| # | |
| # Usage (on the server, where Meilisearch listens on localhost:7700): | |
| # MEILI_KEY=<master-key> ./meili-status.sh | |
| # | |
| # Or pass the key as a flag: | |
| # ./meili-status.sh --key <master-key> | |
| # | |
| # Optional: | |
| # --host http://... Override host (default: http://localhost:7700) | |
| # --prefix dev Only show indexes starting with this prefix | |
| # --watch Refresh every 5s until nothing is indexing, then exit | |
| # | |
| # Requirements: curl. (jq is used for pretty output if available, but not required.) | |
| set -euo pipefail | |
| HOST="${MEILI_HOST:-http://localhost:7700}" | |
| KEY="${MEILI_KEY:-}" | |
| PREFIX="" | |
| WATCH=0 | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| --host) HOST="$2"; shift 2 ;; | |
| --key) KEY="$2"; shift 2 ;; | |
| --prefix) PREFIX="$2"; shift 2 ;; | |
| --watch) WATCH=1; shift ;; | |
| -h|--help) | |
| grep '^#' "$0" | sed 's/^# \{0,1\}//' | |
| exit 0 ;; | |
| *) echo "Unknown argument: $1" >&2; exit 1 ;; | |
| esac | |
| done | |
| if [[ -z "$KEY" ]]; then | |
| echo "Error: set MEILI_KEY (env var or --key flag) to the Meilisearch master key." >&2 | |
| echo "Host defaults to ${HOST}; override with MEILI_HOST or --host." >&2 | |
| echo "Run with --help for usage." >&2 | |
| exit 1 | |
| fi | |
| HOST="${HOST%/}" # strip trailing slash | |
| have_jq=0 | |
| if command -v jq >/dev/null 2>&1; then have_jq=1; fi | |
| fetch() { | |
| # $1 = path; returns body, fails on non-2xx | |
| curl -fsS -H "Authorization: Bearer ${KEY}" "${HOST}${1}" | |
| } | |
| print_status() { | |
| echo "Meilisearch @ ${HOST}" | |
| # Version / health sanity check. | |
| if version_json=$(fetch "/version" 2>/dev/null); then | |
| if [[ $have_jq -eq 1 ]]; then | |
| echo "Version: $(echo "$version_json" | jq -r '.pkgVersion')" | |
| fi | |
| else | |
| echo "Error: could not reach Meilisearch or master key rejected (check /version)." >&2 | |
| exit 2 | |
| fi | |
| echo "----------------------------------------------------------------------" | |
| stats_json=$(fetch "/stats") | |
| if [[ $have_jq -eq 1 ]]; then | |
| printf "%-45s %12s %s\n" "INDEX" "DOCUMENTS" "STATUS" | |
| echo "$stats_json" | jq -r --arg p "$PREFIX" ' | |
| .indexes | |
| | to_entries | |
| | map(select($p == "" or (.key | startswith($p)))) | |
| | sort_by(.key) | |
| | .[] | |
| | [ .key, | |
| (.value.numberOfDocuments | tostring), | |
| (if .value.isIndexing then "INDEXING…" else "ready" end) | |
| ] | @tsv' \ | |
| | while IFS=$'\t' read -r name docs status; do | |
| printf "%-45s %12s %s\n" "$name" "$docs" "$status" | |
| done | |
| total=$(echo "$stats_json" | jq -r '.databaseSize // 0') | |
| indexing=$(echo "$stats_json" | jq -r '[.indexes[].isIndexing] | any') | |
| echo "----------------------------------------------------------------------" | |
| echo "Database size: $(( total / 1024 / 1024 )) MB" | |
| if [[ "$indexing" == "true" ]]; then | |
| echo "Overall: at least one index is still INDEXING." | |
| else | |
| echo "Overall: all indexes ready." | |
| fi | |
| else | |
| # No jq: dump raw JSON, still useful for the sysadmin. | |
| echo "(jq not installed — showing raw /stats JSON)" | |
| echo "$stats_json" | |
| fi | |
| } | |
| if [[ $WATCH -eq 1 && $have_jq -eq 1 ]]; then | |
| while true; do | |
| clear | |
| print_status | |
| indexing=$(fetch "/stats" | jq -r '[.indexes[].isIndexing] | any') | |
| [[ "$indexing" == "false" ]] && { echo; echo "Done — nothing indexing."; break; } | |
| sleep 5 | |
| done | |
| else | |
| print_status | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment