Загрузить файлы в «/»
This commit is contained in:
1 parent
3a427b1001
commit
a9f0571e0d
1 file changed
+417
@@ -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
|
||||||
Reference in new issue
Block a user