Загрузить файлы в «/»

This commit is contained in:
lobanov_v committed 2026-09-25 09:59:38 +00:00
1 parent 3a427b1001
commit a9f0571e0d
1 file changed
+417
+417
View File
@@ -0,0 +1,417 @@
#!/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