Files
Joplin_server_daily_diag/joplin_server_daily_diag.sh
2025-11-13 16:49:27 +01:00

350 lines
9.0 KiB
Bash

cat /home/scripts/joplin_server_daily_diag.sh
#!/bin/bash
########################################
# Rapport quotidien serveur + Discord
# - Ping API Joplin
# - Espace disque global
# - Ressources CPU / RAM / top process
# - Événements majeurs des 24h (journalctl -p 0..3)
# - Espace disque par user Linux (/home)
# - Espace disque par user Joplin (PostgreSQL)
# - Envoi Discord (message + log en pièce jointe)
########################################
# === CONFIG DISCORD ===
WEBHOOK="https://discord.com/api/webhooks/1234567890000000987654321/hsagsklzjkldhfgasouihfgdhfdousahFLDSAHFOUHFJNDAFOUADHFAOUSFHDOU"
# Dossier de logs
LOG_DIR="/var/log/server-daily-diag"
mkdir -p "${LOG_DIR}"
TS="$(date '+%Y-%m-%d_%H-%M-%S')"
LOG_FILE="${LOG_DIR}/server_daily_diag_${TS}.log"
HOSTNAME="$(hostname -f 2>/dev/null || hostname)"
# === CONFIG PING JOPLIN ===
JOPLIN_PING_URL="http://127.0.0.1:22300/api/ping"
JOPLIN_HOST_HEADER="joplin.server.me"
JOPLIN_ORIGIN_HEADER="https://joplin.server.me"
JOPLIN_X_FORWARDED_PROTO="https"
# === CONFIG JOPLIN DB (PostgreSQL) ===
ENABLE_JOPLIN_DB_STATS=1
JOPLIN_DB_HOST="127.0.0.1"
JOPLIN_DB_PORT="5432"
JOPLIN_DB_NAME="joplin"
JOPLIN_DB_USER="joplin"
JOPLIN_DB_PASSWORD="PASSWORDxxxXXX1233764"
########################################
# PRÉREQUIS
########################################
# jq est un prérequis systématique pour Discord
if ! command -v jq >/dev/null 2>&1; then
echo "ERREUR: jq n'est pas installé sur ce serveur."
echo "Installe-le avant d'utiliser ce script :"
echo " apt update -y && apt install -y jq"
exit 1
fi
########################################
# Variables globales pour le résumé
########################################
API_STATUS="inconnu"
ROOT_USAGE="n/a"
LOAD_AVG="n/a"
MEM_LINE="n/a"
JOPLIN_USERS_SUMMARY=""
########################################
# Utils
########################################
log() {
# log dans le fichier avec timestamp
printf '[%s] %s\n' "$(date +'%Y-%m-%dT%H:%M:%S%z')" "$*" >> "${LOG_FILE}"
}
human_bytes() {
local bytes="$1"
local units=(B KB MB GB TB PB)
local i=0
if ! [[ "$bytes" =~ ^[0-9]+$ ]]; then
echo "-"
return
fi
while [ "$bytes" -ge 1024 ] && [ "$i" -lt $(( ${#units[@]} - 1 )) ]; do
bytes=$(( (bytes + 512) / 1024 ))
i=$((i + 1))
done
echo "${bytes}${units[$i]}"
}
########################################
# 1) Ping Joplin
########################################
check_joplin() {
log "===== Vérification Joplin Server (/api/ping) ====="
local response http_code status message json_body
response="$(curl -sS -i \
-H "Host: ${JOPLIN_HOST_HEADER}" \
-H "Origin: ${JOPLIN_ORIGIN_HEADER}" \
-H "X-Forwarded-Proto: ${JOPLIN_X_FORWARDED_PROTO}" \
"${JOPLIN_PING_URL}" || true)"
http_code="$(printf '%s\n' "${response}" | awk 'NR==1 {print $2}')"
json_body="$(printf '%s\n' "${response}" | awk '/^\{/{print}')"
status="$(printf '%s\n' "${json_body}" | jq -r '.status // empty' 2>/dev/null)"
message="$(printf '%s\n' "${json_body}" | jq -r '.message // empty' 2>/dev/null)"
if [ "${http_code}" = "200" ] && [ "${status}" = "ok" ]; then
API_STATUS="OK (${http_code}, ${message})"
log "Joplin Server OK (HTTP ${http_code}) - ${message}"
else
API_STATUS="KO (${http_code:-N/A})"
log "Joplin Server PROBLÈME (HTTP ${http_code:-N/A})"
log "Réponse brute :"
printf '%s\n' "${response}" | sed 's/^/ /' >> "${LOG_FILE}"
fi
log ""
}
########################################
# 2) Espace disque global
########################################
disk_global() {
log "===== Espace disque global (df -hT) ====="
df -hT >> "${LOG_FILE}" 2>&1
log ""
ROOT_USAGE="$(df -h / 2>/dev/null | awk 'NR==2 {print $5 " used on " $6}')"
[ -z "${ROOT_USAGE}" ] && ROOT_USAGE="n/a"
}
########################################
# 3) Espace disque par utilisateur Linux (/home)
########################################
disk_per_linux_user() {
log "===== Espace disque par utilisateur Linux (/home) ====="
if [ ! -d /home ]; then
log "/home n'existe pas, section ignorée."
log ""
return
fi
for dir in /home/*; do
[ -d "${dir}" ] || continue
user="$(basename "${dir}")"
bytes="$(du -sb "${dir}" 2>/dev/null | awk '{print $1}')"
human="$(human_bytes "${bytes}")"
log "User Linux: ${user} -> ${human} (~ ${bytes:-0} B) [${dir}]"
done
log ""
}
########################################
# 4) Ressources système
########################################
system_resources() {
log "===== Ressources système ====="
log "-- Uptime et charge --"
uptime 2>/dev/null >> "${LOG_FILE}" 2>&1 || log "uptime indisponible"
log ""
LOAD_AVG="$(awk '{print $1","$2","$3}' /proc/loadavg 2>/dev/null)"
[ -z "${LOAD_AVG}" ] && LOAD_AVG="n/a"
log "-- Mémoire (free -h) --"
free -h 2>/dev/null >> "${LOG_FILE}" || log "free indisponible"
log ""
MEM_LINE="$(free -h 2>/dev/null | awk '/Mem:/ {print $3 " / " $2 " used"}')"
[ -z "${MEM_LINE}" ] && MEM_LINE="n/a"
log "-- Top CPU (top 5) --"
if command -v ps >/dev/null 2>&1; then
ps -eo pid,user,pcpu,pmem,comm --sort=-pcpu | head -n 6 >> "${LOG_FILE}"
else
log "ps indisponible."
fi
log ""
log "-- Top RAM (top 5) --"
if command -v ps >/dev/null 2>&1; then
ps -eo pid,user,pcpu,pmem,comm --sort=-pmem | head -n 6 >> "${LOG_FILE}"
else
log "ps indisponible."
fi
log ""
}
########################################
# 5) Logs système (24h, priorité 0..3)
########################################
major_events_24h() {
log "===== Événements système majeurs (24h, journalctl -p 0..3) ====="
if ! command -v journalctl >/dev/null 2>&1; then
log "journalctl non disponible, section ignorée."
log ""
return
fi
journalctl -p 0..3 --since "24 hours ago" --no-pager 2>/dev/null | tail -n 300 >> "${LOG_FILE}"
log ""
}
########################################
# 6) Espace disque par utilisateur Joplin
########################################
joplin_per_user() {
log "===== Espace disque par utilisateur Joplin (total_item_size) ====="
if [ "${ENABLE_JOPLIN_DB_STATS}" -ne 1 ]; then
log "Section désactivée (ENABLE_JOPLIN_DB_STATS != 1)."
log ""
return
fi
if ! command -v psql >/dev/null 2>&1; then
log "psql introuvable, impossible de lire la base Joplin."
log ""
return
fi
if [ -z "${JOPLIN_DB_NAME}" ] || [ -z "${JOPLIN_DB_USER}" ]; then
log "Config DB Joplin incomplète (nom ou user manquant)."
log ""
return
fi
export PGPASSWORD="${JOPLIN_DB_PASSWORD}"
local query
query="SELECT email, full_name, COALESCE(total_item_size,0) AS total_item_size
FROM users
ORDER BY total_item_size DESC;"
local lines
lines="$(
psql \
-h "${JOPLIN_DB_HOST}" \
-p "${JOPLIN_DB_PORT}" \
-U "${JOPLIN_DB_USER}" \
-d "${JOPLIN_DB_NAME}" \
-t -A -F '|' \
-c "${query}" 2>&1
)"
if printf '%s\n' "${lines}" | grep -qi "ERROR"; then
log "Erreur lors de la requête PostgreSQL :"
printf '%s\n' "${lines}" | sed 's/^/ /' >> "${LOG_FILE}"
log ""
return
fi
while IFS='|' read -r email full_name total_bytes; do
[ -z "${email}" ] && continue
human_size="$(human_bytes "${total_bytes}")"
if [ -n "${full_name}" ]; then
line="Joplin user: ${email} (${full_name}) -> ${human_size} (~ ${total_bytes} B)"
else
line="Joplin user: ${email} -> ${human_size} (~ ${total_bytes} B)"
fi
# Log complet
log "${line}"
# Résumé pour Discord
JOPLIN_USERS_SUMMARY+="${line}"$'\n'
done <<< "${lines}"
log ""
}
########################################
# 7) Envoi sur Discord
########################################
send_discord() {
log "===== Envoi du rapport sur Discord ====="
# Si aucune donnée Joplin collectée
if [ -z "${JOPLIN_USERS_SUMMARY}" ]; then
JOPLIN_USERS_SUMMARY="(Aucune donnée Joplin ou stats désactivées)"
fi
SUMMARY="🧾 Rapport Joplin serveur
Host : ${HOSTNAME}
Date : $(date '+%Y-%m-%d %H:%M:%S')
API Joplin : ${API_STATUS}
Disque racine : ${ROOT_USAGE}
Charge (1/5/15min): ${LOAD_AVG}
Mémoire : ${MEM_LINE}
Users:
${JOPLIN_USERS_SUMMARY}
Détails complets (logs, stats Joplin & users) dans le fichier joint.
"
# Sécurité limite Discord (<2000 chars)
SUMMARY_TRIMMED="$(printf '%s\n' "${SUMMARY}" | cut -c1-1900)"
# Encodage JSON safe via jq -Rs
JSON_PAYLOAD="$(printf '%s' "${SUMMARY_TRIMMED}" | jq -Rs '{content: .}')"
curl -sS -X POST \
-F "payload_json=${JSON_PAYLOAD}" \
-F "file=@${LOG_FILE};type=text/plain" \
"${WEBHOOK}" >/dev/null || {
echo "ERREUR: échec de l'envoi à Discord." >&2
return 1
}
log "Rapport envoyé sur Discord (résumé + pièce jointe)."
}
########################################
# MAIN
########################################
log "===== DIAGNOSTIC QUOTIDIEN SERVEUR JOPLIN ====="
log "Date : $(date '+%Y-%m-%d %H:%M:%S %z')"
log ""
check_joplin
disk_global
disk_per_linux_user
system_resources
major_events_24h
joplin_per_user
send_discord
log "===== FIN DIAGNOSTIC ====="
exit 0