feat: один апдейтер на несколько репозиториев
build / build (push) Successful in 20s

update-geodata.sh теперь ходит по списку SOURCES (строка «URL-базы|имя»),
а не по одной базе: ipcheck.dat и оба discord-.dat обновляются за один
запуск и с одним перезапуском сервиса. Старый вызов с DEST продолжает
работать — каталог берётся из него.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Leonid Pershin
2026-08-10 09:31:14 +03:00
co-authored by Claude Opus 5
parent 60c7141f88
commit e6186ba6df
2 changed files with 61 additions and 19 deletions
+41 -16
View File
@@ -1,6 +1,5 @@
#!/bin/sh
# Обновляет локальные discord-geosite.dat и discord-geoip.dat из ветки release.
# Рассчитан на запуск по cron.
# Обновляет geosite/geoip-файлы Xray из веток release. Рассчитан на cron.
#
# Каждый файл скачивается, только если его sha256 отличается от локального,
# контрольная сумма проверяется до подмены, а сервис перезапускается один раз
@@ -8,20 +7,35 @@
# cron не будет слать письма впустую.
#
# ./update-geodata.sh
# BASE_URL=https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release \
# DEST_DIR=/usr/local/x-ui/bin RESTART_CMD='x-ui restart' ./update-geodata.sh
# RESTART_CMD='x-ui restart' ./update-geodata.sh
#
# Что качать, задаёт SOURCES — по строке на файл, формат «URL-базы|имя-файла»
# (без «|» берётся BASE_URL). По умолчанию это ipcheck.dat из ipcheck-domains
# и оба .dat из discord-geodata:
#
# SOURCES='https://example.org/raw/branch/release|my.dat' ./update-geodata.sh
#
# NAMES задаёт список файлов; по умолчанию — оба .dat.
# Коды возврата: 0 — обновлено или уже актуально, 1 — ошибка.
set -eu
BASE_URL="${BASE_URL:-https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release}"
DEST_DIR="${DEST_DIR:-/usr/local/x-ui/bin}"
NAMES="${NAMES:-discord-geosite.dat discord-geoip.dat}"
BASE_URL="${BASE_URL:-https://gitea.hsrv.site/mrleo1nid/ipcheck-domains/raw/branch/release}"
DISCORD_URL="${DISCORD_URL:-https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release}"
RESTART_CMD="${RESTART_CMD:-}"
TIMEOUT="${TIMEOUT:-30}"
# Совместимость со старым вызовом, где DEST задавал единственный файл целиком.
if [ -n "${DEST:-}" ]; then
DEST_DIR=$(dirname "$DEST")
NAME="${NAME:-$(basename "$DEST")}"
fi
SOURCES="${SOURCES:-\
$BASE_URL|${NAME:-ipcheck.dat}
$DISCORD_URL|discord-geosite.dat
$DISCORD_URL|discord-geoip.dat}"
log() { printf '%s update-geodata: %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$*"; }
die() { log "ОШИБКА: $*" >&2; exit 1; }
@@ -37,15 +51,26 @@ fi
fetch() { curl -fsSL --retry 3 --retry-delay 2 --max-time "$TIMEOUT" "$1"; }
tmp=""
cleanup() { [ -z "$tmp" ] || rm -f "$tmp"; }
trap cleanup EXIT INT TERM
mkdir -p "$DEST_DIR"
changed=0
for name in $NAMES; do
# Цикл читает SOURCES через here-doc, а не из конвейера: в подоболочке
# счётчик changed не пережил бы выход из цикла.
while IFS='|' read -r base name; do
[ -n "$base" ] || continue
if [ -z "$name" ]; then
name="$base"
base="$BASE_URL"
fi
dest="$DEST_DIR/$name"
# Без промежуточной переменной статус вернул бы cut, а не curl.
remote_line=$(fetch "$BASE_URL/$name.sha256sum") ||
die "не удалось скачать $BASE_URL/$name.sha256sum"
remote_line=$(fetch "$base/$name.sha256sum") ||
die "не удалось скачать $base/$name.sha256sum"
remote_sum=$(printf '%s' "$remote_line" | cut -d' ' -f1)
case "$remote_sum" in
[0-9a-f][0-9a-f]*) [ "${#remote_sum}" -eq 64 ] || die "битая контрольная сумма: $remote_sum" ;;
@@ -56,10 +81,8 @@ for name in $NAMES; do
continue # уже актуально — тишина
fi
tmp=$(mktemp "${TMPDIR:-/tmp}/discord-geodata.XXXXXX") || die "не удалось создать временный файл"
trap 'rm -f "$tmp"' EXIT INT TERM
fetch "$BASE_URL/$name" > "$tmp" || die "не удалось скачать $BASE_URL/$name"
tmp=$(mktemp "${TMPDIR:-/tmp}/geodata.XXXXXX") || die "не удалось создать временный файл"
fetch "$base/$name" > "$tmp" || die "не удалось скачать $base/$name"
got=$(hash_of "$tmp")
[ "$got" = "$remote_sum" ] || die "$name: ожидалось $remote_sum, получено $got"
@@ -69,11 +92,13 @@ for name in $NAMES; do
# mv в пределах одного каталога атомарен: Xray никогда не увидит половину файла.
cat "$tmp" > "$dest.new" && mv -f "$dest.new" "$dest" || die "не удалось записать $dest"
rm -f "$tmp"
trap - EXIT INT TERM
tmp=""
log "обновлён $dest (sha256 $remote_sum)"
changed=1
done
done <<EOF
$SOURCES
EOF
[ "$changed" -eq 1 ] || exit 0