morozovka-portal/dump_project.sh
2026-10-20 03:27:14 +03:00

178 lines
6.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# dump_project.sh — собирает всё нужное для аудита проекта в один файл
# Запуск: sudo bash dump_project.sh
# Результат: /root/morozovka_dump_YYYY-MM-DD_HH-MM.txt
set -uo pipefail
PROJECT_DIR="/opt/morozovka-portal"
OUT="/root/morozovka_dump_$(date +%F_%H-%M).txt"
MAX_FILE_SIZE=$((512 * 1024)) # файлы больше 512 КБ пропускаем (обычно мусор)
# ----- исключения -----
EXCLUDES=(
"*/venv/*"
"*/__pycache__/*"
"*.pyc"
"*/.git/*"
"*/node_modules/*"
"*.log"
"*.sqlite"
"*.db"
"google_credentials.json" # СЕКРЕТ — не включаем
"*.png" "*.jpg" "*.jpeg" "*.gif" "*.ico" "*.pdf" "*.zip" "*.tar" "*.gz" "*.woff" "*.woff2" "*.ttf"
)
should_skip() {
local f="$1"
for pat in "${EXCLUDES[@]}"; do
# shellcheck disable=SC2053
[[ "$f" == $pat ]] && return 0
done
return 1
}
section() {
echo "" >> "$OUT"
echo "================================================================================" >> "$OUT"
echo "== $*" >> "$OUT"
echo "================================================================================" >> "$OUT"
}
dump_file() {
local f="$1"
[[ -f "$f" ]] || { echo "[skip: not a file] $f" >> "$OUT"; return; }
local size
size=$(stat -c%s "$f" 2>/dev/null || echo 0)
if (( size > MAX_FILE_SIZE )); then
echo "" >> "$OUT"
echo "---- FILE: $f (SKIPPED, size=${size}B > ${MAX_FILE_SIZE}B) ----" >> "$OUT"
return
fi
echo "" >> "$OUT"
echo "---- FILE: $f (size=${size}B) ----" >> "$OUT"
cat "$f" >> "$OUT"
echo "" >> "$OUT"
echo "---- END: $f ----" >> "$OUT"
}
# ----- начинаем -----
: > "$OUT"
echo "DUMP GENERATED: $(date -Is)" >> "$OUT"
echo "HOSTNAME: $(hostname -f 2>/dev/null || hostname)" >> "$OUT"
echo "UPTIME: $(uptime -p 2>/dev/null || uptime)" >> "$OUT"
# 1) Дерево файлов проекта
section "TREE: $PROJECT_DIR"
if command -v tree >/dev/null 2>&1; then
tree -a -I 'venv|__pycache__|.git|node_modules' -L 4 "$PROJECT_DIR" >> "$OUT" 2>&1
else
find "$PROJECT_DIR" \
\( -path '*/venv' -o -path '*/__pycache__' -o -path '*/.git' -o -path '*/node_modules' \) -prune -o \
-type f -print | sort >> "$OUT"
fi
# 2) requirements.txt + версия Python
section "ENVIRONMENT"
echo "python: $(command -v python3) $(python3 --version 2>&1)" >> "$OUT"
if [[ -f "$PROJECT_DIR/requirements.txt" ]]; then
echo "" >> "$OUT"
echo "--- pip freeze (из venv) ---" >> "$OUT"
if [[ -x "$PROJECT_DIR/venv/bin/pip" ]]; then
"$PROJECT_DIR/venv/bin/pip" freeze >> "$OUT" 2>&1
else
cat "$PROJECT_DIR/requirements.txt" >> "$OUT"
fi
fi
# 3) Все текстовые файлы проекта
section "PROJECT FILES ($PROJECT_DIR)"
while IFS= read -r -d '' f; do
should_skip "$f" && continue
# бинарные — пропускаем по mime
if command -v file >/dev/null 2>&1; then
case "$(file -b --mime-encoding "$f" 2>/dev/null)" in
binary) echo "" >> "$OUT"; echo "---- BINARY SKIPPED: $f ----" >> "$OUT"; continue ;;
esac
fi
dump_file "$f"
done < <(find "$PROJECT_DIR" \
\( -path '*/venv' -o -path '*/__pycache__' -o -path '*/.git' -o -path '*/node_modules' \) -prune -o \
-type f -print0 | sort -z)
# 4) systemd-юниты и таймеры проекта
section "SYSTEMD UNITS"
for u in \
/etc/systemd/system/morozovka-portal.service \
/etc/systemd/system/morozovka-sync.service \
/etc/systemd/system/morozovka-sync.timer \
/etc/systemd/system/gitea.service \
/etc/systemd/system/bridge-webui.service; do
[[ -f "$u" ]] && dump_file "$u" || echo "[missing] $u" >> "$OUT"
done
echo "" >> "$OUT"
echo "--- systemctl list-units (morozovka*) ---" >> "$OUT"
systemctl list-units --type=service --type=timer --no-pager --all --no-legend 2>/dev/null \
| grep -Ei 'morozovka|gitea|bridge' >> "$OUT" || true
echo "" >> "$OUT"
echo "--- systemctl status (кратко) ---" >> "$OUT"
for s in morozovka-portal morozovka-sync.timer gitea; do
echo "" >> "$OUT"
echo "### $s" >> "$OUT"
systemctl is-enabled "$s" 2>&1 >> "$OUT" || true
systemctl is-active "$s" 2>&1 >> "$OUT" || true
done
# 5) Nginx-конфиги (сервер 3)
section "NGINX CONFIGS (server 3)"
for d in /etc/nginx/sites-available /etc/nginx/sites-enabled /etc/nginx/conf.d; do
[[ -d "$d" ]] || continue
while IFS= read -r -d '' f; do
dump_file "$f"
done < <(find "$d" -maxdepth 1 -type f -o -type l -print0 2>/dev/null | sort -z)
done
section "NGINX TEST OUTPUT"
nginx -t 2>&1 >> "$OUT" || true
# 6) PostgreSQL: список таблиц и схема (без данных)
section "POSTGRESQL SCHEMA (morozovka_portal)"
if command -v psql >/dev/null 2>&1 || [[ -x /usr/bin/sudo ]]; then
sudo -u postgres psql -d morozovka_portal -c "\dt" >> "$OUT" 2>&1 || true
sudo -u postgres psql -d morozovka_portal -c "\d+" >> "$OUT" 2>&1 || true
echo "" >> "$OUT"
echo "--- pg_dump --schema-only ---" >> "$OUT"
sudo -u postgres pg_dump --schema-only --no-owner --no-privileges morozovka_portal >> "$OUT" 2>&1 || true
else
echo "[psql not found]" >> "$OUT"
fi
# 7) Проверка, что портал отвечает
section "PORTAL HEALTH"
curl -sS -m 5 http://127.0.0.1:8000/healthz >> "$OUT" 2>&1 || echo "[healthz failed]" >> "$OUT"
echo "" >> "$OUT"
curl -sS -m 5 -o /dev/null -w "HTTP %{http_code} time=%{time_total}s\n" http://127.0.0.1:8000/ >> "$OUT" 2>&1 || true
# 8) Последние логи (обрезанные)
section "RECENT LOGS (last 40 lines each)"
for u in morozovka-portal morozovka-sync; do
echo "" >> "$OUT"
echo "### journalctl -u $u -n 40 --no-pager" >> "$OUT"
journalctl -u "$u" -n 40 --no-pager >> "$OUT" 2>&1 || true
done
# 9) Проверка VPN/маршрутов на всякий
section "NETWORK (server 3)"
ip -brief addr >> "$OUT" 2>&1 || true
echo "" >> "$OUT"
ip route >> "$OUT" 2>&1 || true
echo "" >> "$OUT"
echo "DUMP COMPLETE: $(date -Is)" >> "$OUT"
echo "SIZE: $(du -h "$OUT" | cut -f1)" >> "$OUT"
echo "Готово: $OUT"
echo "Размер: $(du -h "$OUT" | cut -f1)"