Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
@@ -0,0 +1,573 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#####################################################################################
|
||||
#### database-smoke-tests.sh — Verify database health ####
|
||||
#### Checks connectivity, auth, replication, backup age, bloat, connections. ####
|
||||
#### Supports: PostgreSQL, MySQL/MariaDB, Redis ####
|
||||
#### ####
|
||||
#### Author: Phil Connor ####
|
||||
#### Contact: contact@mylinux.work ####
|
||||
#### License: MIT ####
|
||||
#### Version: 1.0 ####
|
||||
#### ####
|
||||
#### Usage: DB_TYPE=postgresql DB_HOST=localhost ./database-smoke-tests.sh ####
|
||||
#### DB_TYPE=redis REDIS_HOST=localhost ./database-smoke-tests.sh ####
|
||||
#### ####
|
||||
#### See --help for all options. ####
|
||||
#####################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Help
|
||||
# ---------------------------------------------------------------------------
|
||||
show_help() {
|
||||
cat <<'EOF'
|
||||
database-smoke-tests.sh — Database health smoke testing
|
||||
|
||||
ENVIRONMENT VARIABLES:
|
||||
DB_TYPE (required) postgresql | mysql | redis
|
||||
DB_HOST Database host (default: localhost)
|
||||
DB_PORT Database port (default: auto — 5432/3306/6379)
|
||||
DB_USER Database user (default: postgres | root | "")
|
||||
DB_PASS Database password (default: "")
|
||||
DB_NAME Database name (default: postgres | mysql)
|
||||
|
||||
REDIS_HOST Redis host (falls back to DB_HOST)
|
||||
REDIS_PORT Redis port (falls back to DB_PORT)
|
||||
REDIS_AUTH Redis auth (falls back to DB_PASS)
|
||||
|
||||
MAX_REPLICATION_LAG_S Max replication lag in seconds (default: 30)
|
||||
MAX_BACKUP_AGE_H Max backup / last-save age in hours (default: 26)
|
||||
MAX_CONNECTIONS_PCT Connection usage threshold % (default: 80)
|
||||
SKIP_REPLICATION Skip replication checks (default: false)
|
||||
SKIP_BACKUP_AGE Skip backup-age checks (default: false)
|
||||
|
||||
OUTPUT_FORMAT text | tap (default: text)
|
||||
COLOR auto | always | never (default: auto)
|
||||
VERBOSE true | false (default: false)
|
||||
|
||||
EXAMPLES:
|
||||
DB_TYPE=postgresql DB_HOST=db1 DB_PASS=secret ./database-smoke-tests.sh
|
||||
DB_TYPE=mysql DB_HOST=db2 DB_USER=app DB_NAME=mydb ./database-smoke-tests.sh
|
||||
DB_TYPE=redis REDIS_HOST=cache1 REDIS_AUTH=pass ./database-smoke-tests.sh
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
[[ "${1:-}" == "--help" || "${1:-}" == "-h" ]] && show_help
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Environment defaults
|
||||
# ---------------------------------------------------------------------------
|
||||
DB_TYPE="${DB_TYPE:-}"
|
||||
DB_HOST="${DB_HOST:-localhost}"
|
||||
DB_PORT="${DB_PORT:-}"
|
||||
DB_USER="${DB_USER:-}"
|
||||
DB_PASS="${DB_PASS:-}"
|
||||
DB_NAME="${DB_NAME:-}"
|
||||
|
||||
REDIS_HOST="${REDIS_HOST:-$DB_HOST}"
|
||||
REDIS_PORT="${REDIS_PORT:-${DB_PORT:-6379}}"
|
||||
REDIS_AUTH="${REDIS_AUTH:-$DB_PASS}"
|
||||
|
||||
MAX_REPLICATION_LAG_S="${MAX_REPLICATION_LAG_S:-30}"
|
||||
MAX_BACKUP_AGE_H="${MAX_BACKUP_AGE_H:-26}"
|
||||
MAX_CONNECTIONS_PCT="${MAX_CONNECTIONS_PCT:-80}"
|
||||
SKIP_REPLICATION="${SKIP_REPLICATION:-false}"
|
||||
SKIP_BACKUP_AGE="${SKIP_BACKUP_AGE:-false}"
|
||||
|
||||
OUTPUT_FORMAT="${OUTPUT_FORMAT:-text}"
|
||||
COLOR="${COLOR:-auto}"
|
||||
VERBOSE="${VERBOSE:-false}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Apply per-engine defaults after DB_TYPE is known
|
||||
# ---------------------------------------------------------------------------
|
||||
apply_defaults() {
|
||||
case "$DB_TYPE" in
|
||||
postgresql)
|
||||
DB_PORT="${DB_PORT:-5432}"
|
||||
DB_USER="${DB_USER:-postgres}"
|
||||
DB_NAME="${DB_NAME:-postgres}"
|
||||
;;
|
||||
mysql)
|
||||
DB_PORT="${DB_PORT:-3306}"
|
||||
DB_USER="${DB_USER:-root}"
|
||||
DB_NAME="${DB_NAME:-mysql}"
|
||||
;;
|
||||
redis)
|
||||
REDIS_PORT="${REDIS_PORT:-6379}"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: DB_TYPE must be one of: postgresql, mysql, redis" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Colour setup
|
||||
# ---------------------------------------------------------------------------
|
||||
setup_colors() {
|
||||
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" RESET=""
|
||||
local use_color=false
|
||||
case "$COLOR" in
|
||||
always) use_color=true ;;
|
||||
never) use_color=false ;;
|
||||
auto) [[ -t 1 ]] && use_color=true ;;
|
||||
esac
|
||||
if $use_color; then
|
||||
RED=$'\033[0;31m'
|
||||
GREEN=$'\033[0;32m'
|
||||
YELLOW=$'\033[1;33m'
|
||||
BLUE=$'\033[0;34m'
|
||||
BOLD=$'\033[1m'
|
||||
RESET=$'\033[0m'
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Counters
|
||||
# ---------------------------------------------------------------------------
|
||||
PASS_COUNT=0
|
||||
FAIL_COUNT=0
|
||||
SKIP_COUNT=0
|
||||
TEST_NUM=0
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# run_test "description" command...
|
||||
# ---------------------------------------------------------------------------
|
||||
run_test() {
|
||||
local desc="$1"; shift
|
||||
TEST_NUM=$((TEST_NUM + 1))
|
||||
local output rc
|
||||
output=$("$@" 2>&1) && rc=0 || rc=$?
|
||||
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
PASS_COUNT=$((PASS_COUNT + 1))
|
||||
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
|
||||
echo "ok $TEST_NUM - $desc"
|
||||
else
|
||||
echo " ${GREEN}PASS${RESET} $desc"
|
||||
fi
|
||||
elif [[ $rc -eq 2 ]]; then
|
||||
SKIP_COUNT=$((SKIP_COUNT + 1))
|
||||
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
|
||||
echo "ok $TEST_NUM - $desc # SKIP ${output:-skipped}"
|
||||
else
|
||||
echo " ${YELLOW}SKIP${RESET} $desc — ${output:-skipped}"
|
||||
fi
|
||||
else
|
||||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||||
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
|
||||
echo "not ok $TEST_NUM - $desc"
|
||||
[[ -n "$output" ]] && echo "# $output"
|
||||
else
|
||||
echo " ${RED}FAIL${RESET} $desc"
|
||||
[[ -n "$output" ]] && echo " $output"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$VERBOSE" == "true" && -n "$output" && $rc -eq 0 ]]; then
|
||||
echo " ${BLUE}→${RESET} $output"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# skip_test "description" "reason"
|
||||
# ---------------------------------------------------------------------------
|
||||
skip_test() {
|
||||
local desc="$1" reason="${2:-skipped}"
|
||||
TEST_NUM=$((TEST_NUM + 1))
|
||||
SKIP_COUNT=$((SKIP_COUNT + 1))
|
||||
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
|
||||
echo "ok $TEST_NUM - $desc # SKIP $reason"
|
||||
else
|
||||
echo " ${YELLOW}SKIP${RESET} $desc — $reason"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# check_port host port [timeout]
|
||||
# ---------------------------------------------------------------------------
|
||||
check_port() {
|
||||
local host="$1" port="$2" timeout="${3:-5}"
|
||||
if command -v nc &>/dev/null; then
|
||||
nc -z -w "$timeout" "$host" "$port" 2>/dev/null
|
||||
elif [[ -e /dev/tcp ]]; then
|
||||
timeout "$timeout" bash -c "echo >/dev/tcp/$host/$port" 2>/dev/null
|
||||
else
|
||||
(echo >/dev/tcp/"$host"/"$port") 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helper: build psql / mysql invocations
|
||||
# ---------------------------------------------------------------------------
|
||||
run_psql() {
|
||||
PGPASSWORD="$DB_PASS" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" \
|
||||
-d "${1:-$DB_NAME}" -t -A -c "$2" 2>&1
|
||||
}
|
||||
|
||||
run_mysql() {
|
||||
MYSQL_PWD="$DB_PASS" mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" \
|
||||
-D "${1:-$DB_NAME}" -N -s -e "$2" 2>&1
|
||||
}
|
||||
|
||||
run_redis() {
|
||||
local auth_args=()
|
||||
[[ -n "$REDIS_AUTH" ]] && auth_args=(-a "$REDIS_AUTH" --no-auth-warning)
|
||||
redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" "${auth_args[@]}" "$@" 2>&1
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# PostgreSQL tests
|
||||
# ===========================================================================
|
||||
run_postgresql_tests() {
|
||||
echo "${BOLD}PostgreSQL smoke tests — ${DB_HOST}:${DB_PORT}${RESET}"
|
||||
echo ""
|
||||
|
||||
# 1. TCP connectivity
|
||||
run_test "TCP connectivity to ${DB_HOST}:${DB_PORT}" \
|
||||
check_port "$DB_HOST" "$DB_PORT"
|
||||
|
||||
# 2. Authentication
|
||||
run_test "Authentication as ${DB_USER}" \
|
||||
bash -c 'PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c "SELECT 1" >/dev/null'
|
||||
|
||||
# 3. Version
|
||||
run_test "Server version" \
|
||||
bash -c '
|
||||
ver=$(PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c "SHOW server_version" 2>&1)
|
||||
echo "PostgreSQL $ver"
|
||||
'
|
||||
|
||||
# 4. Database accessible
|
||||
run_test "Database '${DB_NAME}' accessible" \
|
||||
bash -c 'PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c "SELECT current_database()" >/dev/null'
|
||||
|
||||
# 5. Replication lag
|
||||
if [[ "$SKIP_REPLICATION" == "true" ]]; then
|
||||
skip_test "Replication lag" "SKIP_REPLICATION=true"
|
||||
else
|
||||
run_test "Replication lag < ${MAX_REPLICATION_LAG_S}s" \
|
||||
bash -c '
|
||||
is_replica=$(PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c "SELECT pg_is_in_recovery()" 2>&1)
|
||||
if [[ "$is_replica" == "t" ]]; then
|
||||
lag=$(PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c \
|
||||
"SELECT COALESCE(EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::int, 0)" 2>&1)
|
||||
if [[ "$lag" -gt '"$MAX_REPLICATION_LAG_S"' ]]; then
|
||||
echo "lag=${lag}s exceeds ${'"$MAX_REPLICATION_LAG_S"'}s"; exit 1
|
||||
fi
|
||||
echo "replica lag=${lag}s"
|
||||
else
|
||||
echo "not a replica"; exit 2
|
||||
fi
|
||||
'
|
||||
fi
|
||||
|
||||
# 6. Connection count
|
||||
run_test "Connection usage < ${MAX_CONNECTIONS_PCT}%" \
|
||||
bash -c '
|
||||
read -r used max_c <<< $(PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c \
|
||||
"SELECT sum(numbackends), (SELECT setting::int FROM pg_settings WHERE name='"'"'max_connections'"'"') FROM pg_stat_database" 2>&1 | tr "|" " ")
|
||||
pct=$((used * 100 / max_c))
|
||||
if [[ $pct -ge '"$MAX_CONNECTIONS_PCT"' ]]; then
|
||||
echo "${used}/${max_c} (${pct}%)"; exit 1
|
||||
fi
|
||||
echo "${used}/${max_c} (${pct}%)"
|
||||
'
|
||||
|
||||
# 7. Long-running queries
|
||||
run_test "No queries running > 300s" \
|
||||
bash -c '
|
||||
count=$(PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c \
|
||||
"SELECT count(*) FROM pg_stat_activity WHERE state='"'"'active'"'"' AND now()-query_start > interval '"'"'300 seconds'"'"' AND pid <> pg_backend_pid()" 2>&1)
|
||||
if [[ "$count" -gt 0 ]]; then
|
||||
echo "${count} long-running queries found"; exit 1
|
||||
fi
|
||||
echo "none"
|
||||
'
|
||||
|
||||
# 8. Table bloat
|
||||
run_test "Table bloat (dead tuple ratio < 20%)" \
|
||||
bash -c '
|
||||
worst=$(PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c \
|
||||
"SELECT schemaname||'"'"'.'"'"'||relname||'"'"' '"'"'||round(100.0*n_dead_tup/(n_live_tup+n_dead_tup+1),1)||'"'"'%'"'"' FROM pg_stat_user_tables WHERE n_live_tup+n_dead_tup>1000 AND 100.0*n_dead_tup/(n_live_tup+n_dead_tup+1)>20 ORDER BY n_dead_tup DESC LIMIT 3" 2>&1)
|
||||
if [[ -n "$worst" ]]; then
|
||||
echo "bloated: $worst"; exit 1
|
||||
fi
|
||||
echo "ok"
|
||||
'
|
||||
|
||||
# 9. Disk usage
|
||||
run_test "Disk usage for '${DB_NAME}'" \
|
||||
bash -c '
|
||||
size=$(PGPASSWORD="'"$DB_PASS"'" psql -h "'"$DB_HOST"'" -p "'"$DB_PORT"'" -U "'"$DB_USER"'" -d "'"$DB_NAME"'" -t -A -c \
|
||||
"SELECT pg_size_pretty(pg_database_size(current_database()))" 2>&1)
|
||||
echo "$size"
|
||||
'
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# MySQL / MariaDB tests
|
||||
# ===========================================================================
|
||||
run_mysql_tests() {
|
||||
echo "${BOLD}MySQL smoke tests — ${DB_HOST}:${DB_PORT}${RESET}"
|
||||
echo ""
|
||||
|
||||
# 1. TCP connectivity
|
||||
run_test "TCP connectivity to ${DB_HOST}:${DB_PORT}" \
|
||||
check_port "$DB_HOST" "$DB_PORT"
|
||||
|
||||
# 2. Authentication
|
||||
run_test "Authentication as ${DB_USER}" \
|
||||
bash -c 'MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -e "SELECT 1" >/dev/null'
|
||||
|
||||
# 3. Version
|
||||
run_test "Server version" \
|
||||
bash -c '
|
||||
ver=$(MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -N -s -e "SELECT version()" 2>&1)
|
||||
echo "MySQL $ver"
|
||||
'
|
||||
|
||||
# 4. Database accessible
|
||||
run_test "Database '${DB_NAME}' accessible" \
|
||||
bash -c 'MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -D "'"$DB_NAME"'" -e "SELECT 1" >/dev/null'
|
||||
|
||||
# 5. Replication lag
|
||||
if [[ "$SKIP_REPLICATION" == "true" ]]; then
|
||||
skip_test "Replication lag" "SKIP_REPLICATION=true"
|
||||
else
|
||||
run_test "Replication lag < ${MAX_REPLICATION_LAG_S}s" \
|
||||
bash -c '
|
||||
status=$(MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -N -s -e "SHOW REPLICA STATUS\G" 2>&1)
|
||||
if [[ -z "$status" ]]; then
|
||||
status=$(MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -N -s -e "SHOW SLAVE STATUS\G" 2>&1)
|
||||
fi
|
||||
if [[ -z "$status" ]]; then
|
||||
echo "not a replica"; exit 2
|
||||
fi
|
||||
lag=$(echo "$status" | grep -i "Seconds_Behind" | awk "{print \$NF}")
|
||||
if [[ "$lag" == "NULL" || -z "$lag" ]]; then
|
||||
echo "replication not running (lag=NULL)"; exit 1
|
||||
fi
|
||||
if [[ "$lag" -gt '"$MAX_REPLICATION_LAG_S"' ]]; then
|
||||
echo "lag=${lag}s exceeds '"$MAX_REPLICATION_LAG_S"'s"; exit 1
|
||||
fi
|
||||
echo "replica lag=${lag}s"
|
||||
'
|
||||
fi
|
||||
|
||||
# 6. Connection count
|
||||
run_test "Connection usage < ${MAX_CONNECTIONS_PCT}%" \
|
||||
bash -c '
|
||||
used=$(MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -N -s -e "SELECT count(*) FROM information_schema.processlist" 2>&1)
|
||||
max_c=$(MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -N -s -e "SHOW VARIABLES LIKE '"'"'max_connections'"'"'" 2>&1 | awk "{print \$2}")
|
||||
pct=$((used * 100 / max_c))
|
||||
if [[ $pct -ge '"$MAX_CONNECTIONS_PCT"' ]]; then
|
||||
echo "${used}/${max_c} (${pct}%)"; exit 1
|
||||
fi
|
||||
echo "${used}/${max_c} (${pct}%)"
|
||||
'
|
||||
|
||||
# 7. Slow query log
|
||||
run_test "Slow query log enabled" \
|
||||
bash -c '
|
||||
val=$(MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -N -s -e "SHOW VARIABLES LIKE '"'"'slow_query_log'"'"'" 2>&1 | awk "{print \$2}")
|
||||
if [[ "$val" != "ON" ]]; then
|
||||
echo "slow_query_log=$val"; exit 1
|
||||
fi
|
||||
echo "enabled"
|
||||
'
|
||||
|
||||
# 8. Binary log space
|
||||
run_test "Binary log disk usage" \
|
||||
bash -c '
|
||||
logs=$(MYSQL_PWD="'"$DB_PASS"'" mysql -h "'"$DB_HOST"'" -P "'"$DB_PORT"'" -u "'"$DB_USER"'" -N -s -e "SHOW BINARY LOGS" 2>&1)
|
||||
if [[ "$logs" == *"not enabled"* || -z "$logs" ]]; then
|
||||
echo "binary logging disabled"; exit 2
|
||||
fi
|
||||
total=$(echo "$logs" | awk "{s+=\$2} END {printf \"%.1f MB\", s/1048576}")
|
||||
echo "$total"
|
||||
'
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# Redis tests
|
||||
# ===========================================================================
|
||||
run_redis_tests() {
|
||||
echo "${BOLD}Redis smoke tests — ${REDIS_HOST}:${REDIS_PORT}${RESET}"
|
||||
echo ""
|
||||
|
||||
local auth_args=()
|
||||
[[ -n "$REDIS_AUTH" ]] && auth_args=(-a "$REDIS_AUTH" --no-auth-warning)
|
||||
|
||||
# 1. TCP connectivity
|
||||
run_test "TCP connectivity to ${REDIS_HOST}:${REDIS_PORT}" \
|
||||
check_port "$REDIS_HOST" "$REDIS_PORT"
|
||||
|
||||
# 2. PING/PONG
|
||||
run_test "PING/PONG" \
|
||||
bash -c '
|
||||
reply=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' PING 2>&1)
|
||||
if [[ "$reply" != "PONG" ]]; then
|
||||
echo "got: $reply"; exit 1
|
||||
fi
|
||||
echo "PONG"
|
||||
'
|
||||
|
||||
# 3. Server info
|
||||
run_test "Server info" \
|
||||
bash -c '
|
||||
info=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' INFO server 2>&1)
|
||||
ver=$(echo "$info" | grep "^redis_version:" | cut -d: -f2 | tr -d "\r")
|
||||
up=$(echo "$info" | grep "^uptime_in_days:" | cut -d: -f2 | tr -d "\r")
|
||||
echo "v${ver}, uptime ${up}d"
|
||||
'
|
||||
|
||||
# 4. Memory usage
|
||||
run_test "Memory usage vs maxmemory" \
|
||||
bash -c '
|
||||
info=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' INFO memory 2>&1)
|
||||
used=$(echo "$info" | grep "^used_memory_human:" | cut -d: -f2 | tr -d "\r")
|
||||
max_raw=$(echo "$info" | grep "^maxmemory:" | cut -d: -f2 | tr -d "\r")
|
||||
max_h=$(echo "$info" | grep "^maxmemory_human:" | cut -d: -f2 | tr -d "\r")
|
||||
if [[ "$max_raw" == "0" ]]; then
|
||||
echo "used=${used}, maxmemory=unlimited"; exit 0
|
||||
fi
|
||||
echo "used=${used}, max=${max_h}"
|
||||
'
|
||||
|
||||
# 5. Connected clients
|
||||
run_test "Connected clients" \
|
||||
bash -c '
|
||||
info=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' INFO clients 2>&1)
|
||||
count=$(echo "$info" | grep "^connected_clients:" | cut -d: -f2 | tr -d "\r")
|
||||
echo "${count} clients"
|
||||
'
|
||||
|
||||
# 6. Replication status
|
||||
if [[ "$SKIP_REPLICATION" == "true" ]]; then
|
||||
skip_test "Replication status" "SKIP_REPLICATION=true"
|
||||
else
|
||||
run_test "Replication status" \
|
||||
bash -c '
|
||||
info=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' INFO replication 2>&1)
|
||||
role=$(echo "$info" | grep "^role:" | cut -d: -f2 | tr -d "\r")
|
||||
if [[ "$role" == "master" ]]; then
|
||||
slaves=$(echo "$info" | grep "^connected_slaves:" | cut -d: -f2 | tr -d "\r")
|
||||
echo "role=master, replicas=${slaves}"
|
||||
elif [[ "$role" == "slave" ]]; then
|
||||
link=$(echo "$info" | grep "^master_link_status:" | cut -d: -f2 | tr -d "\r")
|
||||
if [[ "$link" != "up" ]]; then
|
||||
echo "replica link $link"; exit 1
|
||||
fi
|
||||
echo "role=replica, link=up"
|
||||
else
|
||||
echo "role=$role"
|
||||
fi
|
||||
'
|
||||
fi
|
||||
|
||||
# 7. Last save time
|
||||
if [[ "$SKIP_BACKUP_AGE" == "true" ]]; then
|
||||
skip_test "Last RDB/AOF save" "SKIP_BACKUP_AGE=true"
|
||||
else
|
||||
run_test "Last RDB save < ${MAX_BACKUP_AGE_H}h" \
|
||||
bash -c '
|
||||
info=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' INFO persistence 2>&1)
|
||||
last_save=$(echo "$info" | grep "^rdb_last_save_time:" | cut -d: -f2 | tr -d "\r")
|
||||
if [[ -z "$last_save" || "$last_save" == "0" ]]; then
|
||||
echo "no RDB save recorded"; exit 2
|
||||
fi
|
||||
now=$(date +%s)
|
||||
age_h=$(( (now - last_save) / 3600 ))
|
||||
if [[ $age_h -gt '"$MAX_BACKUP_AGE_H"' ]]; then
|
||||
echo "last save ${age_h}h ago (max '"$MAX_BACKUP_AGE_H"'h)"; exit 1
|
||||
fi
|
||||
echo "last save ${age_h}h ago"
|
||||
'
|
||||
fi
|
||||
|
||||
# 8. Keyspace
|
||||
run_test "Keyspace info" \
|
||||
bash -c '
|
||||
info=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' INFO keyspace 2>&1)
|
||||
dbs=$(echo "$info" | grep "^db[0-9]" || true)
|
||||
if [[ -z "$dbs" ]]; then
|
||||
echo "no databases with keys"; exit 2
|
||||
fi
|
||||
total=0
|
||||
while IFS= read -r line; do
|
||||
keys=$(echo "$line" | grep -oP "keys=\K[0-9]+")
|
||||
total=$((total + keys))
|
||||
done <<< "$dbs"
|
||||
echo "${total} keys across $(echo "$dbs" | wc -l) database(s)"
|
||||
'
|
||||
|
||||
# 9. Eviction policy
|
||||
run_test "Eviction policy" \
|
||||
bash -c '
|
||||
policy=$(redis-cli -h "'"$REDIS_HOST"'" -p "'"$REDIS_PORT"'" '"$(printf '%q ' "${auth_args[@]}")"' CONFIG GET maxmemory-policy 2>&1 | tail -1)
|
||||
echo "policy=$policy"
|
||||
'
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# Summary
|
||||
# ===========================================================================
|
||||
print_summary() {
|
||||
local total=$((PASS_COUNT + FAIL_COUNT + SKIP_COUNT))
|
||||
echo ""
|
||||
if [[ "$OUTPUT_FORMAT" == "tap" ]]; then
|
||||
echo "1..$total"
|
||||
echo "# pass $PASS_COUNT"
|
||||
echo "# fail $FAIL_COUNT"
|
||||
echo "# skip $SKIP_COUNT"
|
||||
else
|
||||
echo "${BOLD}───────────────────────────────────────${RESET}"
|
||||
echo " ${GREEN}PASS${RESET} $PASS_COUNT"
|
||||
echo " ${RED}FAIL${RESET} $FAIL_COUNT"
|
||||
echo " ${YELLOW}SKIP${RESET} $SKIP_COUNT"
|
||||
echo " Total $total"
|
||||
echo "${BOLD}───────────────────────────────────────${RESET}"
|
||||
if [[ $FAIL_COUNT -gt 0 ]]; then
|
||||
echo " ${RED}${BOLD}RESULT: FAIL${RESET}"
|
||||
else
|
||||
echo " ${GREEN}${BOLD}RESULT: PASS${RESET}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# Main
|
||||
# ===========================================================================
|
||||
main() {
|
||||
if [[ -z "$DB_TYPE" ]]; then
|
||||
echo "ERROR: DB_TYPE is required (postgresql, mysql, redis)" >&2
|
||||
echo "Run with --help for usage information." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
apply_defaults
|
||||
setup_colors
|
||||
|
||||
case "$DB_TYPE" in
|
||||
postgresql) run_postgresql_tests ;;
|
||||
mysql) run_mysql_tests ;;
|
||||
redis) run_redis_tests ;;
|
||||
*)
|
||||
echo "ERROR: Unsupported DB_TYPE '${DB_TYPE}'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
print_summary
|
||||
|
||||
[[ $FAIL_COUNT -gt 0 ]] && exit 1
|
||||
exit 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user