Π‘ΠΈΡΡΠ΅ΠΌΠ½ΡΠΉ ΠΠ΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡ | Sysadmin Windows & Linux Server. ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π‘Π΅ΡΠΈ, ΠΠ ΠΈ ΠΠ΅Π»Π΅Π·Π°. IT Π£ΡΠΎΠΊΠΈ Π΄Π»Ρ Π‘ΠΈΡΠ°Π΄ΠΌΠΈΠ½Π°: ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΡ, Π‘ΠΎΡΡ ΠΈ Π’Π΅Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° (Helpdesk). ΠΠΎΠΌΠΏΡΡΡΠ΅ΡΠ½Π°Ρ ΠΏΠΎΠΌΠΎΡΡ.
IT ΠΈ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Β· 18 ΠΈΡΠ»Ρ 2026 Π³.
π Π‘ΠΊΡΠΈΠΏΡ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΠΊΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΡΠ°Π»ΠΎΠ³ΠΈ Π²ΡΡΠΎΡΠ»ΠΈ Ρ ΠΏΡΠΎΡΠ»ΠΎΠ³ΠΎ Π·Π°ΠΏΡΡΠΊΠ°
π Π‘ΠΊΡΠΈΠΏΡ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΠΊΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΡΠ°Π»ΠΎΠ³ΠΈ Π²ΡΡΠΎΡΠ»ΠΈ Ρ ΠΏΡΠΎΡΠ»ΠΎΠ³ΠΎ Π·Π°ΠΏΡΡΠΊΠ° Π‘ΠΊΡΠΈΠΏΡ Π½ΠΈΠΆΠ΅ Π΄Π΅Π»Π°Π΅Ρ ΡΠ½ΠΈΠΌΠΎΠΊ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ² ΠΊΠ°ΡΠ°Π»ΠΎΠ³ΠΎΠ² (ΡΠ΅ΡΠ΅Π· du), Π° ΠΏΡΠΈ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌ Π·Π°ΠΏΡΡΠΊΠ΅ ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ ΡΠΎΠΏ ΠΏΡΠΈΡΠΎΡΡΠΎΠ² - ΠΊΡΠΎ Π²ΡΡΠΎΡ ΠΈ Π½Π° ΡΠΊΠΎΠ»ΡΠΊΠΎ. #!/usr/bin/env bash # Π°Π²ΡΠΎΡ: https://t.me/i_odmin set -Eeuo pipefail usage() { cat <<'HELP' Usage: du-delta.sh [-p PATH] [-d DEPTH] [-n TOP] [-t THRESH] [-s STATE_DIR] -p PATH ΠΠΎΡΠ΅Π½Ρ Π°Π½Π°Π»ΠΈΠ·Π° (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ /) -d DEPTH ΠΠ»ΡΠ±ΠΈΠ½Π° du (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 2) -n TOP Π‘ΠΊΠΎΠ»ΡΠΊΠΎ ΡΡΡΠΎΠΊ ΠΏΠΎΠΊΠ°Π·Π°ΡΡ (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 15) -t THRESH ΠΠΎΡΠΎΠ³ ΡΠΎΡΡΠ° (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ 100M, 1G; ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ 100M) -s STATE_DIR ΠΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ (ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ /var/lib/du-delta) -h ΠΠΎΠΌΠΎΡΡ ΠΡΠΈΠΌ.: ΡΡΠ΅Π±ΡΡΡΡΡ ΠΏΡΠ°Π²Π° Π½Π° ΡΡΠ΅Π½ΠΈΠ΅ Π°Π½Π°Π»ΠΈΠ·ΠΈΡΡΠ΅ΠΌΡΡ ΠΊΠ°ΡΠ°Π»ΠΎΠ³ΠΎΠ². HELP } PATH_TO="/" DEPTH=2 TOP=15 THRESH="100M" STATE_DIR="/var/lib/du-delta" while getopts ":p:d:n:t:s:h" opt; do case "$opt" in p) PATH_TO="$OPTARG" ;; d) DEPTH="$OPTARG" ;; n) TOP="$OPTARG" ;; t) THRESH="$OPTARG" ;; s) STATE_DIR="$OPTARG" ;; h) usage; exit 0 ;; \?) echo "ΠΠ΅ΠΈΠ·Π²Π΅ΡΡΠ½ΡΠΉ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡ: -$OPTARG" >&2; usage; exit 1 ;; π echo "ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ -$OPTARG Π½ΡΠΆΠ½ΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅" >&2; exit 1 ;; esac done to_bytes() { local v="$1" if command -v numfmt >/dev/null 2>&1; then numfmt --from=iec "$v" else awk -v s="$v" 'BEGIN{ n=s; sub(/[KkMmGgTtPp][Bb]?$/,"",n); u=""; if (match(s,/[KkMmGgTtPp]/)) u=substr(s,RSTART,1); m=1; if(u=="K"||u=="k") m=1024; else if(u=="M"||u=="m") m=1024^2; else if(u=="G"||u=="g") m=1024^3; else if(u=="T"||u=="t") m=1024^4; else if(u=="P"||u=="p") m=1024^5; printf "%d", n*m }' fi } human() { local b="$1" if command -v numfmt >/dev/null 2>&1; then numfmt --to=iec --suffix=B "$b" else awk -v b="$b" 'function h(x, a,i){ split("B KiB MiB GiB TiB PiB",a," "); for(i=1; x>=1024 && i<6; i++) x/=1024; return sprintf("%.1f %s", x, a[i]) } BEGIN{print h(b)}' fi } # ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΡΠΉ ΠΊΠ»ΡΡ Π³Π»ΡΠ±ΠΈΠ½Ρ Π΄Π»Ρ du if du -d 0 / >/dev/null 2>&1; then DU_DEPTH=(-d "$DEPTH") else DU_DEPTH=(--max-depth="$DEPTH") fi mkdir -p "$STATE_DIR" chmod 700 "$STATE_DIR" # ΠΠΌΡ ΡΠ½Π°ΠΏΡΠΎΡΠ° Π·Π°Π²ΠΈΡΠΈΡ ΠΎΡ ΠΏΡΡΠΈ ΠΈ Π³Π»ΡΠ±ΠΈΠ½Ρ safe_name="$(echo "$PATH_TO" | sed 's|/|_|g; s|^_$|root|')_d${DEPTH}.tsv" SNAP_FILE="$STATE_DIR/$safe_name" tmp_cur="$(mktemp)" trap 'rm -f "$tmp_cur"' EXIT # Π‘Π½ΠΈΠΌΠΎΠΊ ΡΠ΅ΠΊΡΡΠΈΡ ΡΠ°Π·ΠΌΠ΅ΡΠΎΠ²: "path \t bytes" # -B1: Π±Π°ΠΉΡΡ, -x: Π½Π΅ Π²ΡΠ»Π΅Π·Π°ΡΡ Π½Π° Π΄ΡΡΠ³ΠΈΠ΅ Π€Π‘, --apparent-size: ΠΏΠΎ ΠΆΠ΅Π»Π°Π½ΠΈΡ (ΠΊΠΎΠΌΠΌΠ΅Π½Ρ Π½ΠΈΠΆΠ΅) # Π£Π±Π΅ΡΠΈΡΠ΅ --apparent-size, Π΅ΡΠ»ΠΈ Ρ ΠΎΡΠΈΡΠ΅ ΡΡΠΈΡΠ°ΡΡ Π²ΡΠ΄Π΅Π»Π΅Π½Π½ΡΠ΅ Π±Π»ΠΎΠΊΠΈ, Π° Π½Π΅ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ°Π·ΠΌΠ΅Ρ. du -B1 "${DU_DEPTH[@]}" -x --apparent-size "$PATH_TO" 2>/dev/null \ | awk 'BEGIN{OFS="\t"} {sz=$1; $1=""; sub(/^[ \t]+/,""); print $0, sz}' \ | sort -k1,1 > "$tmp_cur" # ΠΡΠ»ΠΈ Π΅ΡΡΡ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠΈΠΉ ΡΠ½ΠΈΠΌΠΎΠΊ β ΡΡΠΈΡΠ°Π΅ΠΌ Π΄Π΅Π»ΡΡΡ THRESH_BYTES="$(to_bytes "$THRESH")" printf "π Π’ΠΎΠΏ %d ΠΏΡΠΈΡΠΎΡΡΠΎΠ² Π² %s (Π³Π»ΡΠ±ΠΈΠ½Π° %d, ΠΏΠΎΡΠΎΠ³ %s):\n" \ "$TOP" "$PATH_TO" "$DEPTH" "$THRESH" if [[ -s "$SNAP_FILE" ]]; then awk -F'\t' -v th="$THRESH_BYTES" ' NR==FNR { prev[$1]=$2; next } { cur=$2+0; p=(($1 in prev)?prev[$1]+0:0); d=cur-p; if (d>=th) { print $1 "\t" d } } ' "$SNAP_FILE" "$tmp_cur" \ | sort -k2,2nr \ | head -n "$TOP" \ | awk -F'\t' '{printf " + %-8s %s\n", "'"$(human "$2")"'", $1}' \ || true else echo " (ΠΏΠ΅ΡΠ²ΡΠΉ Π·Π°ΠΏΡΡΠΊ β ΡΠ½ΠΈΠΌΠ°Ρ Π±Π°Π·ΠΎΠ²ΡΡ ΠΌΠ΅ΡΡΠΈΠΊΡ, ΡΡΠ°Π²Π½ΠΈΠ²Π°ΡΡ Π½Π΅ Ρ ΡΠ΅ΠΌ)" fi # ΠΠ±Π½ΠΎΠ²Π»ΡΠ΅ΠΌ ΡΠ½ΠΈΠΌΠΎΠΊ mv -f "$tmp_cur" "$SNAP_FILE" - ΠΡΡΡΡΡΠΉ Π·Π°ΠΏΡΡΠΊ Π²ΡΡΡΠ½ΡΡ: sudo bash du-delta.sh -p /var -d 3 -t 200M -n 20 - ΠΠΎΠ²Π΅ΡΠΈΡΡ Π½Π° cron (ΠΊΠ°ΠΆΠ΄ΡΠ΅ 6 ΡΠ°ΡΠΎΠ²) ΠΈ ΠΏΠΈΡΠ°ΡΡ Π² syslog: */6 * * * * root /usr/local/sbin/du-delta.sh -p / -d 3 -t 200M -n 20 | logger -t du-delta Π₯ΠΎΡΠ΅ΡΡ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠ°ΠΉΠ»ΠΎΠ² (ΠΊΠ°ΠΊ Π²ΠΈΠ΄ΠΈΡ ls -l) - ΠΎΡΡΠ°Π²Π»ΡΠΉ --apparent-size. ΠΡΠΆΠ΅Π½ ΠΈΠΌΠ΅Π½Π½ΠΎ Π·Π°Π½ΡΡΡΠΉ Π½Π° Π΄ΠΈΡΠΊΠ΅ ΠΎΠ±ΡΡΠΌ - ΡΠ±Π΅ΡΠΈ ΡΡΠΎΡ ΡΠ»Π°Π³. π‘ ΠΠ°ΡΠ½ΠΈ Ρ -d 2 Π΄Π»Ρ ΠΎΠ±Π·ΠΎΡΠ° Π²Π΅ΡΡ Π½ΠΈΡ ΡΡΠΎΠ²Π½Π΅ΠΉ, ΠΏΠΎΡΠΎΠΌ ΡΠΎΡΠ΅ΡΠ½ΠΎ ΡΠΏΡΡΠΊΠ°ΠΉΡΡ Π³Π»ΡΠ±ΠΆΠ΅ ΠΏΠΎ Β«ΠΏΠΎΠ΄ΠΎΠ·ΡΠΈΡΠ΅Π»ΡΠ½ΡΠΌΒ» ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π°ΠΌ. π @i_odmin
ΠΠ°Π½Π°Π» Π² ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π΅ ΠΠ°ΠΊΡΠΈΠΌΠ΅ΡΠ΅ΡΠ°
6Β 171 ΠΏΠΎΠ΄ΠΏΠΈΡΡΠΈΠΊΠΎΠ² Β· IT ΠΈ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