#!/usr/bin/env bash set -u PATH=/usr/sbin:/usr/bin:/sbin:/bin export PATH die() { echo "ZBX_NOTSUPPORTED" exit 1 } BASE="${2:-}" [ -n "$BASE" ] || die [ -d "$BASE" ] || die BASE="${BASE%/}" # # Convert: # # 260924-0949 # 260924-0949_Image_C # # to Unix timestamp. # name_to_epoch() { local n="$1" local yy mm dd hh mi year # Remove Image suffix n="${n%%_Image_*}" if [[ "$n" =~ ^([0-9]{2})([0-9]{2})([0-9]{2})-([0-9]{2})([0-9]{2})$ ]]; then yy="${BASH_REMATCH[1]}" mm="${BASH_REMATCH[2]}" dd="${BASH_REMATCH[3]}" hh="${BASH_REMATCH[4]}" mi="${BASH_REMATCH[5]}" if (( 10#$yy >= 70 )); then year="19$yy" else year="20$yy" fi date -d "${year}-${mm}-${dd} ${hh}:${mi}:00" +%s 2>/dev/null return fi echo 0 } valid_client() { [[ -n "$1" ]] || return 1 [[ "$1" != "." ]] || return 1 [[ "$1" != ".." ]] || return 1 [[ "$1" != *"/"* ]] || return 1 } client_dir() { local client="$1" valid_client "$client" || die printf '%s/%s\n' "$BASE" "$client" } # # File backup: # # 260924-0936 # is_file_backup() { local d="$1" local n="${1##*/}" [[ "$n" =~ ^[0-9]{6}-[0-9]{4}$ ]] || return 1 [ -d "$d" ] || return 1 return 0 } # # Image backup: # # 260924-0949_Image_C # # Must also contain a non-empty image file (.vhdz, .vhd or .raw). # is_image_backup() { local d="$1" local n="${1##*/}" local vhdz [[ "$n" =~ ^[0-9]{6}-[0-9]{4}_Image_.*$ ]] || return 1 [ -d "$d" ] || return 1 # Ищет любые типы виртуальных дисков, которые создает UrBackup vhdz="$(find "$d" \ -maxdepth 1 \ -type f \ \( -name '*.vhdz' -o -name '*.vhd' -o -name '*.raw' \) \ -size +0c \ -print -quit 2>/dev/null)" [ -n "$vhdz" ] } # # Find latest backup timestamp. # latest_epoch() { local dir="$1" local kind="$2" local best=0 local d local n local e [ -d "$dir" ] || { echo 0 return } while IFS= read -r -d '' d; do n="${d##*/}" case "$kind" in file) is_file_backup "$d" || continue ;; image) is_image_backup "$d" || continue ;; *) echo 0 return ;; esac e="$(name_to_epoch "$n")" if (( e > best )); then best="$e" fi done < <( find "$dir" \ -mindepth 1 \ -maxdepth 1 \ -type d \ -print0 2>/dev/null ) echo "$best" } # # Determine whether directory is a real UrBackup client. # is_client_dir() { local dir="$1" local d while IFS= read -r -d '' d; do if is_file_backup "$d"; then return 0 fi if is_image_backup "$d"; then return 0 fi done < <( find "$dir" \ -mindepth 1 \ -maxdepth 1 \ -type d \ -print0 2>/dev/null ) return 1 } # # MAIN # case "${1:-}" in discovery) printf '{"data":[' first=1 while IFS= read -r -d '' d; do client="${d##*/}" valid_client "$client" || continue is_client_dir "$d" || continue [ "$first" -eq 1 ] || printf ',' esc="$(printf '%s' "$client" | \ sed 's/\\/\\\\/g; s/"/\\"/g')" printf '{"{#CLIENT}":"%s"}' "$esc" first=0 done < <( find "$BASE" \ -mindepth 1 \ -maxdepth 1 \ -type d \ -print0 2>/dev/null | sort -z ) printf ']}\n' ;; last_ts) [ "$#" -eq 4 ] || die client="$3" kind="$4" latest_epoch \ "$(client_dir "$client")" \ "$kind" ;; last_age) [ "$#" -eq 4 ] || die client="$3" kind="$4" ts="$( latest_epoch \ "$(client_dir "$client")" \ "$kind" )" if [ "$ts" -le 0 ]; then # No backup found. echo 999999999 else now="$(date +%s)" age=$((now - ts)) (( age < 0 )) && age=0 echo "$age" fi ;; count) [ "$#" -eq 4 ] || die client="$3" kind="$4" dir="$(client_dir "$client")" count=0 while IFS= read -r -d '' d; do case "$kind" in file) is_file_backup "$d" || continue ;; image) is_image_backup "$d" || continue ;; all) if is_file_backup "$d"; then : elif is_image_backup "$d"; then : else continue fi ;; *) die ;; esac count=$((count + 1)) done < <( find "$dir" \ -mindepth 1 \ -maxdepth 1 \ -type d \ -print0 2>/dev/null ) echo "$count" ;; image_size) [ "$#" -eq 3 ] || die client="$3" dir="$(client_dir "$client")" ts="$(latest_epoch "$dir" image)" [ "$ts" -gt 0 ] || { echo 0 exit } best="" while IFS= read -r -d '' d; do is_image_backup "$d" || continue n="${d##*/}" e="$(name_to_epoch "$n")" [ "$e" -eq "$ts" ] || continue best="$d" break done < <( find "$dir" \ -mindepth 1 \ -maxdepth 1 \ -type d \ -print0 2>/dev/null ) [ -n "$best" ] || { echo 0 exit } # Ищет размер для любых форматов образов (.vhdz, .vhd, .raw) vhdz="$( find "$best" \ -maxdepth 1 \ -type f \ \( -name '*.vhdz' -o -name '*.vhd' -o -name '*.raw' \) \ -size +0c \ -print -quit 2>/dev/null )" [ -n "$vhdz" ] || { echo 0 exit } stat -c '%s' "$vhdz" 2>/dev/null || echo 0 ;; disk_free_pct) df -P "$BASE" 2>/dev/null | awk 'NR==2 { gsub(/%/,"",$5); print 100-$5 }' ;; *) die ;; esac