zioinfo-mail/setup/download_packages.sh
DESKTOP-TKLFCPR\ython d196886752 feat(setup): 폐쇄망 완전 오프라인 설치 지원
[download_packages.sh — 인터넷 서버에서 실행]
- OS별 패키지 다운로드 (ubuntu .deb / centos .rpm)
- pip wheel 전체 다운로드 (-r requirements.txt)
- Tomcat 9 tar.gz, Ollama 바이너리, Chart.js 다운로드
- Ollama 모델(llama3.1:8b, codellama:7b) 압축 패키지
- Docker 이미지 tar (docker_package.sh 연동)
- setup/offline/ 에 계층적으로 저장, README.md 자동 생성

[설치 스크립트 오프라인 지원 강화]
- setup_ubuntu.sh: OFFLINE_PKG_DIR 환경변수 지원 (.deb 로컬 설치)
- setup_centos.sh: OFFLINE_PKG_DIR 환경변수 지원 (.rpm 로컬 설치)
- 기존 TOMCAT_MIRROR=file://..., OLLAMA_INSTALL=offline 유지

[Chart.js 오프라인 폴백]
- index.html: CDN 실패 시 /static/chart.umd.min.js 로컬 폴백
- db_init.py: 오프라인 패키지에서 chart.umd.min.js 자동 복사

폐쇄망 설치 절차:
  인터넷 서버: bash setup/download_packages.sh all
  USB 복사:    tar -czf offline.tar.gz setup/offline/
  폐쇄망 설치: OFFLINE_PKG_DIR=./offline/ubuntu bash setup/setup_ubuntu.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 19:14:05 +09:00

376 lines
12 KiB
Bash

