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,372 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
# Script Name: dovecot-metrics-exporter.sh
|
||||
# Description: Prometheus exporter for Dovecot IMAP/POP3 server metrics
|
||||
#
|
||||
# Collects connection counts, authentication stats, mailbox operations,
|
||||
# process info, and protocol-level metrics from doveadm and Dovecot stats.
|
||||
#
|
||||
# Author: Phil Connor
|
||||
# Contact: contact@mylinux.work
|
||||
# Website: https://mylinux.work
|
||||
# License: MIT
|
||||
# Version: 1.0
|
||||
#
|
||||
# Usage:
|
||||
# # Output to stdout
|
||||
# ./dovecot-metrics-exporter.sh
|
||||
#
|
||||
# # Textfile collector mode (atomic write)
|
||||
# ./dovecot-metrics-exporter.sh --textfile
|
||||
#
|
||||
# # Custom output file
|
||||
# ./dovecot-metrics-exporter.sh -o /path/to/metrics.prom
|
||||
#
|
||||
################################################################################
|
||||
|
||||
# ============================================================================
|
||||
# CONFIGURATION VARIABLES
|
||||
# ============================================================================
|
||||
|
||||
TEXTFILE_DIR="/var/lib/node_exporter"
|
||||
OUTPUT_FILE=""
|
||||
HOSTNAME=$(hostname)
|
||||
|
||||
# ============================================================================
|
||||
# HELPER FUNCTIONS
|
||||
# ============================================================================
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTIONS]
|
||||
|
||||
Export Dovecot IMAP/POP3 server metrics as Prometheus metrics.
|
||||
|
||||
MODES:
|
||||
--textfile Write to node_exporter textfile collector
|
||||
(writes to $TEXTFILE_DIR/dovecot-metrics.prom)
|
||||
|
||||
OPTIONS:
|
||||
-o, --output Output file path (for custom locations)
|
||||
-h, --help Show this help message
|
||||
|
||||
EXAMPLES:
|
||||
$0 # Output to stdout
|
||||
$0 --textfile # Write to textfile collector
|
||||
$0 -o /tmp/dovecot.prom # Write to custom file
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help) show_usage ;;
|
||||
--textfile) OUTPUT_FILE="$TEXTFILE_DIR/dovecot-metrics.prom"; shift ;;
|
||||
-o|--output) OUTPUT_FILE="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Safe integer extraction — returns 0 on failure
|
||||
safe_int() {
|
||||
local val="$1"
|
||||
if [[ "$val" =~ ^[0-9]+$ ]]; then
|
||||
echo "$val"
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# METRIC GENERATION
|
||||
# ============================================================================
|
||||
|
||||
generate_metrics() {
|
||||
local START_TIME
|
||||
START_TIME=$(date +%s.%N)
|
||||
|
||||
# --- Exporter info ---
|
||||
echo "# HELP dovecot_up Exporter status (1=up, 0=down)"
|
||||
echo "# TYPE dovecot_up gauge"
|
||||
|
||||
# Check if Dovecot is running
|
||||
if systemctl is-active --quiet dovecot 2>/dev/null; then
|
||||
echo "dovecot_up 1"
|
||||
else
|
||||
echo "dovecot_up 0"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "# HELP dovecot_exporter_info Exporter version information"
|
||||
echo "# TYPE dovecot_exporter_info gauge"
|
||||
echo 'dovecot_exporter_info{version="1.0"} 1'
|
||||
echo ""
|
||||
|
||||
# --- Dovecot version ---
|
||||
echo "# HELP dovecot_version_info Dovecot version information"
|
||||
echo "# TYPE dovecot_version_info gauge"
|
||||
local dovecot_version
|
||||
dovecot_version=$(dovecot --version 2>/dev/null | awk '{print $1}') || dovecot_version="unknown"
|
||||
echo "dovecot_version_info{version=\"${dovecot_version}\"} 1"
|
||||
echo ""
|
||||
|
||||
# --- Process counts ---
|
||||
echo "# HELP dovecot_processes Number of running Dovecot processes by type"
|
||||
echo "# TYPE dovecot_processes gauge"
|
||||
for proc_type in imap pop3 lmtp managesieve submission auth anvil; do
|
||||
count=$(pgrep -c "dovecot/${proc_type}" 2>/dev/null) || count=0
|
||||
echo "dovecot_processes{type=\"${proc_type}\"} ${count}"
|
||||
done
|
||||
local total_procs
|
||||
total_procs=$(pgrep -c dovecot 2>/dev/null) || total_procs=0
|
||||
echo "dovecot_processes{type=\"total\"} ${total_procs}"
|
||||
echo ""
|
||||
|
||||
# --- Connected users (from doveadm) ---
|
||||
echo "# HELP dovecot_connected_users Number of currently connected users by protocol"
|
||||
echo "# TYPE dovecot_connected_users gauge"
|
||||
local imap_users=0 pop3_users=0 lmtp_users=0 managesieve_users=0
|
||||
if command -v doveadm >/dev/null 2>&1; then
|
||||
imap_users=$(doveadm who -1 2>/dev/null | grep -c 'imap' 2>/dev/null) || imap_users=0
|
||||
pop3_users=$(doveadm who -1 2>/dev/null | grep -c 'pop3' 2>/dev/null) || pop3_users=0
|
||||
lmtp_users=$(doveadm who -1 2>/dev/null | grep -c 'lmtp' 2>/dev/null) || lmtp_users=0
|
||||
managesieve_users=$(doveadm who -1 2>/dev/null | grep -c 'managesieve' 2>/dev/null) || managesieve_users=0
|
||||
fi
|
||||
echo "dovecot_connected_users{protocol=\"imap\"} ${imap_users}"
|
||||
echo "dovecot_connected_users{protocol=\"pop3\"} ${pop3_users}"
|
||||
echo "dovecot_connected_users{protocol=\"lmtp\"} ${lmtp_users}"
|
||||
echo "dovecot_connected_users{protocol=\"managesieve\"} ${managesieve_users}"
|
||||
echo ""
|
||||
|
||||
# --- Total connections (from doveadm who) ---
|
||||
echo "# HELP dovecot_connections_total Total active connections by protocol"
|
||||
echo "# TYPE dovecot_connections_total gauge"
|
||||
local imap_conns=0 pop3_conns=0
|
||||
if command -v doveadm >/dev/null 2>&1; then
|
||||
imap_conns=$(doveadm who -1 2>/dev/null | grep 'imap' | awk '{sum+=$3} END {print sum+0}' 2>/dev/null) || imap_conns=0
|
||||
pop3_conns=$(doveadm who -1 2>/dev/null | grep 'pop3' | awk '{sum+=$3} END {print sum+0}' 2>/dev/null) || pop3_conns=0
|
||||
fi
|
||||
echo "dovecot_connections_total{protocol=\"imap\"} ${imap_conns}"
|
||||
echo "dovecot_connections_total{protocol=\"pop3\"} ${pop3_conns}"
|
||||
echo ""
|
||||
|
||||
# --- Authentication stats from mail.log ---
|
||||
local LOG_FILE="/var/log/mail.log"
|
||||
if [[ ! -f "$LOG_FILE" ]]; then
|
||||
LOG_FILE="/var/log/maillog"
|
||||
fi
|
||||
|
||||
echo "# HELP dovecot_auth_success_total Successful authentication attempts by protocol"
|
||||
echo "# TYPE dovecot_auth_success_total counter"
|
||||
local imap_auth_ok=0 pop3_auth_ok=0
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
imap_auth_ok=$(grep -c 'imap-login: Info: Login:' "$LOG_FILE" 2>/dev/null) || imap_auth_ok=0
|
||||
pop3_auth_ok=$(grep -c 'pop3-login: Info: Login:' "$LOG_FILE" 2>/dev/null) || pop3_auth_ok=0
|
||||
fi
|
||||
echo "dovecot_auth_success_total{protocol=\"imap\"} ${imap_auth_ok}"
|
||||
echo "dovecot_auth_success_total{protocol=\"pop3\"} ${pop3_auth_ok}"
|
||||
echo ""
|
||||
|
||||
echo "# HELP dovecot_auth_failed_total Failed authentication attempts by protocol"
|
||||
echo "# TYPE dovecot_auth_failed_total counter"
|
||||
local imap_auth_fail=0 pop3_auth_fail=0
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
imap_auth_fail=$(grep -c 'imap-login:.*auth failed\|imap-login: Info: Aborted login' "$LOG_FILE" 2>/dev/null) || imap_auth_fail=0
|
||||
pop3_auth_fail=$(grep -c 'pop3-login:.*auth failed\|pop3-login: Info: Aborted login' "$LOG_FILE" 2>/dev/null) || pop3_auth_fail=0
|
||||
fi
|
||||
echo "dovecot_auth_failed_total{protocol=\"imap\"} ${imap_auth_fail}"
|
||||
echo "dovecot_auth_failed_total{protocol=\"pop3\"} ${pop3_auth_fail}"
|
||||
echo ""
|
||||
|
||||
# --- TLS connections ---
|
||||
echo "# HELP dovecot_tls_connections_total TLS connections by status"
|
||||
echo "# TYPE dovecot_tls_connections_total counter"
|
||||
local tls_yes=0 tls_no=0
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
tls_yes=$(grep -c 'Login:.*TLS' "$LOG_FILE" 2>/dev/null) || tls_yes=0
|
||||
tls_no=$(grep 'Login:' "$LOG_FILE" 2>/dev/null | grep -cv 'TLS' 2>/dev/null) || tls_no=0
|
||||
fi
|
||||
echo "dovecot_tls_connections_total{tls=\"yes\"} ${tls_yes}"
|
||||
echo "dovecot_tls_connections_total{tls=\"no\"} ${tls_no}"
|
||||
echo ""
|
||||
|
||||
# --- Authentication methods ---
|
||||
echo "# HELP dovecot_auth_method_total Logins by authentication method"
|
||||
echo "# TYPE dovecot_auth_method_total counter"
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
for method in PLAIN LOGIN CRAM-MD5 DIGEST-MD5; do
|
||||
count=$(grep -c "Login:.*method=${method}" "$LOG_FILE" 2>/dev/null) || count=0
|
||||
echo "dovecot_auth_method_total{method=\"${method}\"} ${count}"
|
||||
done
|
||||
else
|
||||
for method in PLAIN LOGIN CRAM-MD5 DIGEST-MD5; do
|
||||
echo "dovecot_auth_method_total{method=\"${method}\"} 0"
|
||||
done
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- Disconnections ---
|
||||
echo "# HELP dovecot_disconnections_total Client disconnections by reason"
|
||||
echo "# TYPE dovecot_disconnections_total counter"
|
||||
local dc_logout=0 dc_timeout=0 dc_closed=0 dc_internal=0
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
dc_logout=$(grep -c 'Logged out' "$LOG_FILE" 2>/dev/null) || dc_logout=0
|
||||
dc_timeout=$(grep -c 'Disconnected.*Timed out\|Connection timed out' "$LOG_FILE" 2>/dev/null) || dc_timeout=0
|
||||
dc_closed=$(grep -c 'Disconnected.*Connection closed' "$LOG_FILE" 2>/dev/null) || dc_closed=0
|
||||
dc_internal=$(grep -c 'Disconnected.*Internal error' "$LOG_FILE" 2>/dev/null) || dc_internal=0
|
||||
fi
|
||||
echo "dovecot_disconnections_total{reason=\"logout\"} ${dc_logout}"
|
||||
echo "dovecot_disconnections_total{reason=\"timeout\"} ${dc_timeout}"
|
||||
echo "dovecot_disconnections_total{reason=\"connection_closed\"} ${dc_closed}"
|
||||
echo "dovecot_disconnections_total{reason=\"internal_error\"} ${dc_internal}"
|
||||
echo ""
|
||||
|
||||
# --- LMTP delivery stats ---
|
||||
echo "# HELP dovecot_lmtp_deliveries_total LMTP deliveries by status"
|
||||
echo "# TYPE dovecot_lmtp_deliveries_total counter"
|
||||
local lmtp_ok=0 lmtp_reject=0 lmtp_tempfail=0
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
lmtp_ok=$(grep -c 'lmtp.*saved mail' "$LOG_FILE" 2>/dev/null) || lmtp_ok=0
|
||||
lmtp_reject=$(grep -c 'lmtp.*rejected' "$LOG_FILE" 2>/dev/null) || lmtp_reject=0
|
||||
lmtp_tempfail=$(grep -c 'lmtp.*temporary failure\|lmtp.*temp-fail' "$LOG_FILE" 2>/dev/null) || lmtp_tempfail=0
|
||||
fi
|
||||
echo "dovecot_lmtp_deliveries_total{status=\"delivered\"} ${lmtp_ok}"
|
||||
echo "dovecot_lmtp_deliveries_total{status=\"rejected\"} ${lmtp_reject}"
|
||||
echo "dovecot_lmtp_deliveries_total{status=\"tempfail\"} ${lmtp_tempfail}"
|
||||
echo ""
|
||||
|
||||
# --- Sieve stats ---
|
||||
echo "# HELP dovecot_sieve_actions_total Sieve filter actions"
|
||||
echo "# TYPE dovecot_sieve_actions_total counter"
|
||||
local sieve_filed=0 sieve_discard=0 sieve_redirect=0 sieve_reject=0
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
sieve_filed=$(grep -c 'sieve:.*stored mail\|sieve:.*fileinto' "$LOG_FILE" 2>/dev/null) || sieve_filed=0
|
||||
sieve_discard=$(grep -c 'sieve:.*discard' "$LOG_FILE" 2>/dev/null) || sieve_discard=0
|
||||
sieve_redirect=$(grep -c 'sieve:.*redirect' "$LOG_FILE" 2>/dev/null) || sieve_redirect=0
|
||||
sieve_reject=$(grep -c 'sieve:.*reject' "$LOG_FILE" 2>/dev/null) || sieve_reject=0
|
||||
fi
|
||||
echo "dovecot_sieve_actions_total{action=\"filed\"} ${sieve_filed}"
|
||||
echo "dovecot_sieve_actions_total{action=\"discard\"} ${sieve_discard}"
|
||||
echo "dovecot_sieve_actions_total{action=\"redirect\"} ${sieve_redirect}"
|
||||
echo "dovecot_sieve_actions_total{action=\"reject\"} ${sieve_reject}"
|
||||
echo ""
|
||||
|
||||
# --- Dovecot stats (if old_stats or stats plugin enabled) ---
|
||||
# Try doveadm stats dump for Dovecot 2.3+
|
||||
echo "# HELP dovecot_mail_commands_total Mail commands executed"
|
||||
echo "# TYPE dovecot_mail_commands_total counter"
|
||||
local cmds_select=0 cmds_fetch=0 cmds_store=0 cmds_search=0 cmds_copy=0 cmds_expunge=0
|
||||
if command -v doveadm >/dev/null 2>&1; then
|
||||
local stats_output
|
||||
stats_output=$(doveadm stats dump session 2>/dev/null | head -20)
|
||||
if [[ -n "$stats_output" ]]; then
|
||||
cmds_select=$(echo "$stats_output" | awk '{sum+=$4} END {print sum+0}') || cmds_select=0
|
||||
cmds_fetch=$(echo "$stats_output" | awk '{sum+=$5} END {print sum+0}') || cmds_fetch=0
|
||||
fi
|
||||
fi
|
||||
# Fallback: count from logs
|
||||
if [[ -f "$LOG_FILE" ]]; then
|
||||
cmds_copy=$(grep -c 'Copy\|copy' "$LOG_FILE" 2>/dev/null | head -1) || cmds_copy=0
|
||||
cmds_expunge=$(grep -c 'Expunged' "$LOG_FILE" 2>/dev/null) || cmds_expunge=0
|
||||
fi
|
||||
echo "dovecot_mail_commands_total{command=\"copy\"} ${cmds_copy}"
|
||||
echo "dovecot_mail_commands_total{command=\"expunge\"} ${cmds_expunge}"
|
||||
echo ""
|
||||
|
||||
# --- Mail storage quota (top users if doveadm quota available) ---
|
||||
echo "# HELP dovecot_quota_usage_bytes User quota usage in bytes (top users)"
|
||||
echo "# TYPE dovecot_quota_usage_bytes gauge"
|
||||
echo "# HELP dovecot_quota_limit_bytes User quota limit in bytes"
|
||||
echo "# TYPE dovecot_quota_limit_bytes gauge"
|
||||
if command -v doveadm >/dev/null 2>&1; then
|
||||
doveadm quota get -A 2>/dev/null | grep 'STORAGE' | head -20 | while IFS=$'\t' read -r user type value limit _; do
|
||||
local usage_bytes=$((value * 1024))
|
||||
local limit_bytes=$((limit * 1024))
|
||||
echo "dovecot_quota_usage_bytes{user=\"${user}\"} ${usage_bytes}"
|
||||
echo "dovecot_quota_limit_bytes{user=\"${user}\"} ${limit_bytes}"
|
||||
done 2>/dev/null
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# --- Dovecot uptime ---
|
||||
echo "# HELP dovecot_uptime_seconds Dovecot process uptime in seconds"
|
||||
echo "# TYPE dovecot_uptime_seconds gauge"
|
||||
local dovecot_pid uptime_seconds=0
|
||||
dovecot_pid=$(pgrep -o dovecot 2>/dev/null) || dovecot_pid=""
|
||||
if [[ -n "$dovecot_pid" ]] && [[ -d "/proc/${dovecot_pid}" ]]; then
|
||||
local start_time
|
||||
start_time=$(stat -c %Y "/proc/${dovecot_pid}" 2>/dev/null) || start_time=0
|
||||
if [[ "$start_time" -gt 0 ]]; then
|
||||
uptime_seconds=$(( $(date +%s) - start_time ))
|
||||
fi
|
||||
fi
|
||||
echo "dovecot_uptime_seconds ${uptime_seconds}"
|
||||
echo ""
|
||||
|
||||
# --- Memory usage ---
|
||||
echo "# HELP dovecot_memory_bytes Total memory usage of all Dovecot processes"
|
||||
echo "# TYPE dovecot_memory_bytes gauge"
|
||||
local total_mem=0
|
||||
total_mem=$(pgrep dovecot 2>/dev/null | xargs -I {} cat /proc/{}/status 2>/dev/null | awk '/VmRSS/{sum+=$2} END {print sum*1024+0}') || total_mem=0
|
||||
echo "dovecot_memory_bytes ${total_mem}"
|
||||
echo ""
|
||||
|
||||
# --- Script execution time ---
|
||||
local END_TIME
|
||||
END_TIME=$(date +%s.%N)
|
||||
local DURATION
|
||||
DURATION=$(echo "$END_TIME - $START_TIME" | bc)
|
||||
|
||||
echo "# HELP dovecot_exporter_duration_seconds Time to generate all metrics"
|
||||
echo "# TYPE dovecot_exporter_duration_seconds gauge"
|
||||
echo "dovecot_exporter_duration_seconds ${DURATION}"
|
||||
echo ""
|
||||
|
||||
echo "# HELP dovecot_exporter_last_run_timestamp Unix timestamp of last successful run"
|
||||
echo "# TYPE dovecot_exporter_last_run_timestamp gauge"
|
||||
echo "dovecot_exporter_last_run_timestamp $(date +%s)"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# MAIN EXECUTION
|
||||
# ============================================================================
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
|
||||
if [ -n "$OUTPUT_FILE" ]; then
|
||||
local output_dir
|
||||
output_dir="$(dirname "$OUTPUT_FILE")"
|
||||
mkdir -p "$output_dir"
|
||||
|
||||
local temp_file
|
||||
temp_file=$(mktemp "${output_dir}/.dovecot_metrics.XXXXXX")
|
||||
|
||||
if ! generate_metrics > "$temp_file" 2>/dev/null; then
|
||||
rm -f "$temp_file"
|
||||
echo "ERROR: Failed to generate metrics" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local file_lines
|
||||
file_lines=$(wc -l < "$temp_file" 2>/dev/null || echo 0)
|
||||
|
||||
if [ "$file_lines" -lt 10 ]; then
|
||||
rm -f "$temp_file"
|
||||
echo "ERROR: Metrics file too small ($file_lines lines), keeping previous" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod 644 "$temp_file"
|
||||
mv -f "$temp_file" "$OUTPUT_FILE"
|
||||
|
||||
echo "Metrics written to $OUTPUT_FILE ($file_lines lines)" >&2
|
||||
else
|
||||
generate_metrics
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user