From ce6a3d4620e26a53d248160fd903d292d38ccad3 Mon Sep 17 00:00:00 2001 From: ssh-monitor Date: Tue, 14 Apr 2026 11:41:03 +1000 Subject: [PATCH] =?UTF-8?q?Zabbix:=20=D0=BA=D0=BE=D1=80=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=B8=D0=B9=20plain=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=B0=D0=BD?= =?UTF-8?q?=D0=B0=D0=BB=D0=B0;=20seq=20=D0=B2=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=B5;=20alert=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20python3=20-o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- ssh-monitor | 178 ++++++++++++++++++++++++++++----------- ssh-monitor.conf.example | 7 +- 2 files changed, 135 insertions(+), 50 deletions(-) diff --git a/ssh-monitor b/ssh-monitor index e0b7885..d042aee 100644 --- a/ssh-monitor +++ b/ssh-monitor @@ -7,7 +7,7 @@ IFS=$'\n\t' # ============================================ CONFIG_FILE="/etc/ssh-monitor.conf" -SSH_MONITOR_VERSION="0.9.5.8" +SSH_MONITOR_VERSION="0.9.7.0" TELEGRAM_BOT_TOKEN="" TELEGRAM_CHAT_ID="" @@ -22,9 +22,10 @@ ZABBIX_SERVER="" ZABBIX_HOST_NAME="" ZABBIX_ALERT_KEY="ssh.monitor.alert" ZABBIX_SEQ_KEY="ssh.monitor.seq" -# Лимит UTF-8 байт для значения ssh.monitor.alert (Zabbix trapper «Character» ≈255 байт). -# 0 = не урезать (item типа Text / большой лимит). По умолчанию 250 — влезает в Character. -ZABBIX_ALERT_MAX_BYTES="250" +# Лимит UTF-8 байт для значения ssh.monitor.alert (0 = не урезать). Для короткого plain-текста в Zabbix обычно 0. +ZABBIX_ALERT_MAX_BYTES="0" +# Файл последнего ssh.monitor.seq (число), чтобы после перезапуска счётчик не сбрасывался в 1. +ZABBIX_SEQ_STATE_FILE="/var/log/ssh_monitor_zabbix_seq" # Почта (SMTP через python3). Нужны MAIL_SMTP_HOST, MAIL_FROM, MAIL_TO. MAIL_SMTP_HOST="" @@ -160,7 +161,8 @@ load_config() { local cfg_zabbix_host_name="${ZABBIX_HOST_NAME:-}" local cfg_zabbix_alert_key="${ZABBIX_ALERT_KEY:-ssh.monitor.alert}" local cfg_zabbix_seq_key="${ZABBIX_SEQ_KEY:-ssh.monitor.seq}" - local cfg_zabbix_alert_max_bytes="${ZABBIX_ALERT_MAX_BYTES:-250}" + local cfg_zabbix_alert_max_bytes="${ZABBIX_ALERT_MAX_BYTES:-0}" + local cfg_zabbix_seq_state_file="${ZABBIX_SEQ_STATE_FILE:-/var/log/ssh_monitor_zabbix_seq}" local cfg_log_file="${LOG_FILE}" local cfg_last_heartbeat_file="${LAST_HEARTBEAT_FILE}" local cfg_last_report_file="${LAST_REPORT_FILE}" @@ -215,10 +217,11 @@ load_config() { ZABBIX_ALERT_KEY="$(trim_value "${ZABBIX_ALERT_KEY:-$cfg_zabbix_alert_key}")" ZABBIX_SEQ_KEY="$(trim_value "${ZABBIX_SEQ_KEY:-$cfg_zabbix_seq_key}")" ZABBIX_ALERT_MAX_BYTES="$(trim_value "${ZABBIX_ALERT_MAX_BYTES:-$cfg_zabbix_alert_max_bytes}")" - if ! [[ "${ZABBIX_ALERT_MAX_BYTES:-250}" =~ ^[0-9]+$ ]]; then - printf 'WARN: ZABBIX_ALERT_MAX_BYTES="%s" не число, использую 250\n' "${ZABBIX_ALERT_MAX_BYTES:-}" >&2 - ZABBIX_ALERT_MAX_BYTES=250 + if ! [[ "${ZABBIX_ALERT_MAX_BYTES:-0}" =~ ^[0-9]+$ ]]; then + printf 'WARN: ZABBIX_ALERT_MAX_BYTES="%s" не число, использую 0\n' "${ZABBIX_ALERT_MAX_BYTES:-}" >&2 + ZABBIX_ALERT_MAX_BYTES=0 fi + ZABBIX_SEQ_STATE_FILE="$(trim_value "${ZABBIX_SEQ_STATE_FILE:-$cfg_zabbix_seq_state_file}")" LOG_FILE="${LOG_FILE:-$cfg_log_file}" LAST_HEARTBEAT_FILE="${LAST_HEARTBEAT_FILE:-$cfg_last_heartbeat_file}" LAST_REPORT_FILE="${LAST_REPORT_FILE:-$cfg_last_report_file}" @@ -265,6 +268,8 @@ load_config() { MAIL_TO="$(trim_value "${MAIL_TO:-$cfg_mail_to}")" MAIL_SMTP_STARTTLS="${MAIL_SMTP_STARTTLS:-$cfg_mail_smtp_starttls}" MAIL_SMTP_SSL="${MAIL_SMTP_SSL:-$cfg_mail_smtp_ssl}" + + _sshmon_zbx_load_seq_state } # Дата/время для ежедневного отчёта (час DAILY_REPORT_HOUR и «сегодня» в LAST_REPORT_FILE). @@ -602,17 +607,31 @@ PY return 1 } -# zabbix_sender с произвольными аргументами (-i файл или -k/-o и т.д.). Весь вывод в zlog. -# Успех только по ответу сервера failed: 0 (exit-код и строка «sent:» часто обманчивы). -# Ошибка разбора входа: обычно есть «Sending failed.» — не путать с успехом. -_sshmon_zbx_send() { +# Восстановить счётчик seq из файла (после перезапуска не начинать с 1). +_sshmon_zbx_load_seq_state() { + [ -z "${ZABBIX_SEQ_STATE_FILE:-}" ] && return 0 + [ ! -f "$ZABBIX_SEQ_STATE_FILE" ] && return 0 + local s + s="$(tr -d ' \t\r\n' <"$ZABBIX_SEQ_STATE_FILE" 2>/dev/null || true)" + if [[ "$s" =~ ^[0-9]+$ ]] && [ "$s" -ge "${ZABBIX_EVENT_SEQ:-0}" ]; then + ZABBIX_EVENT_SEQ="$s" + fi +} + +_sshmon_zbx_save_seq_state() { + [ -z "${ZABBIX_SEQ_STATE_FILE:-}" ] && return 0 + local d + d="$(dirname "$ZABBIX_SEQ_STATE_FILE")" + mkdir -p "$d" 2>/dev/null || true + printf '%s\n' "${ZABBIX_EVENT_SEQ:-0}" >"${ZABBIX_SEQ_STATE_FILE}.tmp" 2>/dev/null || return 0 + mv -f "${ZABBIX_SEQ_STATE_FILE}.tmp" "$ZABBIX_SEQ_STATE_FILE" 2>/dev/null || true +} + +# Разбор вывода zabbix_sender (stdout+stderr в zlog). +_sshmon_zbx_parse_sender_output() { local log_tag="$1" local zlog="$2" - shift 2 - [ -n "${ZABBIX_SERVER:-}" ] && [ -n "${ZABBIX_HOST_NAME:-}" ] || return 1 - : >"$zlog" - zabbix_sender -z "$ZABBIX_SERVER" -s "$ZABBIX_HOST_NAME" "$@" >"$zlog" 2>&1 || : - local zrc=$? + local zrc="${3:-0}" if grep -Fq 'Sending failed.' "$zlog" 2>/dev/null; then write_log "WARN: zabbix_sender ${log_tag}: exit ${zrc}, $(tr '\n\r' ' ' <"$zlog")" return 1 @@ -623,7 +642,7 @@ _sshmon_zbx_send() { if [ -s "$zlog" ]; then write_log "WARN: zabbix_sender ${log_tag}: exit ${zrc}, $(tr '\n\r' ' ' <"$zlog")" if grep -Eq 'failed:[[:space:]]*[1-9][0-9]*[[:space:]]*;' "$zlog" 2>/dev/null; then - write_log "WARN: Zabbix отклонил значение (${log_tag}): хост/ключ/тип item; длинный UTF-8 (эмодзи, кириллица) часто не влезает в trapper «Character» (~255 байт) — смените item на «Text» или задайте ZABBIX_ALERT_MAX_BYTES." + write_log "WARN: Zabbix отклонил значение (${log_tag}): хост, ключ trapper, тип item, препроцессинг или лимит; для длинных текстов — ZABBIX_ALERT_MAX_BYTES." fi else write_log "WARN: zabbix_sender ${log_tag}: exit ${zrc}, вывод пуст (PATH zabbix_sender, сеть до ${ZABBIX_SERVER})" @@ -631,12 +650,25 @@ _sshmon_zbx_send() { return 1 } +# zabbix_sender с произвольными аргументами (-i файл или -k/-o и т.д.). Весь вывод в zlog. +# Успех только по ответу сервера failed: 0 (exit-код и строка «sent:» часто обманчивы). +_sshmon_zbx_send() { + local log_tag="$1" + local zlog="$2" + shift 2 + [ -n "${ZABBIX_SERVER:-}" ] && [ -n "${ZABBIX_HOST_NAME:-}" ] || return 1 + : >"$zlog" + zabbix_sender -z "$ZABBIX_SERVER" -s "$ZABBIX_HOST_NAME" "$@" >"$zlog" 2>&1 || : + local zrc=$? + _sshmon_zbx_parse_sender_output "$log_tag" "$zlog" "$zrc" +} + # Укладывает текст в лимит байт UTF-8 (Zabbix trapper «Character»). 0 = без усечения. _sshmon_zbx_truncate_alert_value() { local text="$1" - local maxb="${ZABBIX_ALERT_MAX_BYTES:-250}" + local maxb="${ZABBIX_ALERT_MAX_BYTES:-0}" case "$maxb" in - ''|*[!0-9]*) maxb=250 ;; + ''|*[!0-9]*) maxb=0 ;; esac if [ "$maxb" -eq 0 ]; then printf '%s' "$text" @@ -702,28 +734,50 @@ send_zabbix_trapper() { ZABBIX_EVENT_SEQ=$((ZABBIX_EVENT_SEQ + 1)) - local tmp zlog alert_rc seq_rc - tmp="$(mktemp "${TMPDIR:-/tmp}/ssh-monitor.zbx.al.XXXXXX" 2>/dev/null)" || return 1 - zlog="$(mktemp "${TMPDIR:-/tmp}/ssh-monitor.zbx.log.XXXXXX" 2>/dev/null)" || { - rm -f "$tmp" + local zlog alert_rc seq_rc tmp="" + zlog="$(mktemp "${TMPDIR:-/tmp}/ssh-monitor.zbx.log.XXXXXX" 2>/dev/null)" || return 1 + + alert_rc=1 + seq_rc=1 + # UTF-8 в -o через python3 (argv) надёжнее, чем -i файл на части сборок zabbix_sender. + if command -v python3 >/dev/null 2>&1; then + : >"$zlog" + printf '%s' "$one_line" | SSHMON_ZBX_TRAPPER_K="$key_al" SSHMON_ZBX_TRAPPER_LOG="$zlog" python3 -c ' +import os, subprocess, sys +val = sys.stdin.read() +k = os.environ["SSHMON_ZBX_TRAPPER_K"] +path = os.environ["SSHMON_ZBX_TRAPPER_LOG"] +r = subprocess.run( + ["zabbix_sender", "-z", os.environ["ZABBIX_SERVER"], + "-s", os.environ["ZABBIX_HOST_NAME"], "-k", k, "-o", val], + capture_output=True, text=True) +with open(path, "w", encoding="utf-8", newline="\n") as fh: + fh.write((r.stdout or "") + (r.stderr or "")) +' || true + if _sshmon_zbx_parse_sender_output "alert (${key_al})" "$zlog" 0; then + alert_rc=0 + fi + else + tmp="$(mktemp "${TMPDIR:-/tmp}/ssh-monitor.zbx.al.XXXXXX" 2>/dev/null)" || { + rm -f "$zlog" return 1 } - printf '%s\t%s\n' "$key_al" "$one_line" >"$tmp" || { rm -f "$tmp" "$zlog" return 1 } - - alert_rc=1 - seq_rc=1 if _sshmon_zbx_send "alert (${key_al})" "$zlog" -i "$tmp"; then alert_rc=0 fi + rm -f "$tmp" + fi + if _sshmon_zbx_send "seq (${key_sq})" "$zlog" -k "$key_sq" -o "${ZABBIX_EVENT_SEQ}"; then seq_rc=0 fi - rm -f "$tmp" "$zlog" + rm -f "$zlog" + _sshmon_zbx_save_seq_state # Раньше один файл с двумя строками: при failed по seq весь пакет считался неуспешным. # Текст оповещения — основной результат; seq нужен для триггеров по изменению. @@ -736,8 +790,12 @@ send_zabbix_trapper() { notify_send() { local message="$1" + local zabbix_plain="${2:-}" if [ "${DRY_RUN:-0}" = "1" ]; then printf '[DRY-RUN notify] %s\n' "$(printf '%s' "$message" | tr '\n' ' ')" >&2 + if [ -n "$zabbix_plain" ]; then + printf '[DRY-RUN notify] zabbix (plain): %s\n' "$(printf '%s' "$zabbix_plain" | tr '\n' ' ')" >&2 + fi return 0 fi @@ -753,7 +811,7 @@ notify_send() { fi ;; zabbix) - if send_zabbix_trapper "$message"; then + if send_zabbix_trapper "${zabbix_plain:-$message}"; then any_ok=1 else write_log "WARN: канал zabbix: не удалось отправить (zabbix_sender, сеть, имя хоста/ключи в Zabbix)" @@ -940,7 +998,8 @@ block_ip() { message="${message}📊 Неудачных попыток: ${attempts}"$'\n' message="${message}⏱️ Блокировка на: ${ban_time_hours} час(ов)"$'\n' message="${message}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$message" + local zbx_ban="IP заблокирован: $(server_display_name_with_ip), адрес ${ip}, неудачных попыток ${attempts}, блок ${ban_time_hours} ч." + notify_send "$message" "$zbx_ban" write_log "AUTO-BAN: IP $ip заблокирован на $ban_time_hours часов ($attempts попыток)" } @@ -965,7 +1024,8 @@ unblock_expired_ips() { local message=" 🔓 IP РАЗБЛОКИРОВАН "$'\n' message="${message}🌐 IP: ${ip}"$'\n' message="${message}🕐 Время разблокировки: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$message" + local zbx_un="IP разблокирован: $(server_display_name_with_ip), адрес ${ip}" + notify_send "$message" "$zbx_un" unblocked=$((unblocked + 1)) fi @@ -1136,13 +1196,15 @@ monitor_ssh() { message="${message}👤 Пользователь: ${user}"$'\n' message="${message}🌐 IP адрес: ${ip:-local}"$'\n' message="${message}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$message" + local zbx_ssh="Новый SSH-вход: $(server_display_name_with_ip), пользователь ${user}, адрес ${ip:-local}" + notify_send "$message" "$zbx_ssh" write_log "SSH успешный вход: $user с IP ${ip:-local}" if [ "$user" = "root" ]; then local rmsg=" 🔑 SSH ВХОД ПОД ROOT "$'\n' rmsg="${rmsg}🌐 IP: ${ip:-local}"$'\n' rmsg="${rmsg}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$rmsg" + local zbx_root="Новый SSH-вход под root: $(server_display_name_with_ip), адрес ${ip:-local}" + notify_send "$rmsg" "$zbx_root" fi fi elif echo "$line" | grep -q "Failed password"; then @@ -1171,7 +1233,8 @@ monitor_ssh() { message="${message}🌐 IP адрес: ${ip}"$'\n' message="${message}📊 Попытка ${current_attempts} из ${MAX_ATTEMPTS}"$'\n' message="${message}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$message" + local zbx_fail="Неудачный SSH: $(server_display_name_with_ip), пользователь ${user}, адрес ${ip}, попытка ${current_attempts} из ${MAX_ATTEMPTS}" + notify_send "$message" "$zbx_fail" fi write_log "SSH неудачная попытка: $user с IP $ip (попытка $current_attempts из $MAX_ATTEMPTS)" fi @@ -1286,7 +1349,15 @@ monitor_sudo() { message="${message}💻 Команда: ${sudo_cmd}"$'\n' message="${message}📁 Директория: ${pwd:-unknown}"$'\n' message="${message}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$message" + local cmdz="${sudo_cmd}" + if [ "${#cmdz}" -gt 200 ]; then + cmdz="${cmdz:0:200}…" + fi + local zbx_sudo="Повышение привилегий (sudo): $(server_display_name_with_ip), пользователь ${user}, команда: ${cmdz}" + if [ -n "${run_as:-}" ]; then + zbx_sudo="${zbx_sudo}, от имени ${run_as}" + fi + notify_send "$message" "$zbx_sudo" write_log "SUDO: $user выполнил $sudo_cmd${run_as:+ (USER=$run_as)}" fi done <<<"$sudo_logs" @@ -1327,7 +1398,8 @@ monitor_security_events() { local m=" 🔐 ВНИМАНИЕ: изменение SSH host key / MITM? "$'\n' m="${m}$(printf '%s\n' "$hk")" m="${m}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$m" + local zbx_hk="SSH host key / MITM: $(server_display_name_with_ip), см. журнал" + notify_send "$m" "$zbx_hk" write_log "SECURITY: обнаружено сообщение об изменении host key" fi fi @@ -1348,7 +1420,8 @@ monitor_security_events() { bm="${bm}🌐 IP: ${ip}"$'\n' bm="${bm}📊 Неудачных попыток за ~${BRUTE_WINDOW_SEC}s: ${count}"$'\n' bm="${bm}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$bm" + local zbx_br="SSH брутфорс: $(server_display_name_with_ip), IP ${ip}, попыток ~${count} за ${BRUTE_WINDOW_SEC}s" + notify_send "$bm" "$zbx_br" write_log "SECURITY: массовый брутфорс? IP=$ip fails=${count} за окно ${BRUTE_WINDOW_SEC}s" fi fi @@ -1459,7 +1532,8 @@ monitor_logind() { msg="${msg}👤 Пользователь: ${user:-неизвестно}"$'\n' msg="${msg}🆔 Сессия: ${sid:-?}"$'\n' msg="${msg}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$msg" + local zbx_ln="Сессия logind: $(server_display_name_with_ip), пользователь ${user:-?}, sid ${sid:-?}" + notify_send "$msg" "$zbx_ln" write_log "LOGIND: новая сессия: ${line}" else write_log "LOGIND: новая сессия (разбор user/sid не удался): ${line}" @@ -1476,7 +1550,8 @@ monitor_logind() { local msg_r=" 🚪 СЕССИЯ ЗАКРЫТА (systemd-logind) "$'\n' msg_r="${msg_r}🆔 Сессия: ${sess_r:-?}"$'\n' msg_r="${msg_r}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$msg_r" + local zbx_lr="Сессия закрыта (logind): $(server_display_name_with_ip), sid ${sess_r:-?}" + notify_send "$msg_r" "$zbx_lr" fi elif [[ "$low" == *"failed"* ]]; then @@ -1484,7 +1559,12 @@ monitor_logind() { local msg_f=" ❌ СБОЙ (systemd-logind) "$'\n' msg_f="${msg_f}📝 ${line}"$'\n' msg_f="${msg_f}🕐 Время: $(notification_date '+%d.%m.%Y %H:%M:%S')" - notify_send "$msg_f" + local ln_f="$line" + if [ "${#ln_f}" -gt 180 ]; then + ln_f="${ln_f:0:180}…" + fi + local zbx_lf="Сбой logind: $(server_display_name_with_ip), ${ln_f}" + notify_send "$msg_f" "$zbx_lf" write_log "LOGIND: сбой: $line" fi fi @@ -1613,7 +1693,8 @@ send_daily_report() { message="${message} Нет активных пользователей"$'\n' fi - notify_send "$message" + local zbx_rep="Отчет ssh-monitor 24h: $(server_display_name_with_ip), ok=${successful_logins:-0} fail=${failed_logins:-0} sudo=${sudo_commands:-0} bans=${active_bans}" + notify_send "$message" "$zbx_rep" write_log "Ежедневный отчет отправлен" echo "$(report_date '+%F')" >"$LAST_REPORT_FILE" @@ -1672,7 +1753,8 @@ send_heartbeat() { message="${message}🖥️ Сервер: $(server_display_name_with_ip)"$'\n' message="${message}🕐 Время: ${timestamp_human}" - notify_send "$message" + local zbx_hb="Heartbeat ssh-monitor: $(server_display_name_with_ip)" + notify_send "$message" "$zbx_hb" echo "$timestamp" >"$LAST_HEARTBEAT_FILE" write_log "Heartbeat отправлен" } @@ -1736,7 +1818,8 @@ send_startup_notification() { message="${message}❤️ Heartbeat будет отправляться каждые 12 часов"$'\n' message="${message}📢 Каналы уведомлений (все по списку): $(notify_chain_human)" - notify_send "$message" + local zbx_su="Старт ssh-monitor v${SSH_MONITOR_VERSION:-?}: $(server_display_name_with_ip), whitelist=${whitelist_count}" + notify_send "$message" "$zbx_su" write_log "Скрипт мониторинга запущен (белый список: $whitelist_count записей)" } @@ -1750,7 +1833,8 @@ send_shutdown_notification() { message="${message}🖥️ Сервер: $(server_display_name_with_ip)"$'\n' message="${message}🕐 Время остановки: ${timestamp}" - notify_send "$message" + local zbx_sd="Стоп ssh-monitor: $(server_display_name_with_ip)" + notify_send "$message" "$zbx_sd" write_log "Скрипт мониторинга остановлен" } @@ -1809,8 +1893,8 @@ run_check_config() { printf 'LOGIND_NOTIFY_NEW=%s LOGIND_NOTIFY_REMOVED=%s LOGIND_NOTIFY_FAILED=%s LOGIND_SKIP_REMOTE=%s\n' \ "${LOGIND_NOTIFY_NEW:-}" "${LOGIND_NOTIFY_REMOVED:-}" "${LOGIND_NOTIFY_FAILED:-}" "${LOGIND_SKIP_REMOTE:-}" printf 'ZABBIX_SERVER=%s ZABBIX_HOST_NAME=%s\n' "${ZABBIX_SERVER:-}" "${ZABBIX_HOST_NAME:-}" - printf 'ZABBIX_ALERT_KEY=%s ZABBIX_SEQ_KEY=%s ZABBIX_ALERT_MAX_BYTES=%s (0=без усечения)\n' \ - "${ZABBIX_ALERT_KEY:-}" "${ZABBIX_SEQ_KEY:-}" "${ZABBIX_ALERT_MAX_BYTES:-250}" + printf 'ZABBIX_ALERT_KEY=%s ZABBIX_SEQ_KEY=%s ZABBIX_ALERT_MAX_BYTES=%s ZABBIX_SEQ_STATE_FILE=%s\n' \ + "${ZABBIX_ALERT_KEY:-}" "${ZABBIX_SEQ_KEY:-}" "${ZABBIX_ALERT_MAX_BYTES:-0}" "${ZABBIX_SEQ_STATE_FILE:-}" if [ -n "${ZABBIX_SERVER:-}" ] && [ -n "${ZABBIX_HOST_NAME:-}" ]; then if command -v zabbix_sender >/dev/null 2>&1; then printf 'zabbix_sender: найден (%s)\n' "$(command -v zabbix_sender)" diff --git a/ssh-monitor.conf.example b/ssh-monitor.conf.example index abbc3e7..d2cdf88 100644 --- a/ssh-monitor.conf.example +++ b/ssh-monitor.conf.example @@ -31,9 +31,10 @@ ZABBIX_SERVER="" ZABBIX_HOST_NAME="" ZABBIX_ALERT_KEY="ssh.monitor.alert" ZABBIX_SEQ_KEY="ssh.monitor.seq" -# Макс. байт UTF-8 для значения trapper (по умолчанию 250 — типичный лимит «Character» в Zabbix). -# Полные тексты как в Telegram — item ssh.monitor.alert лучше типа «Text», тогда можно ZABBIX_ALERT_MAX_BYTES="0". -ZABBIX_ALERT_MAX_BYTES="250" +# В Zabbix уходит короткий plain-текст (второй аргумент notify_send); 0 = не урезать длину. +ZABBIX_ALERT_MAX_BYTES="0" +# Последний ssh.monitor.seq на диске — после перезапуска счётчик не сбрасывается. +ZABBIX_SEQ_STATE_FILE="/var/log/ssh_monitor_zabbix_seq" # SMTP (python3). Для авто-режима почты нужны MAIL_SMTP_HOST, MAIL_FROM, MAIL_TO. MAIL_SMTP_HOST=""