#!/bin/bash
# ============================================================
# GUARDiA 폐쇄망 설치 패키지 다운로드 스크립트
# ============================================================
# 인터넷이 연결된 Linux 서버에서 실행하세요.
# 모든 필요 파일을 setup/offline/ 에 다운로드합니다.
#
# 사용법:
# bash setup/download_packages.sh [OS유형]
# bash setup/download_packages.sh ubuntu # Ubuntu 20/22/24
# bash setup/download_packages.sh centos # CentOS 7/8/Stream
# bash setup/download_packages.sh rhel # RHEL 8/9
# bash setup/download_packages.sh all # 세 OS 모두
#
# 결과 디렉토리:
# setup/offline/
# ├── ubuntu/ deb 패키지 + pip 휠 + 바이너리
# ├── centos/ rpm 패키지 + pip 휠 + 바이너리
# ├── rhel/ rpm 패키지 + pip 휠 + 바이너리
# ├── common/ 공통 바이너리 (Tomcat, Ollama, Chart.js 등)
# └── python/ pip 휠 파일 (OS 공통)
# ============================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GUARDIA_ROOT="$(dirname "$SCRIPT_DIR")"
OFFLINE_DIR="$SCRIPT_DIR/offline"
OS_TYPE="${1:-all}"
TOMCAT_VER="${TOMCAT_VER:-9.0.98}"
PYTHON_VER="${PYTHON_VER:-3.11}"
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
fail() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
info() { echo -e " $*"; }
echo "=================================================="
echo " GUARDiA 폐쇄망 패키지 다운로드"
echo " 대상 OS: $OS_TYPE"
echo " 저장 위치: $OFFLINE_DIR"
echo "=================================================="
mkdir -p "$OFFLINE_DIR/common" "$OFFLINE_DIR/python"
# ── 공통 바이너리 다운로드 ──────────────────────────────
download_common() {
echo ""
echo "=== 공통 바이너리 다운로드 ==="
# Tomcat 9
TOMCAT_URL="https://archive.apache.org/dist/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz"
if [[ ! -f "$OFFLINE_DIR/common/apache-tomcat-${TOMCAT_VER}.tar.gz" ]]; then
echo " Tomcat $TOMCAT_VER 다운로드..."
wget -q "$TOMCAT_URL" -O "$OFFLINE_DIR/common/apache-tomcat-${TOMCAT_VER}.tar.gz" \
&& ok "Tomcat $TOMCAT_VER" || warn "Tomcat 다운로드 실패"
else
info "Tomcat $TOMCAT_VER 이미 존재"
fi
# Ollama Linux AMD64
OLLAMA_VER="${OLLAMA_VER:-latest}"
if [[ ! -f "$OFFLINE_DIR/common/ollama-linux-amd64" ]]; then
echo " Ollama 바이너리 다운로드..."
wget -q "https://ollama.com/download/ollama-linux-amd64" \
-O "$OFFLINE_DIR/common/ollama-linux-amd64" \
&& chmod +x "$OFFLINE_DIR/common/ollama-linux-amd64" \
&& ok "Ollama binary" \
|| warn "Ollama 다운로드 실패"
else
info "Ollama 바이너리 이미 존재"
fi
# Chart.js (오프라인 대시보드용)
if [[ ! -f "$OFFLINE_DIR/common/chart.umd.min.js" ]]; then
echo " Chart.js 다운로드..."
wget -q "https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js" \
-O "$OFFLINE_DIR/common/chart.umd.min.js" \
&& ok "Chart.js 4.4.0" || warn "Chart.js 다운로드 실패"
fi
# NSSM (Windows 서비스 관리자)
if [[ ! -f "$OFFLINE_DIR/common/nssm-2.24.zip" ]]; then
echo " NSSM 다운로드..."
wget -q "https://nssm.cc/release/nssm-2.24.zip" \
-O "$OFFLINE_DIR/common/nssm-2.24.zip" \
&& ok "NSSM 2.24" || warn "NSSM 다운로드 실패"
fi
}
# ── Python 패키지 (pip wheel) ───────────────────────────
download_python_packages() {
echo ""
echo "=== Python 패키지 다운로드 (pip wheel) ==="
if [[ ! -d "$OFFLINE_DIR/python/wheels" ]]; then
mkdir -p "$OFFLINE_DIR/python/wheels"
echo " requirements.txt 기반 wheel 다운로드..."
pip download \
-r "$GUARDIA_ROOT/itsm/requirements.txt" \
-d "$OFFLINE_DIR/python/wheels" \
--platform manylinux2014_x86_64 \
--python-version 311 \
--implementation cp \
--abi cp311 \
--only-binary=:all: \
2>/dev/null || true
# 일부 패키지는 소스 빌드 필요 — 아무 플랫폼 없이 재시도
pip download \
-r "$GUARDIA_ROOT/itsm/requirements.txt" \
-d "$OFFLINE_DIR/python/wheels" \
2>/dev/null || true
ok "Python 패키지 다운로드 완료 ($(ls "$OFFLINE_DIR/python/wheels" | wc -l)개)"
else
info "Python 패키지 이미 존재 ($(ls "$OFFLINE_DIR/python/wheels" | wc -l)개)"
fi
}
# ── Ubuntu/Debian 패키지 ────────────────────────────────
download_ubuntu() {
echo ""
echo "=== Ubuntu .deb 패키지 다운로드 ==="
if ! command -v apt-get &>/dev/null; then
warn "apt-get 없음 — Ubuntu/Debian 환경에서 실행하거나 Docker로 다운로드하세요."
warn " docker run --rm -v $OFFLINE_DIR/ubuntu:/downloads ubuntu:22.04 bash -c \\"
warn " 'apt-get update && apt-get install -y --download-only -o Dir::Cache::Archives=/downloads [패키지목록]'"
return
fi
UBUNTU_DIR="$OFFLINE_DIR/ubuntu"
mkdir -p "$UBUNTU_DIR"
apt-get update -qq
PACKAGES=(
python3.11 python3.11-venv python3.11-dev python3-pip
openjdk-17-jdk
openjdk-11-jdk
openjdk-8-jdk-headless
postgresql postgresql-contrib
redis-server
nginx
fail2ban
chrony
curl wget git
lsof unzip jq
libpq-dev gcc
)
echo " 패키지 다운로드 중 (${#PACKAGES[@]}개)..."
apt-get install -y --download-only \
-o Dir::Cache::Archives="$UBUNTU_DIR" \
"${PACKAGES[@]}" 2>/dev/null \
&& ok "Ubuntu .deb 다운로드 완료 ($(ls "$UBUNTU_DIR"/*.deb 2>/dev/null | wc -l)개)" \
|| warn "일부 패키지 다운로드 실패 — 이미 설치된 패키지는 아래로 수동 복사:"
# 이미 설치된 패키지의 캐시 복사
find /var/cache/apt/archives -name "*.deb" 2>/dev/null | while read -r f; do
cp -n "$f" "$UBUNTU_DIR/" 2>/dev/null || true
done
# 오프라인 설치 스크립트 생성
cat > "$UBUNTU_DIR/install_offline.sh" << 'UBSCRIPT'
#!/bin/bash
# Ubuntu 오프라인 패키지 설치
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "Ubuntu 패키지 오프라인 설치 중..."
dpkg -i "$SCRIPT_DIR"/*.deb 2>/dev/null || true
apt-get install -f -y 2>/dev/null || true
echo "완료"
UBSCRIPT
chmod +x "$UBUNTU_DIR/install_offline.sh"
ok "Ubuntu 오프라인 설치 스크립트 생성"
}
# ── CentOS/RHEL rpm 패키지 ──────────────────────────────
download_centos() {
echo ""
echo "=== CentOS/RHEL .rpm 패키지 다운로드 ==="
if ! command -v dnf &>/dev/null && ! command -v yum &>/dev/null; then
warn "dnf/yum 없음 — CentOS/RHEL 환경에서 실행하거나 Docker로 다운로드하세요."
warn " docker run --rm -v $OFFLINE_DIR/centos:/downloads centos:stream9 bash -c \\"
warn " 'dnf download --downloaddir=/downloads --resolve [패키지목록]'"
return
fi
CENTOS_DIR="$OFFLINE_DIR/centos"
mkdir -p "$CENTOS_DIR"
PACKAGES=(
python3.11 python3.11-devel python3-pip
java-17-openjdk java-17-openjdk-devel
java-11-openjdk
java-1.8.0-openjdk
postgresql-server postgresql-contrib
redis
nginx
fail2ban
chrony
curl wget git
lsof unzip jq
postgresql-devel gcc
)
PKG_MGR="dnf"
command -v dnf &>/dev/null || PKG_MGR="yum"
echo " 패키지 다운로드 중..."
$PKG_MGR install -y --downloadonly \
--downloaddir="$CENTOS_DIR" \
"${PACKAGES[@]}" 2>/dev/null \
&& ok "CentOS/RHEL .rpm 다운로드 완료 ($(ls "$CENTOS_DIR"/*.rpm 2>/dev/null | wc -l)개)" \
|| warn "일부 패키지 다운로드 실패"
cat > "$CENTOS_DIR/install_offline.sh" << 'RPMSCRIPT'
#!/bin/bash
# CentOS/RHEL 오프라인 패키지 설치
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "RPM 패키지 오프라인 설치 중..."
dnf install -y "$SCRIPT_DIR"/*.rpm --disablerepo='*' 2>/dev/null || \
yum install -y "$SCRIPT_DIR"/*.rpm 2>/dev/null || \
rpm -ivh --nodeps "$SCRIPT_DIR"/*.rpm 2>/dev/null || true
echo "완료"
RPMSCRIPT
chmod +x "$CENTOS_DIR/install_offline.sh"
ok "CentOS/RHEL 오프라인 설치 스크립트 생성"
}
# ── Ollama 모델 다운로드 ─────────────────────────────────
download_ollama_models() {
echo ""
echo "=== Ollama 모델 다운로드 ==="
MODELS_DIR="$OFFLINE_DIR/common/ollama-models"
mkdir -p "$MODELS_DIR"
MODELS=( "llama3.1:8b" "codellama:7b" )
if command -v ollama &>/dev/null; then
for model in "${MODELS[@]}"; do
echo " 모델 다운로드: $model"
ollama pull "$model" 2>&1 | tail -3 || warn "$model 다운로드 실패"
done
# 모델 파일 압축
OLLAMA_HOME="${OLLAMA_MODELS:-$HOME/.ollama}"
if [[ -d "$OLLAMA_HOME/models" ]]; then
echo " 모델 파일 압축 중..."
tar -czf "$MODELS_DIR/models.tar.gz" \
-C "$OLLAMA_HOME" models manifests 2>/dev/null \
&& ok "Ollama 모델 압축 완료 ($(du -sh "$MODELS_DIR/models.tar.gz" | cut -f1))" \
|| warn "모델 압축 실패"
fi
else
warn "Ollama 미설치 — 모델 다운로드 건너뜀"
info "설치 후 수동 실행: OLLAMA_MODELS_PATH=$MODELS_DIR ollama pull llama3.1:8b"
fi
}
# ── Docker 이미지 패키지 ─────────────────────────────────
download_docker_images() {
echo ""
echo "=== Docker 이미지 패키지 ==="
if command -v docker &>/dev/null; then
bash "$SCRIPT_DIR/docker_package.sh" "$OFFLINE_DIR/docker"
ok "Docker 이미지 패키지 완료"
else
warn "Docker 미설치 — docker_package.sh를 Docker가 설치된 서버에서 별도 실행하세요."
fi
}
# ── 설치 인덱스 생성 ─────────────────────────────────────
create_index() {
echo ""
echo "=== 설치 인덱스 생성 ==="
cat > "$OFFLINE_DIR/README.md" << RDEOF
# GUARDiA 폐쇄망 설치 패키지
생성 일시: $(date)
## 디렉토리 구조
\`\`\`
offline/
├── common/ # 공통 바이너리
│ ├── apache-tomcat-${TOMCAT_VER}.tar.gz
│ ├── ollama-linux-amd64
│ ├── chart.umd.min.js
│ └── ollama-models/models.tar.gz
├── ubuntu/ # Ubuntu .deb 패키지
│ └── install_offline.sh
├── centos/ # CentOS/RHEL .rpm 패키지
│ └── install_offline.sh
├── python/
│ └── wheels/ # pip wheel 파일
└── docker/ # Docker 이미지 tar (있는 경우)
\`\`\`
## 폐쇄망 설치 절차
### Ubuntu
\`\`\`bash
# 1. OS 패키지
bash offline/ubuntu/install_offline.sh
# 2. Python 패키지
pip install --no-index --find-links=offline/python/wheels -r itsm/requirements.txt
# 3. Tomcat
TOMCAT_MIRROR=file://\$(pwd)/offline/common bash setup/setup_ubuntu.sh
\`\`\`
### CentOS/RHEL
\`\`\`bash
bash offline/centos/install_offline.sh
pip install --no-index --find-links=offline/python/wheels -r itsm/requirements.txt
TOMCAT_MIRROR=file://\$(pwd)/offline/common bash setup/setup_centos.sh
\`\`\`
### Docker (Docker 설치된 서버)
\`\`\`bash
bash offline/docker/guardia-docker-*/docker_load.sh --start
\`\`\`
RDEOF
ok "설치 인덱스 생성: $OFFLINE_DIR/README.md"
}
# ── 메인 실행 ────────────────────────────────────────────
download_common
download_python_packages
case "$OS_TYPE" in
ubuntu)
download_ubuntu ;;
centos|rhel)
download_centos ;;
all)
download_ubuntu
download_centos ;;
docker)
download_docker_images ;;
*)
warn "알 수 없는 OS 유형: $OS_TYPE. ubuntu|centos|rhel|all|docker 중 선택하세요." ;;
esac
download_ollama_models
create_index
echo ""
echo "=================================================="
ok "다운로드 완료!"
echo ""
info "저장 위치: $OFFLINE_DIR"
info "전체 크기: $(du -sh "$OFFLINE_DIR" | cut -f1)"
echo ""
info "패키지 압축 (USB 복사용):"
info " tar -czf guardia-offline-$(date +%Y%m%d).tar.gz -C setup offline/"
echo "=================================================="