Kompletne odstraneno: - Emoji (smajliky, symboly, boxes, arrows) z README - Emoji ze skriptu (sipky, symboly) - Emoji z docker-compose (adresare) Nahrano za: - Textove alternativy (sipky -> '->', boxes -> '+', atd.) - ASCII pouze kde to slo Ciste vsechny 7 repo (overeno Python skriptem).
185 lines
5.5 KiB
Bash
185 lines
5.5 KiB
Bash
#!/usr/bin/env bash
|
||
#
|
||
# disk-watch.sh -- sledování volného místa na Docker datech
|
||
#
|
||
# Kontroluje:
|
||
# - <ssd-data-mount> (Docker data)
|
||
# - <backup-disk-mount> (zálohy)
|
||
# - Docker disk usage (images, containers, volumes, build cache)
|
||
#
|
||
# Při podkročení prahu pošle notifikaci (Telegram přes Hermes cron, nebo lokální alert).
|
||
# V defaultu jen vypíše stav; s --alert pošle zprávu přes Hermes Telegram doručení.
|
||
#
|
||
# Použití:
|
||
# ./disk-watch.sh # jen výpis
|
||
# ./disk-watch.sh --alert # pošle notifikaci při podkročení
|
||
# SSDDATA_THRESHOLD=80 ./disk-watch.sh # 80 % prah pro SSD-data
|
||
#
|
||
|
||
set -euo pipefail
|
||
|
||
SSD_DATA="${SSD_DATA:-<ssd-data-mount>}"
|
||
SSD_BACKUP="${SSD_BACKUP:-<backup-disk-mount>}"
|
||
SSD_DATA_THRESHOLD="${SSD_DATA_THRESHOLD:-85}" # %
|
||
SSD_BACKUP_THRESHOLD="${SSD_BACKUP_THRESHOLD:-85}" # %
|
||
DOCKER_THRESHOLD="${DOCKER_THRESHOLD:-80}" # %
|
||
|
||
ALERT=0
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
--alert|-a) ALERT=1 ;;
|
||
--help|-h)
|
||
sed -n '2,15p' "$0"
|
||
exit 0
|
||
;;
|
||
*) echo "Unknown arg: $arg" >&2; exit 1 ;;
|
||
esac
|
||
done
|
||
|
||
# Barevné výstupy
|
||
if [ -t 1 ]; then
|
||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||
else
|
||
RED=''; GREEN=''; YELLOW=''; BLUE=''; NC=''
|
||
fi
|
||
|
||
WARNINGS=()
|
||
|
||
check_disk() {
|
||
local path="$1" threshold="$2" label="$3"
|
||
if [ ! -d "$path" ]; then
|
||
printf '%s%s%s %s -- adresář neexistuje\n' "$YELLOW" "" "$NC" "$label"
|
||
return
|
||
fi
|
||
# df v macOS nevrací % použití přímo; parsujeme z výstupu
|
||
local line used avail capacity
|
||
line=$(df -h "$path" | tail -n +2 | head -n 1)
|
||
capacity=$(echo "$line" | awk '{print $5}' | tr -d '%')
|
||
used=$(echo "$line" | awk '{print $3}')
|
||
avail=$(echo "$line" | awk '{print $4}')
|
||
total=$(echo "$line" | awk '{print $2}')
|
||
|
||
if [ -z "$capacity" ]; then
|
||
printf '%s%s%s %s -- nelze přečíst\n' "$YELLOW" "" "$NC" "$label"
|
||
return
|
||
fi
|
||
|
||
if [ "$capacity" -ge "$threshold" ]; then
|
||
printf '%s%s %s %s/%s (%s%%) -- %sPŘEKROČEN PRAH%s (%s%%)\n' \
|
||
"$RED" "$NC" "$label" "$used" "$total" "$capacity" "$RED" "$NC" "$threshold"
|
||
WARNINGS+=("$label: ${capacity}% (prah ${threshold}%)")
|
||
else
|
||
printf '%s%s %s %s/%s (%s%%) -- OK\n' \
|
||
"$GREEN" "$NC" "$label" "$used" "$total" "$capacity"
|
||
fi
|
||
}
|
||
|
||
check_docker_disk() {
|
||
if ! docker info >/dev/null 2>&1; then
|
||
printf '%s%s Docker -- není dostupný\n' "$YELLOW" "$NC"
|
||
return
|
||
fi
|
||
|
||
# Získat velikost images + containers + volumes
|
||
local out
|
||
out=$(docker system df --format '{{.Type}}\t{{.Size}}\t{{.Reclaimable}}' 2>/dev/null || true)
|
||
|
||
if [ -z "$out" ]; then
|
||
printf '%s%s Docker disk -- nešlo přečíst\n' "$YELLOW" "$NC"
|
||
return
|
||
fi
|
||
|
||
# Spočítat celkové využití Dockeru (obtížné bez du -s na /var/lib/docker;
|
||
# protože jsme na Docker Desktop macOS, kontrolujeme jen velikost images)
|
||
local images_size_bytes
|
||
images_size_bytes=$(docker system df --format '{{.Type}}\t{{.Size}}' \
|
||
| awk -F'\t' '$1 == "Images" {print $2}')
|
||
|
||
printf '%s%s Docker images: %s\n' "$BLUE" "$NC" "${images_size_bytes:-neznámé}"
|
||
|
||
# Velké images (>500 MB), které nejsou používané
|
||
printf '%s%s Velké images (>500 MB):\n' "$BLUE" "$NC"
|
||
docker images --format '{{.Size}}\t{{.Repository}}:{{.Tag}}\t{{.ID}}' \
|
||
| awk -F'\t' '{
|
||
size = $1
|
||
# převod na MB
|
||
if (size ~ /GB/) {mb = size * 1024} else if (size ~ /MB/) {mb = size + 0} else if (size ~ /kB/) {mb = size / 1024} else {mb = 0}
|
||
if (mb + 0 > 500) print $2, size
|
||
}' \
|
||
| head -10 | while read -r line; do
|
||
printf ' %s\n' "$line"
|
||
done
|
||
|
||
# Nepoužívané images (pozor, ne "používané" -- bezpečnost)
|
||
unused=$(docker images --format '{{.Size}}\t{{.Repository}}:{{.Tag}}' \
|
||
| awk -F'\t' '
|
||
/^([0-9.]+[kMG]B)\s/ {
|
||
size = $1
|
||
if (size ~ /GB/) mb = size * 1024
|
||
else if (size ~ /MB/) mb = size + 0
|
||
else if (size ~ /kB/) mb = size / 1024
|
||
if (mb + 0 > 200) print size, $2
|
||
}' | head -5)
|
||
if [ -n "$unused" ]; then
|
||
printf '%s%s Kandidáti na vyčištění (>200 MB):\n' "$YELLOW" "$NC"
|
||
echo "$unused" | while read -r line; do printf ' %s\n' "$line"; done
|
||
fi
|
||
}
|
||
|
||
check_top_offenders() {
|
||
if [ ! -d "$SSD_DATA/Dockery" ]; then
|
||
return
|
||
fi
|
||
printf '\n%s%s Top 5 největších adresářů v <docker-projects-root>:\n' "$BLUE" "$NC"
|
||
/bin/du -sh "$SSD_DATA"/Dockery/*/ 2>/dev/null \
|
||
| /usr/bin/sort -rh \
|
||
| /usr/bin/head -5 \
|
||
| /usr/bin/sed 's/^/ /'
|
||
}
|
||
|
||
printf '%s%s%s\n' "$BLUE" "=== DISK WATCH ===" "$NC"
|
||
printf 'Prahy: SSD-data>%s%%, disk2-data>%s%%\n' "$SSD_DATA_THRESHOLD" "$SSD_BACKUP_THRESHOLD"
|
||
printf 'Datum: %s\n\n' "$(date '+%Y-%m-%d %H:%M:%S')"
|
||
|
||
check_disk "$SSD_DATA" "$SSD_DATA_THRESHOLD" "SSD-data (Docker)"
|
||
check_disk "$SSD_BACKUP" "$SSD_BACKUP_THRESHOLD" "disk2-data (zálohy)"
|
||
|
||
check_docker_disk
|
||
check_top_offenders
|
||
|
||
if [ "${#WARNINGS[@]}" -gt 0 ]; then
|
||
printf '\n%s%s VAROVÁNÍ:\n' "$RED" "$NC"
|
||
for w in "${WARNINGS[@]}"; do
|
||
printf ' - %s\n' "$w"
|
||
done
|
||
fi
|
||
|
||
if [ "$ALERT" = "1" ] && [ "${#WARNINGS[@]}" -gt 0 ]; then
|
||
# Alert přes Hermes Telegram cron
|
||
MSG="️ Disk Watch -- překročen prah
|
||
$(printf '%s\n' "${WARNINGS[@]}")
|
||
|
||
Datum: $(date '+%Y-%m-%d %H:%M:%S')
|
||
Host: $(hostname)"
|
||
|
||
# Vytvoř one-shot cron pro doručení
|
||
CRON_TS=$(date -u -v+1M +%Y-%m-%dT%H:%M:%S 2>/dev/null \
|
||
|| date -u -d '+1 minute' +%Y-%m-%dT%H:%M:%S)
|
||
PAYLOAD=$(printf '%s' "$MSG" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))')
|
||
|
||
if command -v hermes >/dev/null 2>&1; then
|
||
hermes cron add \
|
||
--name "disk-watch-alert-$(date +%s)" \
|
||
--at "$CRON_TS" \
|
||
--deliver all \
|
||
--message "$MSG" 2>/dev/null \
|
||
&& log "Alert naplánován na $CRON_TS" \
|
||
|| err "Nepodařilo se naplánovat alert (hermes cron)"
|
||
else
|
||
# Fallback: jen vypiš, že by se měl alert poslat
|
||
printf '\n%s[ALERT by se poslal:]%s\n' "$YELLOW" "$NC"
|
||
printf '%s\n' "$MSG"
|
||
fi
|
||
fi
|
||
|
||
exit 0 |