초기 커밋: PBS 백업 복구 스크립트
✨ 주요 기능: - PBS (Proxmox Backup Server)에서 VM/Container 백업 복구 - 대화형 모드로 쉬운 백업 선택 및 복구 - 백업 목록 조회 및 VMID별 검색 - VM 및 Container 타입 자동 감지 - VMID 중복 확인 및 다른 VMID로 복구 (클론) - 스토리지 선택 가능 - 안전한 확인 절차 포함 🛠️ 포함 파일: - pbs-restore.sh: PBS 백업 복구 스크립트 - README.md: 상세한 사용 가이드, 시나리오 및 문제 해결 📦 사용 방법: # 대화형 모드 (권장) curl -fsSL https://git.0bin.in/thug0bin/pve-pbs-restore/raw/branch/main/pbs-restore.sh | bash # 백업 목록 보기 ./pbs-restore.sh -l -s pbs-backup -v 100 # 비대화형 복구 ./pbs-restore.sh -r -V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" -t 100 -T vm 🔧 주요 기능: - qmrestore 및 pct restore 명령어 활용 - 컬러 출력으로 가독성 향상 - Volume ID 자동 파싱 - 백업 날짜 및 크기 표시 - 복구 전 확인 단계 - Root 권한 및 Proxmox VE 환경 자동 확인 🎯 사용 사례: - 삭제된 VM/Container 복구 - VM 클론 생성 (테스트 환경) - 특정 시점으로 롤백 - 재해 복구 (Disaster Recovery) - 자동화 스크립트에 통합 💡 특징: - 3가지 모드: 대화형, 목록, 복구 - VMID 가용성 자동 확인 - 다중 PBS 스토리지 지원 - 추가 복구 옵션 지원 (--unique, --force 등) - 상세한 에러 메시지 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
070a23ff74
460
README.md
Normal file
460
README.md
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
# PBS 백업 복구 스크립트
|
||||||
|
|
||||||
|
Proxmox Backup Server(PBS)에서 VM 및 Container 백업을 쉽고 빠르게 복구하는 스크립트입니다.
|
||||||
|
|
||||||
|
## 특징
|
||||||
|
|
||||||
|
- ✅ 대화형 모드로 쉬운 백업 선택 및 복구
|
||||||
|
- ✅ 백업 목록 조회 및 검색
|
||||||
|
- ✅ VM 및 Container 자동 감지
|
||||||
|
- ✅ VMID 중복 확인
|
||||||
|
- ✅ 다른 VMID로 복구 가능 (클론)
|
||||||
|
- ✅ 스토리지 선택 가능
|
||||||
|
- ✅ 컬러 출력으로 가독성 향상
|
||||||
|
- ✅ 안전한 확인 절차
|
||||||
|
|
||||||
|
## 요구사항
|
||||||
|
|
||||||
|
- Proxmox VE 7.0 이상
|
||||||
|
- PBS 스토리지가 PVE에 추가되어 있어야 함
|
||||||
|
- Root 권한
|
||||||
|
|
||||||
|
## 빠른 설치
|
||||||
|
|
||||||
|
### 방법 1: 원라인 실행 (대화형 모드)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://git.0bin.in/thug0bin/pve-pbs-restore/raw/branch/main/pbs-restore.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 방법 2: 다운로드 후 실행
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://git.0bin.in/thug0bin/pve-pbs-restore/raw/branch/main/pbs-restore.sh
|
||||||
|
chmod +x pbs-restore.sh
|
||||||
|
./pbs-restore.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 사용 방법
|
||||||
|
|
||||||
|
### 1. 대화형 모드 (가장 쉬움, 권장)
|
||||||
|
|
||||||
|
스크립트를 실행하면 단계별로 안내합니다:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**진행 순서:**
|
||||||
|
1. PBS 스토리지 선택
|
||||||
|
2. 복구할 원본 VMID 입력
|
||||||
|
3. 백업 목록에서 선택
|
||||||
|
4. 타겟 VMID 입력 (같은 VMID 또는 새로운 VMID)
|
||||||
|
5. 복구할 스토리지 선택
|
||||||
|
6. 확인 후 복구 진행
|
||||||
|
|
||||||
|
### 2. 백업 목록 보기
|
||||||
|
|
||||||
|
#### 모든 백업 보기
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -l -s pbs-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 특정 VMID의 백업만 보기
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -l -s pbs-backup -v 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 비대화형 복구 (자동화)
|
||||||
|
|
||||||
|
#### VM 복구 (같은 VMID로)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" \
|
||||||
|
-t 100 \
|
||||||
|
-T vm
|
||||||
|
```
|
||||||
|
|
||||||
|
#### VM 복구 (다른 VMID로 - 클론)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" \
|
||||||
|
-t 150 \
|
||||||
|
-T vm \
|
||||||
|
-S local-lvm
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Container 복구
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/ct-200-2025_01_28-10_00_00.tar.zst" \
|
||||||
|
-t 200 \
|
||||||
|
-T ct
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 추가 옵션과 함께 복구
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" \
|
||||||
|
-t 100 \
|
||||||
|
-T vm \
|
||||||
|
-S local-lvm \
|
||||||
|
-o "--unique --force"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 명령어 옵션
|
||||||
|
|
||||||
|
### 모드 선택
|
||||||
|
|
||||||
|
| 옵션 | 설명 | 필수 |
|
||||||
|
|------|------|------|
|
||||||
|
| (없음) | 대화형 모드 실행 | - |
|
||||||
|
| `-l` | 백업 목록 보기 모드 | - |
|
||||||
|
| `-r` | 백업 복구 모드 | - |
|
||||||
|
| `-h` | 도움말 표시 | - |
|
||||||
|
|
||||||
|
### 백업 목록 모드 옵션
|
||||||
|
|
||||||
|
| 옵션 | 설명 | 필수 |
|
||||||
|
|------|------|------|
|
||||||
|
| `-s STORAGE` | PBS 스토리지 이름 | ✓ |
|
||||||
|
| `-v VMID` | 특정 VMID의 백업만 검색 | ✗ |
|
||||||
|
|
||||||
|
### 복구 모드 옵션
|
||||||
|
|
||||||
|
| 옵션 | 설명 | 필수 |
|
||||||
|
|------|------|------|
|
||||||
|
| `-V VOLID` | 복구할 Volume ID | ✓ |
|
||||||
|
| `-t VMID` | 타겟 VMID | ✓ |
|
||||||
|
| `-T TYPE` | 백업 타입 (vm/ct) | ✗ (자동 감지) |
|
||||||
|
| `-S STORAGE` | 복구할 스토리지 | ✗ |
|
||||||
|
| `-o OPTIONS` | 추가 옵션 | ✗ |
|
||||||
|
|
||||||
|
## 사용 시나리오
|
||||||
|
|
||||||
|
### 시나리오 1: 삭제된 VM 복구
|
||||||
|
|
||||||
|
VM을 실수로 삭제한 경우 원래 VMID로 복구:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh
|
||||||
|
# 대화형 모드에서:
|
||||||
|
# 1. PBS 스토리지 선택
|
||||||
|
# 2. 삭제된 VMID 입력
|
||||||
|
# 3. 최신 백업 선택
|
||||||
|
# 4. 같은 VMID로 복구
|
||||||
|
```
|
||||||
|
|
||||||
|
### 시나리오 2: VM 클론 (테스트용)
|
||||||
|
|
||||||
|
프로덕션 VM을 다른 VMID로 복구하여 테스트 환경 구축:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" \
|
||||||
|
-t 999 \
|
||||||
|
-T vm \
|
||||||
|
-S local-lvm
|
||||||
|
```
|
||||||
|
|
||||||
|
### 시나리오 3: 특정 시점으로 롤백
|
||||||
|
|
||||||
|
특정 날짜의 백업으로 복구:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 백업 목록에서 날짜 확인
|
||||||
|
./pbs-restore.sh -l -s pbs-backup -v 100
|
||||||
|
|
||||||
|
# 2. 원하는 날짜의 백업 선택하여 복구
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/vm-100-2025_01_20-02_00_00.vma.zst" \
|
||||||
|
-t 100 \
|
||||||
|
-T vm
|
||||||
|
```
|
||||||
|
|
||||||
|
### 시나리오 4: Container 복구
|
||||||
|
|
||||||
|
LXC Container 복구:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh
|
||||||
|
# Container VMID 입력
|
||||||
|
# 백업 선택
|
||||||
|
# 복구 진행
|
||||||
|
```
|
||||||
|
|
||||||
|
### 시나리오 5: 재해 복구 (Disaster Recovery)
|
||||||
|
|
||||||
|
서버 장애 후 전체 VM 복구:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 각 VM에 대해 반복
|
||||||
|
for vmid in 100 101 102 200 201; do
|
||||||
|
./pbs-restore.sh -l -s pbs-backup -v $vmid
|
||||||
|
# 최신 백업 확인 후 복구
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
## Volume ID 형식
|
||||||
|
|
||||||
|
PBS의 Volume ID는 다음과 같은 형식을 가집니다:
|
||||||
|
|
||||||
|
```
|
||||||
|
STORAGE:backup/TYPE-VMID-DATE.EXTENSION
|
||||||
|
|
||||||
|
예시:
|
||||||
|
pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst
|
||||||
|
pbs-backup:backup/ct-200-2025_01_28-15_30_00.tar.zst
|
||||||
|
```
|
||||||
|
|
||||||
|
**구성 요소:**
|
||||||
|
- `STORAGE`: PBS 스토리지 이름
|
||||||
|
- `TYPE`: `vm` (가상머신) 또는 `ct` (컨테이너)
|
||||||
|
- `VMID`: VM/CT ID
|
||||||
|
- `DATE`: 백업 날짜 및 시간
|
||||||
|
- `EXTENSION`: 압축 형식 (`.vma.zst`, `.tar.zst` 등)
|
||||||
|
|
||||||
|
## 복구 옵션 상세
|
||||||
|
|
||||||
|
### VM 복구 옵션 (qmrestore)
|
||||||
|
|
||||||
|
| 옵션 | 설명 | 예시 |
|
||||||
|
|------|------|------|
|
||||||
|
| `--storage` | 복구할 스토리지 | `--storage local-lvm` |
|
||||||
|
| `--unique` | MAC 주소 및 UUID 재생성 | `--unique` |
|
||||||
|
| `--force` | 기존 VM 덮어쓰기 | `--force` |
|
||||||
|
| `--pool` | 리소스 풀 지정 | `--pool production` |
|
||||||
|
|
||||||
|
예시:
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" \
|
||||||
|
-t 150 \
|
||||||
|
-T vm \
|
||||||
|
-o "--unique --pool test"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Container 복구 옵션 (pct restore)
|
||||||
|
|
||||||
|
| 옵션 | 설명 | 예시 |
|
||||||
|
|------|------|------|
|
||||||
|
| `--storage` | 복구할 스토리지 | `--storage local-lvm` |
|
||||||
|
| `--force` | 기존 CT 덮어쓰기 | `--force` |
|
||||||
|
| `--unprivileged` | 비특권 컨테이너로 복구 | `--unprivileged 1` |
|
||||||
|
| `--pool` | 리소스 풀 지정 | `--pool production` |
|
||||||
|
|
||||||
|
예시:
|
||||||
|
```bash
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/ct-200-2025_01_28-10_00_00.tar.zst" \
|
||||||
|
-t 201 \
|
||||||
|
-T ct \
|
||||||
|
-o "--unprivileged 1 --force"
|
||||||
|
```
|
||||||
|
|
||||||
|
## PBS 스토리지 추가
|
||||||
|
|
||||||
|
PBS 스토리지가 아직 추가되지 않았다면, 먼저 추가해야 합니다:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PBS 스토리지 추가 스크립트 사용
|
||||||
|
curl -fsSL https://git.0bin.in/thug0bin/pve-add-pbs-storage/raw/branch/main/add-pbs-storage.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
또는 수동으로:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pvesm add pbs pbs-backup \
|
||||||
|
--server 192.168.1.100 \
|
||||||
|
--datastore datastore1 \
|
||||||
|
--username "root@pam!backup" \
|
||||||
|
--password "your-token-secret"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 복구 후 확인
|
||||||
|
|
||||||
|
복구가 완료된 후 다음 명령어로 확인:
|
||||||
|
|
||||||
|
### VM 확인
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# VM 상태 확인
|
||||||
|
qm status 100
|
||||||
|
|
||||||
|
# VM 설정 확인
|
||||||
|
qm config 100
|
||||||
|
|
||||||
|
# VM 시작
|
||||||
|
qm start 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Container 확인
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# CT 상태 확인
|
||||||
|
pct status 200
|
||||||
|
|
||||||
|
# CT 설정 확인
|
||||||
|
pct config 200
|
||||||
|
|
||||||
|
# CT 시작
|
||||||
|
pct start 200
|
||||||
|
```
|
||||||
|
|
||||||
|
## 문제 해결
|
||||||
|
|
||||||
|
### 백업을 찾을 수 없음
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PBS 스토리지 연결 확인
|
||||||
|
pvesm status --storage pbs-backup
|
||||||
|
|
||||||
|
# PBS 스토리지 컨텐츠 확인
|
||||||
|
pvesm list pbs-backup
|
||||||
|
```
|
||||||
|
|
||||||
|
### VMID가 이미 사용 중
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 기존 VM/CT 삭제
|
||||||
|
qm destroy 100
|
||||||
|
# 또는
|
||||||
|
pct destroy 200
|
||||||
|
|
||||||
|
# 또는 다른 VMID로 복구
|
||||||
|
./pbs-restore.sh -r -V "..." -t 999 -T vm
|
||||||
|
```
|
||||||
|
|
||||||
|
### 복구 실패 - 스토리지 공간 부족
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 스토리지 공간 확인
|
||||||
|
pvesm status
|
||||||
|
|
||||||
|
# 다른 스토리지로 복구
|
||||||
|
./pbs-restore.sh -r -V "..." -t 100 -T vm -S other-storage
|
||||||
|
```
|
||||||
|
|
||||||
|
### 복구 실패 - 권한 문제
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Root로 실행 확인
|
||||||
|
sudo ./pbs-restore.sh
|
||||||
|
|
||||||
|
# PBS API Token 권한 확인 (PBS 웹 UI)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Volume ID를 찾을 수 없음
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 올바른 형식 확인
|
||||||
|
pvesm list pbs-backup | grep vm-100
|
||||||
|
|
||||||
|
# 복사한 Volume ID 사용
|
||||||
|
./pbs-restore.sh -r \
|
||||||
|
-V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" \
|
||||||
|
-t 100 -T vm
|
||||||
|
```
|
||||||
|
|
||||||
|
## 고급 사용법
|
||||||
|
|
||||||
|
### 스크립트로 자동화
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# 자동 복구 스크립트 예시
|
||||||
|
|
||||||
|
PBS_STORAGE="pbs-backup"
|
||||||
|
VMID_LIST=(100 101 102)
|
||||||
|
|
||||||
|
for vmid in "${VMID_LIST[@]}"; do
|
||||||
|
echo "Checking backups for VMID: $vmid"
|
||||||
|
|
||||||
|
# 최신 백업 가져오기
|
||||||
|
latest_backup=$(pvesm list "$PBS_STORAGE" | \
|
||||||
|
grep -E "vm-${vmid}-" | \
|
||||||
|
tail -1 | \
|
||||||
|
awk '{print $1}')
|
||||||
|
|
||||||
|
if [ -n "$latest_backup" ]; then
|
||||||
|
echo "Restoring: $latest_backup"
|
||||||
|
./pbs-restore.sh -r -V "$latest_backup" -t "$vmid" -T vm
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### 특정 기간의 백업 찾기
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 특정 날짜의 백업 검색
|
||||||
|
./pbs-restore.sh -l -s pbs-backup -v 100 | grep "2025-01-28"
|
||||||
|
|
||||||
|
# 최근 7일 백업 검색
|
||||||
|
pvesm list pbs-backup | grep "vm-100" | tail -7
|
||||||
|
```
|
||||||
|
|
||||||
|
### 병렬 복구 (여러 VM 동시 복구)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# 여러 VM을 동시에 복구 (신중하게 사용!)
|
||||||
|
|
||||||
|
restore_vm() {
|
||||||
|
local volid="$1"
|
||||||
|
local vmid="$2"
|
||||||
|
./pbs-restore.sh -r -V "$volid" -t "$vmid" -T vm &
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_vm "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" 100
|
||||||
|
restore_vm "pbs-backup:backup/vm-101-2025_01_28-10_00_00.vma.zst" 101
|
||||||
|
restore_vm "pbs-backup:backup/vm-102-2025_01_28-10_00_00.vma.zst" 102
|
||||||
|
|
||||||
|
wait
|
||||||
|
echo "모든 복구 완료"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 백업 전략 권장사항
|
||||||
|
|
||||||
|
1. **정기 백업**: 자동 백업 스케줄 설정
|
||||||
|
2. **보존 정책**: 적절한 백업 보관 기간 설정
|
||||||
|
3. **복구 테스트**: 정기적으로 복구 테스트 수행
|
||||||
|
4. **문서화**: 중요 VM의 복구 절차 문서화
|
||||||
|
5. **오프사이트 백업**: PBS Remote Sync로 원격 백업
|
||||||
|
|
||||||
|
## 보안 고려사항
|
||||||
|
|
||||||
|
- ✅ Root 권한으로만 실행
|
||||||
|
- ✅ PBS API Token 사용 권장
|
||||||
|
- ✅ 복구 전 항상 확인 단계 포함
|
||||||
|
- ✅ 중요 VM은 복구 테스트 수행
|
||||||
|
- ✅ 백업 암호화 사용 권장
|
||||||
|
|
||||||
|
## 참고 자료
|
||||||
|
|
||||||
|
- [Proxmox VE Backup and Restore](https://pve.proxmox.com/wiki/Backup_and_Restore)
|
||||||
|
- [Proxmox Backup Server 공식 문서](https://pbs.proxmox.com/docs/)
|
||||||
|
- [qmrestore 매뉴얼](https://pve.proxmox.com/pve-docs/qmrestore.1.html)
|
||||||
|
- [pct restore 매뉴얼](https://pve.proxmox.com/pve-docs/pct.1.html)
|
||||||
|
|
||||||
|
## 라이선스
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
## 기여
|
||||||
|
|
||||||
|
Issues 및 Pull Requests는 언제나 환영합니다!
|
||||||
|
|
||||||
|
## 관련 프로젝트
|
||||||
|
|
||||||
|
- [pve-add-pbs-storage](https://git.0bin.in/thug0bin/pve-add-pbs-storage) - PBS 스토리지 추가 스크립트
|
||||||
|
- [pve9-repo-fix](https://git.0bin.in/thug0bin/pve9-repo-fix) - Proxmox VE 9.0 저장소 수정 스크립트
|
||||||
|
|
||||||
|
## 지원
|
||||||
|
|
||||||
|
문제가 발생하면 GitHub Issues에 보고해주세요.
|
||||||
494
pbs-restore.sh
Normal file
494
pbs-restore.sh
Normal file
@ -0,0 +1,494 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Proxmox VE - PBS 백업 복구 스크립트
|
||||||
|
# PBS에서 VM/Container 백업을 쉽게 복구
|
||||||
|
|
||||||
|
# 색상 정의
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
CYAN='\033[0;36m'
|
||||||
|
MAGENTA='\033[0;35m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 로그 함수
|
||||||
|
log_info() { echo -e "${BLUE}ℹ${NC} $1"; }
|
||||||
|
log_success() { echo -e "${GREEN}✓${NC} $1"; }
|
||||||
|
log_warning() { echo -e "${YELLOW}⚠${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}✗${NC} $1"; }
|
||||||
|
log_step() { echo -e "${CYAN}➜${NC} $1"; }
|
||||||
|
|
||||||
|
# 배너 출력
|
||||||
|
print_banner() {
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " PBS 백업 복구 스크립트"
|
||||||
|
echo " Proxmox Backup Server Restore Tool"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Root 권한 확인
|
||||||
|
check_root() {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
log_error "이 스크립트는 root 권한이 필요합니다."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Proxmox VE 환경 확인
|
||||||
|
check_proxmox() {
|
||||||
|
if ! command -v qmrestore &> /dev/null && ! command -v pct &> /dev/null; then
|
||||||
|
log_error "Proxmox VE가 설치되어 있지 않습니다."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_success "Proxmox VE 환경 확인 완료"
|
||||||
|
}
|
||||||
|
|
||||||
|
# PBS 스토리지 목록 가져오기
|
||||||
|
list_pbs_storages() {
|
||||||
|
log_step "사용 가능한 PBS 스토리지 목록:"
|
||||||
|
echo ""
|
||||||
|
pvesm status --type pbs 2>/dev/null | tail -n +2 | awk '{print " • " $1}'
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# PBS 스토리지에서 백업 목록 가져오기
|
||||||
|
list_backups() {
|
||||||
|
local storage="$1"
|
||||||
|
log_step "PBS 스토리지 '${storage}'의 백업 목록을 가져오는 중..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 백업 목록 가져오기
|
||||||
|
local backups=$(pvesm list "$storage" 2>/dev/null | grep -E '\.vma|\.tar' || true)
|
||||||
|
|
||||||
|
if [[ -z "$backups" ]]; then
|
||||||
|
log_warning "백업을 찾을 수 없습니다."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 백업 목록 파싱 및 출력
|
||||||
|
echo "$backups" | while IFS= read -r line; do
|
||||||
|
local volid=$(echo "$line" | awk '{print $1}')
|
||||||
|
local type=$(echo "$line" | awk '{print $2}')
|
||||||
|
local size=$(echo "$line" | awk '{print $3}')
|
||||||
|
|
||||||
|
# VMID 추출
|
||||||
|
local vmid=$(echo "$volid" | grep -oP 'vm-\K[0-9]+' || echo "N/A")
|
||||||
|
if [[ "$vmid" == "N/A" ]]; then
|
||||||
|
vmid=$(echo "$volid" | grep -oP 'ct-\K[0-9]+' || echo "N/A")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 날짜 추출 시도
|
||||||
|
local date=$(echo "$volid" | grep -oP '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z' || echo "")
|
||||||
|
|
||||||
|
echo -e "${CYAN}VMID:${NC} $vmid ${MAGENTA}Type:${NC} $type ${YELLOW}Size:${NC} $size"
|
||||||
|
echo " Volume ID: $volid"
|
||||||
|
if [[ -n "$date" ]]; then
|
||||||
|
echo " Date: $date"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 특정 VMID의 백업 목록 가져오기
|
||||||
|
list_backups_by_vmid() {
|
||||||
|
local storage="$1"
|
||||||
|
local vmid="$2"
|
||||||
|
|
||||||
|
log_step "VMID ${vmid}의 백업 목록을 검색 중..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
local backups=$(pvesm list "$storage" 2>/dev/null | grep -E "vm-${vmid}-|ct-${vmid}-" || true)
|
||||||
|
|
||||||
|
if [[ -z "$backups" ]]; then
|
||||||
|
log_warning "VMID ${vmid}의 백업을 찾을 수 없습니다."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local count=0
|
||||||
|
declare -g -A BACKUP_LIST
|
||||||
|
|
||||||
|
echo "$backups" | while IFS= read -r line; do
|
||||||
|
((count++))
|
||||||
|
local volid=$(echo "$line" | awk '{print $1}')
|
||||||
|
local type=$(echo "$line" | awk '{print $2}')
|
||||||
|
local size=$(echo "$line" | awk '{print $3}')
|
||||||
|
local date=$(echo "$volid" | grep -oP '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z' || echo "Unknown")
|
||||||
|
|
||||||
|
BACKUP_LIST[$count]="$volid"
|
||||||
|
|
||||||
|
echo -e "${GREEN}[$count]${NC} ${CYAN}Date:${NC} $date ${MAGENTA}Type:${NC} $type ${YELLOW}Size:${NC} $size"
|
||||||
|
echo " Volume ID: $volid"
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 백업 검색 (대화형)
|
||||||
|
search_backups_interactive() {
|
||||||
|
list_pbs_storages
|
||||||
|
|
||||||
|
read -p "PBS 스토리지 이름을 입력하세요: " PBS_STORAGE
|
||||||
|
|
||||||
|
if ! pvesm status --storage "$PBS_STORAGE" &> /dev/null; then
|
||||||
|
log_error "스토리지 '${PBS_STORAGE}'를 찾을 수 없습니다."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
read -p "복구할 VMID를 입력하세요 (모두 보려면 Enter): " SEARCH_VMID
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
if [[ -n "$SEARCH_VMID" ]]; then
|
||||||
|
list_backups_by_vmid "$PBS_STORAGE" "$SEARCH_VMID"
|
||||||
|
else
|
||||||
|
list_backups "$PBS_STORAGE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 백업 복구 (VM)
|
||||||
|
restore_vm() {
|
||||||
|
local volid="$1"
|
||||||
|
local target_vmid="$2"
|
||||||
|
local storage="$3"
|
||||||
|
local options="$4"
|
||||||
|
|
||||||
|
log_step "VM 백업 복구 시작..."
|
||||||
|
log_info "Volume ID: $volid"
|
||||||
|
log_info "Target VMID: $target_vmid"
|
||||||
|
log_info "Storage: $storage"
|
||||||
|
|
||||||
|
# 기본 복구 명령어
|
||||||
|
local cmd="qmrestore '$volid' $target_vmid"
|
||||||
|
|
||||||
|
# 스토리지 지정 (선택사항)
|
||||||
|
if [[ -n "$storage" ]]; then
|
||||||
|
cmd+=" --storage $storage"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 추가 옵션
|
||||||
|
if [[ -n "$options" ]]; then
|
||||||
|
cmd+=" $options"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "실행 명령어: $cmd"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 확인
|
||||||
|
read -p "복구를 진행하시겠습니까? (y/N): " confirm
|
||||||
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||||
|
log_warning "복구가 취소되었습니다."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 복구 실행
|
||||||
|
echo ""
|
||||||
|
log_step "복구 진행 중..."
|
||||||
|
if eval "$cmd"; then
|
||||||
|
log_success "VM 복구가 완료되었습니다!"
|
||||||
|
log_info "VMID: $target_vmid"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_error "VM 복구에 실패했습니다."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 백업 복구 (Container)
|
||||||
|
restore_container() {
|
||||||
|
local volid="$1"
|
||||||
|
local target_vmid="$2"
|
||||||
|
local storage="$3"
|
||||||
|
local options="$4"
|
||||||
|
|
||||||
|
log_step "Container 백업 복구 시작..."
|
||||||
|
log_info "Volume ID: $volid"
|
||||||
|
log_info "Target VMID: $target_vmid"
|
||||||
|
log_info "Storage: $storage"
|
||||||
|
|
||||||
|
# 기본 복구 명령어
|
||||||
|
local cmd="pct restore $target_vmid '$volid'"
|
||||||
|
|
||||||
|
# 스토리지 지정 (선택사항)
|
||||||
|
if [[ -n "$storage" ]]; then
|
||||||
|
cmd+=" --storage $storage"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 추가 옵션
|
||||||
|
if [[ -n "$options" ]]; then
|
||||||
|
cmd+=" $options"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "실행 명령어: $cmd"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 확인
|
||||||
|
read -p "복구를 진행하시겠습니까? (y/N): " confirm
|
||||||
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||||
|
log_warning "복구가 취소되었습니다."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 복구 실행
|
||||||
|
echo ""
|
||||||
|
log_step "복구 진행 중..."
|
||||||
|
if eval "$cmd"; then
|
||||||
|
log_success "Container 복구가 완료되었습니다!"
|
||||||
|
log_info "VMID: $target_vmid"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
log_error "Container 복구에 실패했습니다."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# VMID 사용 가능 여부 확인
|
||||||
|
check_vmid_available() {
|
||||||
|
local vmid="$1"
|
||||||
|
|
||||||
|
if qm status "$vmid" &> /dev/null || pct status "$vmid" &> /dev/null; then
|
||||||
|
log_error "VMID ${vmid}는 이미 사용 중입니다."
|
||||||
|
log_warning "다른 VMID를 사용하거나 기존 VM/CT를 삭제하세요."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 스토리지 목록 출력
|
||||||
|
list_storages() {
|
||||||
|
log_step "사용 가능한 스토리지 목록:"
|
||||||
|
echo ""
|
||||||
|
pvesm status | tail -n +2 | awk '{print " • " $1 " (" $2 ")"}'
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 대화형 모드
|
||||||
|
interactive_mode() {
|
||||||
|
echo ""
|
||||||
|
log_info "PBS 백업 복구 - 대화형 모드"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# PBS 스토리지 선택
|
||||||
|
list_pbs_storages
|
||||||
|
read -p "PBS 스토리지 이름: " PBS_STORAGE
|
||||||
|
|
||||||
|
if ! pvesm status --storage "$PBS_STORAGE" &> /dev/null; then
|
||||||
|
log_error "스토리지 '${PBS_STORAGE}'를 찾을 수 없습니다."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# VMID 입력
|
||||||
|
echo ""
|
||||||
|
read -p "복구할 원본 VMID: " SOURCE_VMID
|
||||||
|
|
||||||
|
# 백업 목록 표시
|
||||||
|
echo ""
|
||||||
|
if ! list_backups_by_vmid "$PBS_STORAGE" "$SOURCE_VMID"; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 백업 선택
|
||||||
|
read -p "복구할 백업 번호를 선택하세요: " backup_num
|
||||||
|
|
||||||
|
# 백업 목록 다시 생성 (서브셸 문제 해결)
|
||||||
|
local count=0
|
||||||
|
declare -A BACKUP_LIST_LOCAL
|
||||||
|
while IFS= read -r line; do
|
||||||
|
((count++))
|
||||||
|
local volid=$(echo "$line" | awk '{print $1}')
|
||||||
|
BACKUP_LIST_LOCAL[$count]="$volid"
|
||||||
|
done < <(pvesm list "$PBS_STORAGE" 2>/dev/null | grep -E "vm-${SOURCE_VMID}-|ct-${SOURCE_VMID}-")
|
||||||
|
|
||||||
|
SELECTED_VOLID="${BACKUP_LIST_LOCAL[$backup_num]}"
|
||||||
|
|
||||||
|
if [[ -z "$SELECTED_VOLID" ]]; then
|
||||||
|
log_error "잘못된 선택입니다."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 타겟 VMID 입력
|
||||||
|
echo ""
|
||||||
|
read -p "복구할 타겟 VMID (기본값: ${SOURCE_VMID}): " TARGET_VMID
|
||||||
|
TARGET_VMID=${TARGET_VMID:-$SOURCE_VMID}
|
||||||
|
|
||||||
|
# VMID 사용 가능 여부 확인
|
||||||
|
if ! check_vmid_available "$TARGET_VMID"; then
|
||||||
|
read -p "새로운 VMID를 입력하세요: " TARGET_VMID
|
||||||
|
if ! check_vmid_available "$TARGET_VMID"; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 스토리지 선택
|
||||||
|
echo ""
|
||||||
|
list_storages
|
||||||
|
read -p "복구할 스토리지 (Enter로 원본 스토리지 사용): " TARGET_STORAGE
|
||||||
|
|
||||||
|
# VM 타입 판단
|
||||||
|
echo ""
|
||||||
|
if [[ "$SELECTED_VOLID" =~ "vm-" ]]; then
|
||||||
|
log_info "VM 백업으로 감지되었습니다."
|
||||||
|
BACKUP_TYPE="vm"
|
||||||
|
elif [[ "$SELECTED_VOLID" =~ "ct-" ]]; then
|
||||||
|
log_info "Container 백업으로 감지되었습니다."
|
||||||
|
BACKUP_TYPE="ct"
|
||||||
|
else
|
||||||
|
read -p "백업 타입 (vm/ct): " BACKUP_TYPE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 추가 옵션
|
||||||
|
echo ""
|
||||||
|
log_info "추가 옵션 (선택사항)"
|
||||||
|
read -p "추가 옵션 (예: --force): " EXTRA_OPTIONS
|
||||||
|
|
||||||
|
# 복구 실행
|
||||||
|
echo ""
|
||||||
|
if [[ "$BACKUP_TYPE" == "vm" ]]; then
|
||||||
|
restore_vm "$SELECTED_VOLID" "$TARGET_VMID" "$TARGET_STORAGE" "$EXTRA_OPTIONS"
|
||||||
|
else
|
||||||
|
restore_container "$SELECTED_VOLID" "$TARGET_VMID" "$TARGET_STORAGE" "$EXTRA_OPTIONS"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 사용법
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
사용법: $0 [옵션]
|
||||||
|
|
||||||
|
대화형 모드 (권장):
|
||||||
|
$0
|
||||||
|
|
||||||
|
리스트 모드:
|
||||||
|
$0 -l -s PBS_STORAGE [-v VMID]
|
||||||
|
|
||||||
|
복구 모드:
|
||||||
|
$0 -r -V VOLID -t TARGET_VMID [-S STORAGE] [-T TYPE]
|
||||||
|
|
||||||
|
옵션:
|
||||||
|
-l 백업 목록 보기
|
||||||
|
-r 백업 복구
|
||||||
|
-s STORAGE PBS 스토리지 이름
|
||||||
|
-v VMID 검색할 VMID
|
||||||
|
-V VOLID 복구할 Volume ID
|
||||||
|
-t VMID 타겟 VMID
|
||||||
|
-S STORAGE 복구할 스토리지
|
||||||
|
-T TYPE 백업 타입 (vm 또는 ct)
|
||||||
|
-o OPTIONS 추가 옵션
|
||||||
|
-h 도움말 표시
|
||||||
|
|
||||||
|
예시:
|
||||||
|
# 대화형 모드
|
||||||
|
$0
|
||||||
|
|
||||||
|
# PBS 스토리지의 모든 백업 보기
|
||||||
|
$0 -l -s pbs-backup
|
||||||
|
|
||||||
|
# 특정 VMID의 백업 보기
|
||||||
|
$0 -l -s pbs-backup -v 100
|
||||||
|
|
||||||
|
# VM 백업 복구
|
||||||
|
$0 -r -V "pbs-backup:backup/vm-100-2025_01_28-10_00_00.vma.zst" \\
|
||||||
|
-t 100 -T vm
|
||||||
|
|
||||||
|
# Container 복구 (다른 VMID로)
|
||||||
|
$0 -r -V "pbs-backup:backup/ct-200-2025_01_28-10_00_00.tar.zst" \\
|
||||||
|
-t 201 -S local-lvm -T ct
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# 메인 함수
|
||||||
|
main() {
|
||||||
|
print_banner
|
||||||
|
check_root
|
||||||
|
check_proxmox
|
||||||
|
|
||||||
|
# 옵션 없으면 대화형 모드
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
interactive_mode
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local MODE=""
|
||||||
|
local PBS_STORAGE=""
|
||||||
|
local VMID=""
|
||||||
|
local VOLID=""
|
||||||
|
local TARGET_VMID=""
|
||||||
|
local TARGET_STORAGE=""
|
||||||
|
local BACKUP_TYPE=""
|
||||||
|
local EXTRA_OPTIONS=""
|
||||||
|
|
||||||
|
# 옵션 파싱
|
||||||
|
while getopts "lrs:v:V:t:S:T:o:h" opt; do
|
||||||
|
case $opt in
|
||||||
|
l) MODE="list" ;;
|
||||||
|
r) MODE="restore" ;;
|
||||||
|
s) PBS_STORAGE="$OPTARG" ;;
|
||||||
|
v) VMID="$OPTARG" ;;
|
||||||
|
V) VOLID="$OPTARG" ;;
|
||||||
|
t) TARGET_VMID="$OPTARG" ;;
|
||||||
|
S) TARGET_STORAGE="$OPTARG" ;;
|
||||||
|
T) BACKUP_TYPE="$OPTARG" ;;
|
||||||
|
o) EXTRA_OPTIONS="$OPTARG" ;;
|
||||||
|
h) usage ;;
|
||||||
|
*) usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# 모드별 실행
|
||||||
|
case "$MODE" in
|
||||||
|
list)
|
||||||
|
if [[ -z "$PBS_STORAGE" ]]; then
|
||||||
|
log_error "PBS 스토리지를 지정하세요 (-s 옵션)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$VMID" ]]; then
|
||||||
|
list_backups_by_vmid "$PBS_STORAGE" "$VMID"
|
||||||
|
else
|
||||||
|
list_backups "$PBS_STORAGE"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
restore)
|
||||||
|
if [[ -z "$VOLID" ]] || [[ -z "$TARGET_VMID" ]]; then
|
||||||
|
log_error "Volume ID(-V)와 타겟 VMID(-t)를 지정하세요"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! check_vmid_available "$TARGET_VMID"; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 타입 자동 감지
|
||||||
|
if [[ -z "$BACKUP_TYPE" ]]; then
|
||||||
|
if [[ "$VOLID" =~ "vm-" ]]; then
|
||||||
|
BACKUP_TYPE="vm"
|
||||||
|
elif [[ "$VOLID" =~ "ct-" ]]; then
|
||||||
|
BACKUP_TYPE="ct"
|
||||||
|
else
|
||||||
|
log_error "백업 타입을 지정하세요 (-T vm 또는 -T ct)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$BACKUP_TYPE" == "vm" ]]; then
|
||||||
|
restore_vm "$VOLID" "$TARGET_VMID" "$TARGET_STORAGE" "$EXTRA_OPTIONS"
|
||||||
|
else
|
||||||
|
restore_container "$VOLID" "$TARGET_VMID" "$TARGET_STORAGE" "$EXTRA_OPTIONS"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# 스크립트 실행
|
||||||
|
main "$@"
|
||||||
Loading…
Reference in New Issue
Block a user