#!/bin/bash DB="" # 실제 데이터베이스 이름으로 변경 USER="postgres" # 실제 PostgreSQL 사용자명으로 변경 SCHEMA="public" # 스키마 이름 TABLE="" # 생성할 테이블 이름 SRID_ORI=5186 # 원본 좌표계 SRID_NEW=0 # 변환 좌표계 (0이면 좌표변환 안함) CHARSET="EUC-KR" # 문자 인코딩 SHP_DIR="./" # shp 파일들이 있는 디렉토리 경로 MAX_JOBS=8 # 병렬 작업 수 (시스템 성능에 따라 조정) # 로그 파일 설정 LOG_DIR="./" # 로그 디렉토리 (필요시 경로 변경) mkdir -p "$LOG_DIR" # 로그 디렉토리가 없으면 생성 LOG_FILE="$LOG_DIR/shp_import_$(date '+%Y%m%d_%H%M%S').log" # 로그 함수 정의 logger() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } # 시작 시간 기록 START_TIME=$(date '+%Y-%m-%d %H:%M:%S') START_TIMESTAMP=$(date +%s) # SHP 디렉토리 및 파일 존재 확인 if [ ! -d "$SHP_DIR" ]; then logger "❌ 오류: SHP 디렉토리가 존재하지 않습니다: $SHP_DIR" exit 1 fi SHP_COUNT=$(find "$SHP_DIR" -name "*.shp" | wc -l) if [ $SHP_COUNT -eq 0 ]; then logger "❌ 오류: SHP 파일이 없습니다: $SHP_DIR" exit 1 fi logger "📁 발견된 SHP 파일 수: $SHP_COUNT개" # PostgreSQL 연결 테스트 if ! psql -U "$USER" -d "$DB" -c "SELECT 1;" >/dev/null 2>&1; then logger "❌ 오류: PostgreSQL 연결 실패. 데이터베이스 연결을 확인해주세요." exit 1 fi logger "✅ PostgreSQL 연결 성공" # 좌표계 설정 확인 및 로깅 if [ "$SRID_NEW" -ne 0 ]; then logger "🗺️ 좌표변환 모드: $SRID_ORI → $SRID_NEW" else logger "🗺️ 원본좌표계 사용: $SRID_ORI" fi logger "==================================" logger "🚀 Import 시작: $START_TIME" logger "==================================" # 테이블 존재 여부 확인 logger "🔍 테이블 존재 여부 확인 중: $SCHEMA.$TABLE" TABLE_EXISTS=$(psql -U "$USER" -d "$DB" -t -c "SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = '$SCHEMA' AND tablename = '$TABLE');" 2>/dev/null | tail -1 | tr -d ' \n\r') if [[ "$TABLE_EXISTS" == *"true"* ]] || [[ "$TABLE_EXISTS" == "true" ]]; then logger "📋 테이블 $SCHEMA.$TABLE이 이미 존재합니다. Append 모드로 진행합니다." FIRST="" else logger "📋 테이블 $SCHEMA.$TABLE이 존재하지 않습니다. 새로 생성합니다." # 1. 테이블 먼저 생성 (첫 번째 .shp 기준, 인덱스 없이) FIRST=$(find "$SHP_DIR" -name "*.shp" | head -n 1) logger "Creating table $SCHEMA.$TABLE using $FIRST (without index)" # 좌표변환 여부에 따라 shp2pgsql 명령어 결정 if [ "$SRID_NEW" -ne 0 ]; then OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW "$FIRST" $SCHEMA.$TABLE | psql -U "$USER" -d "$DB" 2>&1) else OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI "$FIRST" $SCHEMA.$TABLE | psql -U "$USER" -d "$DB" 2>&1) fi EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then logger "✅ Table creation completed successfully" else logger "❌ Table creation failed" echo "$OUTPUT" >> "$LOG_FILE" exit 1 fi fi # 2. 병렬로 나머지 파일 append (shp2pgsql -a) function import_append() { SHP="$1" BASENAME=$(basename "$SHP") # 테이블이 새로 생성된 경우: 첫 번째 파일은 건너뛰기 if [[ -n "$FIRST" ]] && [[ "$SHP" == "$FIRST" ]]; then logger "⏭️ Skipping $BASENAME (already processed during table creation)" return fi logger "Appending $BASENAME" # 좌표변환 여부에 따라 shp2pgsql 명령어 결정 if [ "$SRID_NEW" -ne 0 ]; then OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW -a "$SHP" $SCHEMA.$TABLE | psql -U "$USER" -d "$DB" 2>&1) else OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI -a "$SHP" $SCHEMA.$TABLE | psql -U "$USER" -d "$DB" 2>&1) fi EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then logger "✅ $BASENAME appended successfully" else logger "❌ Failed to append $BASENAME" echo "$OUTPUT" >> "$LOG_FILE" fi } # job control 함수 function wait_for_jobs() { while (( $(jobs -rp | wc -l) >= MAX_JOBS )); do sleep 1 done } # 병렬 실행 for shp in "$SHP_DIR"/*.shp; do wait_for_jobs import_append "$shp" & done wait # 데이터 입력 완료 시간 기록 DATA_END_TIME=$(date '+%Y-%m-%d %H:%M:%S') DATA_END_TIMESTAMP=$(date +%s) DATA_DURATION=$((DATA_END_TIMESTAMP - START_TIMESTAMP)) # 데이터 입력 시간을 시:분:초 형식으로 변환 DATA_HOURS=$((DATA_DURATION / 3600)) DATA_MINUTES=$(((DATA_DURATION % 3600) / 60)) DATA_SECONDS=$((DATA_DURATION % 60)) # 1보다 작으면 0으로 표시 if [ $DATA_HOURS -lt 1 ]; then DATA_HOURS=0; fi if [ $DATA_MINUTES -lt 1 ]; then DATA_MINUTES=0; fi logger "==================================" logger "📊 데이터 입력 완료: $DATA_END_TIME" logger "📊 데이터 입력 소요시간: ${DATA_HOURS}시간 ${DATA_MINUTES}분 ${DATA_SECONDS}초" logger "==================================" # 3. (선택) 인덱스 재생성 (권장: 한 번에 생성) INDEX_START_TIME=$(date '+%Y-%m-%d %H:%M:%S') INDEX_START_TIMESTAMP=$(date +%s) logger "🔍 공간 인덱스 생성 시작: $INDEX_START_TIME" # 공간 인덱스 생성 (PostGIS 확장이 활성화되어 있어야 함) psql -U "$USER" -d "$DB" -c "CREATE INDEX IF NOT EXISTS ${TABLE}_geom_idx ON $SCHEMA.$TABLE USING GIST (geom);" >/dev/null 2>&1 INDEX_EXIT_CODE=$? if [ $INDEX_EXIT_CODE -eq 0 ]; then logger "✅ Spatial index created successfully" else logger "❌ Failed to create spatial index" logger "⚠️ PostGIS 확장이 활성화되어 있는지 확인하세요: CREATE EXTENSION IF NOT EXISTS postgis;" fi # 인덱스 재생성 완료 시간 기록 INDEX_END_TIME=$(date '+%Y-%m-%d %H:%M:%S') INDEX_END_TIMESTAMP=$(date +%s) INDEX_DURATION=$((INDEX_END_TIMESTAMP - INDEX_START_TIMESTAMP)) # 인덱스 재생성 시간을 시:분:초 형식으로 변환 INDEX_HOURS=$((INDEX_DURATION / 3600)) INDEX_MINUTES=$(((INDEX_DURATION % 3600) / 60)) INDEX_SECONDS=$((INDEX_DURATION % 60)) # 1보다 작으면 0으로 표시 if [ $INDEX_HOURS -lt 1 ]; then INDEX_HOURS=0; fi if [ $INDEX_MINUTES -lt 1 ]; then INDEX_MINUTES=0; fi # 전체 종료 시간 및 소요 시간 계산 END_TIME=$(date '+%Y-%m-%d %H:%M:%S') END_TIMESTAMP=$(date +%s) TOTAL_DURATION=$((END_TIMESTAMP - START_TIMESTAMP)) # 전체 시간을 시:분:초 형식으로 변환 TOTAL_HOURS=$((TOTAL_DURATION / 3600)) TOTAL_MINUTES=$(((TOTAL_DURATION % 3600) / 60)) TOTAL_SECONDS=$((TOTAL_DURATION % 60)) # 1보다 작으면 0으로 표시 if [ $TOTAL_HOURS -lt 1 ]; then TOTAL_HOURS=0; fi if [ $TOTAL_MINUTES -lt 1 ]; then TOTAL_MINUTES=0; fi logger "==================================" logger "✅ 전체 작업 완료: $END_TIME" logger "📊 전체 소요시간: ${TOTAL_HOURS}시간 ${TOTAL_MINUTES}분 ${TOTAL_SECONDS}초" logger "📋 상세 요약:" logger " - 전체 시작시간: $START_TIME" logger " - 데이터 입력 완료: $DATA_END_TIME (소요: ${DATA_HOURS}시간 ${DATA_MINUTES}분 ${DATA_SECONDS}초)" logger " - 공간 인덱스 생성 시작: $INDEX_START_TIME" logger " - 공간 인덱스 생성 완료: $INDEX_END_TIME (소요: ${INDEX_HOURS}시간 ${INDEX_MINUTES}분 ${INDEX_SECONDS}초)" logger " - 전체 종료시간: $END_TIME" logger " - 대상테이블: $SCHEMA.$TABLE" if [ "$SRID_NEW" -ne 0 ]; then logger " - 좌표계: $SRID_ORI → $SRID_NEW (변환됨)" else logger " - 좌표계: $SRID_ORI (원본)" fi logger "📊 데이터 처리 완료" logger "==================================" logger "로그 파일: $LOG_FILE"