#!/bin/bash # Публикация готового zip-билда (например, присланного фронтендером) в ОТДЕЛЬНУЮ папку nginx. # # publish-zip.sh <имя-папки> <путь-к-zip> # # Имя папки может быть НЕ числовым (например `sol`) — такие сборки живут рядом с # номерными релизами (/opt/game/releases//) и АКТИВНУЮ сборку НЕ трогают: # корень продолжает редиректить на текущий номер, а эта сборка доступна по /<имя>/. set -euo pipefail NAME="${1:?использование: publish-zip.sh <имя-папки> <путь-к-zip>}" ZIP="${2:?использование: publish-zip.sh <имя-папки> <путь-к-zip>}" DEST="/opt/game/releases/${NAME}" TMP="/tmp/unzip-${NAME}" case "$NAME" in *[!a-zA-Z0-9_-]*|'') echo "имя папки: только буквы/цифры/дефис/подчёркивание, получено: $NAME" >&2; exit 1 ;; api|ws|solana-rpc) echo "имя '$NAME' занято служебным location — выбери другое" >&2; exit 1 ;; esac [ -f "$ZIP" ] || { echo "нет файла $ZIP" >&2; exit 1; } command -v unzip >/dev/null || DEBIAN_FRONTEND=noninteractive apt-get install -y -qq unzip >/dev/null echo "=== 1/3 распаковываю ${ZIP} ===" rm -rf "$TMP"; mkdir -p "$TMP" unzip -q "$ZIP" -d "$TMP" # если в архиве одна вложенная папка — поднимаем содержимое наверх CNT=$(find "$TMP" -mindepth 1 -maxdepth 1 | wc -l) if [ "$CNT" = 1 ]; then INNER="$(find "$TMP" -mindepth 1 -maxdepth 1)" if [ -d "$INNER" ]; then mv "$INNER"/* "$TMP"/ 2>/dev/null || true rmdir "$INNER" 2>/dev/null || true fi fi echo "=== 2/3 раскладываю в ${DEST} ===" rm -rf "$DEST"; mkdir -p "$DEST" cp -a "$TMP"/. "$DEST"/ chmod -R a+rX /opt/game/releases rm -rf "$TMP" [ -f "$DEST/index.html" ] || { echo "ВНИМАНИЕ: в сборке нет index.html — проверь архив" >&2; exit 1; } echo "=== 3/3 проверка ===" nginx -t >/dev/null && systemctl reload nginx for u in "/${NAME}/" "/${NAME}/index.html"; do printf ' %-46s %s\n' "$u" "$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1${u}")" done echo "готово: https://smart-updown.binom.pw/${NAME}/" du -sh "$DEST" ls -la "$DEST"