테스트 후 생성된 데이터를 쉽게 정리할 수 있도록 문서와 스크립트 추가 추가 파일: - CLEANUP_TEST_DATA.md: 상세한 정리 가이드 * farmq.db 약국 삭제 방법 * gateway.db 사용자 삭제 방법 * Headscale 노드 삭제 방법 * 백업 및 복구 가이드 - cleanup-test-data.sh: 대화형 정리 스크립트 * P0003 이후 약국 자동 삭제 * ID 5 이후 사용자 자동 삭제 * Headscale 노드 선택 삭제 * 백업 생성 옵션 * 안전 확인 프롬프트 변경 파일: - README.md: Headscale 섹션 업데이트 * 자동 등록 스크립트 설명 추가 * 테스트 데이터 정리 가이드 링크 추가 사용 예시: ```bash # 대화형 정리 bash cleanup-test-data.sh # 원격 실행 curl -fsSL https://.../cleanup-test-data.sh | bash ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
258 lines
7.7 KiB
Bash
Executable File
258 lines
7.7 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ================================
|
|
# 테스트 데이터 정리 스크립트
|
|
# ================================
|
|
#
|
|
# 용도: headscale 자동 등록 테스트 후 생성된 데이터 정리
|
|
# - farmq.db: P0003 이후 약국 삭제
|
|
# - gateway.db: ID 5 이후 사용자 삭제
|
|
# - Headscale: 테스트 노드 삭제 (선택)
|
|
#
|
|
|
|
set -e
|
|
|
|
# ================================
|
|
# 색상 정의
|
|
# ================================
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
WHITE='\033[1;37m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# ================================
|
|
# 헤더 출력
|
|
# ================================
|
|
print_header() {
|
|
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${WHITE}$1${NC}"
|
|
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
}
|
|
|
|
# ================================
|
|
# 1. farmq.db 테스트 약국 삭제
|
|
# ================================
|
|
cleanup_farmq_db() {
|
|
print_header "1. farmq.db 테스트 약국 정리"
|
|
|
|
FARMQ_DB="/srv/headscale-tailscale-replacement/farmq-admin/farmq.db"
|
|
|
|
if [ ! -f "$FARMQ_DB" ]; then
|
|
echo -e "${RED}✗ farmq.db를 찾을 수 없습니다: $FARMQ_DB${NC}"
|
|
return 1
|
|
fi
|
|
|
|
echo -e "${BLUE}현재 약국 목록:${NC}"
|
|
python3 << EOF
|
|
import sqlite3
|
|
conn = sqlite3.connect('$FARMQ_DB')
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT pharmacy_code, pharmacy_name, tailscale_ip FROM pharmacies ORDER BY pharmacy_code')
|
|
for row in cursor.fetchall():
|
|
print(f' {row[0]}: {row[1]} - {row[2]}')
|
|
conn.close()
|
|
EOF
|
|
|
|
echo -e "\n${YELLOW}P0003 이후 약국을 삭제하시겠습니까? (y/N)${NC}"
|
|
read -p "> " -r response </dev/tty
|
|
|
|
if [[ "$response" =~ ^[Yy]$ ]]; then
|
|
python3 << EOF
|
|
import sqlite3
|
|
conn = sqlite3.connect('$FARMQ_DB')
|
|
cursor = conn.cursor()
|
|
cursor.execute("DELETE FROM pharmacies WHERE pharmacy_code >= 'P0003' AND pharmacy_code < 'P1000'")
|
|
deleted_count = cursor.rowcount
|
|
conn.commit()
|
|
conn.close()
|
|
print(f'✓ {deleted_count}개 약국 삭제 완료')
|
|
EOF
|
|
|
|
echo -e "\n${GREEN}남은 약국 목록:${NC}"
|
|
python3 << EOF
|
|
import sqlite3
|
|
conn = sqlite3.connect('$FARMQ_DB')
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT pharmacy_code, pharmacy_name, tailscale_ip FROM pharmacies ORDER BY pharmacy_code')
|
|
for row in cursor.fetchall():
|
|
print(f' {row[0]}: {row[1]} - {row[2]}')
|
|
conn.close()
|
|
EOF
|
|
else
|
|
echo -e "${YELLOW}건너뜀${NC}"
|
|
fi
|
|
}
|
|
|
|
# ================================
|
|
# 2. gateway.db 테스트 사용자 삭제
|
|
# ================================
|
|
cleanup_gateway_db() {
|
|
print_header "2. gateway.db 테스트 사용자 정리"
|
|
|
|
GATEWAY_DB="/srv/pharmq-gateway/gateway.db"
|
|
|
|
if [ ! -f "$GATEWAY_DB" ]; then
|
|
echo -e "${RED}✗ gateway.db를 찾을 수 없습니다: $GATEWAY_DB${NC}"
|
|
return 1
|
|
fi
|
|
|
|
echo -e "${BLUE}현재 사용자 목록:${NC}"
|
|
python3 << EOF
|
|
import sqlite3
|
|
conn = sqlite3.connect('$GATEWAY_DB')
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT id, username, name, primary_pharmacy_code FROM users ORDER BY id')
|
|
for row in cursor.fetchall():
|
|
print(f' ID {row[0]}: {row[1]} ({row[2]}) - {row[3]}')
|
|
conn.close()
|
|
EOF
|
|
|
|
echo -e "\n${YELLOW}ID 5 이후 사용자를 삭제하시겠습니까? (y/N)${NC}"
|
|
read -p "> " -r response </dev/tty
|
|
|
|
if [[ "$response" =~ ^[Yy]$ ]]; then
|
|
python3 << EOF
|
|
import sqlite3
|
|
conn = sqlite3.connect('$GATEWAY_DB')
|
|
cursor = conn.cursor()
|
|
cursor.execute('DELETE FROM pharmacy_members WHERE user_id >= 5')
|
|
cursor.execute('DELETE FROM users WHERE id >= 5')
|
|
deleted_count = cursor.rowcount
|
|
conn.commit()
|
|
conn.close()
|
|
print(f'✓ {deleted_count}명 사용자 삭제 완료')
|
|
EOF
|
|
|
|
echo -e "\n${GREEN}남은 사용자 목록:${NC}"
|
|
python3 << EOF
|
|
import sqlite3
|
|
conn = sqlite3.connect('$GATEWAY_DB')
|
|
cursor = conn.cursor()
|
|
cursor.execute('SELECT id, username, name, primary_pharmacy_code FROM users ORDER BY id')
|
|
for row in cursor.fetchall():
|
|
print(f' ID {row[0]}: {row[1]} ({row[2]}) - {row[3]}')
|
|
conn.close()
|
|
EOF
|
|
else
|
|
echo -e "${YELLOW}건너뜀${NC}"
|
|
fi
|
|
}
|
|
|
|
# ================================
|
|
# 3. Headscale 테스트 노드 삭제
|
|
# ================================
|
|
cleanup_headscale_nodes() {
|
|
print_header "3. Headscale 테스트 노드 정리"
|
|
|
|
# Docker 컨테이너 확인
|
|
if ! docker ps | grep -q headscale; then
|
|
echo -e "${RED}✗ Headscale 컨테이너를 찾을 수 없습니다${NC}"
|
|
return 1
|
|
fi
|
|
|
|
echo -e "${BLUE}현재 노드 목록:${NC}"
|
|
docker exec headscale headscale nodes list
|
|
|
|
echo -e "\n${YELLOW}삭제할 노드 ID를 입력하세요 (공백으로 구분, Enter로 건너뛰기):${NC}"
|
|
echo -e "${YELLOW}예: 13 14 15 16${NC}"
|
|
read -p "> " -r node_ids </dev/tty
|
|
|
|
if [ -z "$node_ids" ]; then
|
|
echo -e "${YELLOW}건너뜀${NC}"
|
|
return 0
|
|
fi
|
|
|
|
echo -e "\n${BLUE}노드 삭제 중...${NC}"
|
|
for id in $node_ids; do
|
|
if docker exec headscale headscale nodes delete --identifier "$id" --force 2>/dev/null; then
|
|
echo -e "${GREEN}✓ Node ID $id 삭제 완료${NC}"
|
|
else
|
|
echo -e "${RED}✗ Node ID $id 삭제 실패${NC}"
|
|
fi
|
|
done
|
|
|
|
echo -e "\n${GREEN}남은 노드 목록:${NC}"
|
|
docker exec headscale headscale nodes list
|
|
}
|
|
|
|
# ================================
|
|
# 4. 백업 생성
|
|
# ================================
|
|
create_backup() {
|
|
print_header "백업 생성 (선택)"
|
|
|
|
echo -e "${YELLOW}데이터베이스 백업을 생성하시겠습니까? (y/N)${NC}"
|
|
read -p "> " -r response </dev/tty
|
|
|
|
if [[ "$response" =~ ^[Yy]$ ]]; then
|
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
|
|
# farmq.db 백업
|
|
if [ -f "/srv/headscale-tailscale-replacement/farmq-admin/farmq.db" ]; then
|
|
cp /srv/headscale-tailscale-replacement/farmq-admin/farmq.db \
|
|
/srv/headscale-tailscale-replacement/farmq-admin/farmq.db.backup_$TIMESTAMP
|
|
echo -e "${GREEN}✓ farmq.db 백업 생성: farmq.db.backup_$TIMESTAMP${NC}"
|
|
fi
|
|
|
|
# gateway.db 백업
|
|
if [ -f "/srv/pharmq-gateway/gateway.db" ]; then
|
|
cp /srv/pharmq-gateway/gateway.db \
|
|
/srv/pharmq-gateway/gateway.db.backup_$TIMESTAMP
|
|
echo -e "${GREEN}✓ gateway.db 백업 생성: gateway.db.backup_$TIMESTAMP${NC}"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}백업 건너뜀${NC}"
|
|
fi
|
|
}
|
|
|
|
# ================================
|
|
# 메인 함수
|
|
# ================================
|
|
main() {
|
|
print_header "팜큐(FARMQ) 테스트 데이터 정리"
|
|
|
|
echo -e "${CYAN}이 스크립트는 다음 작업을 수행합니다:${NC}"
|
|
echo -e " 1. farmq.db에서 P0003 이후 약국 삭제"
|
|
echo -e " 2. gateway.db에서 ID 5 이후 사용자 삭제"
|
|
echo -e " 3. Headscale 테스트 노드 삭제 (선택)"
|
|
echo ""
|
|
echo -e "${YELLOW}⚠ 주의: 운영 데이터는 삭제되지 않습니다${NC}"
|
|
echo -e " - 보호되는 약국: P001, P002, P0002"
|
|
echo -e " - 보호되는 사용자: ID 1~4"
|
|
echo ""
|
|
|
|
read -p "계속하시겠습니까? (y/N) " -r response </dev/tty
|
|
if [[ ! "$response" =~ ^[Yy]$ ]]; then
|
|
echo -e "${YELLOW}취소되었습니다${NC}"
|
|
exit 0
|
|
fi
|
|
|
|
# 백업 생성 (선택)
|
|
create_backup
|
|
|
|
echo ""
|
|
|
|
# 1. farmq.db 정리
|
|
cleanup_farmq_db
|
|
|
|
echo ""
|
|
|
|
# 2. gateway.db 정리
|
|
cleanup_gateway_db
|
|
|
|
echo ""
|
|
|
|
# 3. Headscale 노드 정리
|
|
cleanup_headscale_nodes
|
|
|
|
echo ""
|
|
print_header "정리 완료!"
|
|
echo -e "${GREEN}모든 작업이 완료되었습니다.${NC}"
|
|
}
|
|
|
|
# 스크립트 실행
|
|
main "$@"
|