Última atividade 1756818083

Revisão dbddf1e815f1d87a8f5e16ec2f157bc5da1dfdf9

shp2pgsql.sh Bruto
1#!/bin/bash
2
3DB="" # 실제 데이터베이스 이름으로 변경
4USER="postgres" # 실제 PostgreSQL 사용자명으로 변경
5SCHEMA="public" # 스키마 이름
6TABLE="" # 생성할 테이블 이름
7
8# 대소문자 구분 문제 해결을 위해 소문자로 변환
9SCHEMA_LOWER=$(echo "$SCHEMA" | tr '[:upper:]' '[:lower:]')
10TABLE_LOWER=$(echo "$TABLE" | tr '[:upper:]' '[:lower:]')
11
12SRID_ORI=5186 # 원본 좌표계
13SRID_NEW=0 # 변환 좌표계 (0이면 좌표변환 안함)
14CHARSET="EUC-KR" # 문자 인코딩
15
16SHP_DIR="./" # shp 파일들이 있는 디렉토리 경로
17MAX_JOBS=8 # 병렬 작업 수 (시스템 성능에 따라 조정)
18
19# 로그 파일 설정
20LOG_DIR="./" # 로그 디렉토리 (필요시 경로 변경)
21mkdir -p "$LOG_DIR" # 로그 디렉토리가 없으면 생성
22LOG_FILE="$LOG_DIR/shp_import_$(date '+%Y%m%d_%H%M%S').log"
23
24# 로그 함수 정의
25logger() {
26 echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
27}
28
29# 시작 시간 기록
30START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
31START_TIMESTAMP=$(date +%s)
32
33
34# SHP 디렉토리 및 파일 존재 확인
35if [ ! -d "$SHP_DIR" ]; then
36 logger "❌ 오류: SHP 디렉토리가 존재하지 않습니다: $SHP_DIR"
37 exit 1
38fi
39
40SHP_COUNT=$(find "$SHP_DIR" -name "*.shp" | wc -l)
41if [ $SHP_COUNT -eq 0 ]; then
42 logger "❌ 오류: SHP 파일이 없습니다: $SHP_DIR"
43 exit 1
44fi
45logger "📁 발견된 SHP 파일 수: $SHP_COUNT개"
46
47# 필수 변수 검증
48if [ -z "$DB" ]; then
49 logger "❌ 오류: DB 변수가 설정되지 않았습니다. 스크립트 상단에서 DB 변수를 설정해주세요."
50 exit 1
51fi
52
53if [ -z "$TABLE" ]; then
54 logger "❌ 오류: TABLE 변수가 설정되지 않았습니다. 스크립트 상단에서 TABLE 변수를 설정해주세요."
55 exit 1
56fi
57
58logger "📋 설정된 변수:"
59logger " - 데이터베이스: $DB"
60logger " - 사용자: $USER"
61logger " - 스키마: $SCHEMA"
62logger " - 테이블: $TABLE"
63
64# PostgreSQL 연결 테스트
65if ! psql -U "$USER" -d "$DB" -c "SELECT 1;" >/dev/null 2>&1; then
66 logger "❌ 오류: PostgreSQL 연결 실패. 데이터베이스 연결을 확인해주세요."
67 exit 1
68fi
69logger "✅ PostgreSQL 연결 성공"
70
71# 좌표계 설정 확인 및 로깅
72if [ "$SRID_NEW" -ne 0 ]; then
73 logger "🗺️ 좌표변환 모드: $SRID_ORI$SRID_NEW"
74else
75 logger "🗺️ 원본좌표계 사용: $SRID_ORI"
76fi
77
78logger "=================================="
79logger "🚀 Import 시작: $START_TIME"
80logger "=================================="
81
82# 테이블 존재 여부 확인
83logger "🔍 테이블 존재 여부 확인 중: $SCHEMA_LOWER.$TABLE_LOWER"
84
85# 테이블 존재 여부를 더 안정적으로 확인 (소문자로 비교)
86TABLE_EXISTS=$(psql -U "$USER" -d "$DB" -t -c "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = '$SCHEMA_LOWER' AND table_name = '$TABLE_LOWER');" 2>/dev/null | xargs)
87
88logger "🔍 테이블 존재 확인 결과: '$TABLE_EXISTS'"
89
90if [ "$TABLE_EXISTS" = "t" ]; then
91 logger "📋 테이블 $SCHEMA_LOWER.$TABLE_LOWER이 이미 존재합니다. Append 모드로 진행합니다."
92 FIRST=""
93else
94 logger "📋 테이블 $SCHEMA_LOWER.$TABLE_LOWER이 존재하지 않습니다. 새로 생성합니다."
95 # 1. 테이블 먼저 생성 (첫 번째 .shp 기준, 인덱스 없이)
96 FIRST=$(find "$SHP_DIR" -name "*.shp" | head -n 1)
97 logger "Creating table $SCHEMA_LOWER.$TABLE_LOWER using $FIRST (without index)"
98
99 # 좌표변환 여부에 따라 shp2pgsql 명령어 결정
100 if [ "$SRID_NEW" -ne 0 ]; then
101 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW "$FIRST" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
102 else
103 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI "$FIRST" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
104 fi
105 EXIT_CODE=$?
106
107 if [ $EXIT_CODE -eq 0 ]; then
108 logger "✅ Table creation completed successfully"
109 else
110 logger "❌ Table creation failed"
111 echo "$OUTPUT" >> "$LOG_FILE"
112 exit 1
113 fi
114fi
115
116# 2. 병렬로 나머지 파일 append (shp2pgsql -a)
117function import_append() {
118 SHP="$1"
119 BASENAME=$(basename "$SHP")
120
121 logger "Appending $BASENAME"
122
123 # 좌표변환 여부에 따라 shp2pgsql 명령어 결정
124 if [ "$SRID_NEW" -ne 0 ]; then
125 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
126 else
127 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
128 fi
129 EXIT_CODE=$?
130
131 if [ $EXIT_CODE -eq 0 ]; then
132 logger "$BASENAME appended successfully"
133 else
134 logger "❌ Failed to append $BASENAME"
135 echo "$OUTPUT" >> "$LOG_FILE"
136 fi
137}
138
139# job control 함수
140function wait_for_jobs() {
141 while (( $(jobs -rp | wc -l) >= MAX_JOBS )); do
142 sleep 1
143 done
144}
145
146# 병렬 실행 (테이블이 새로 생성된 경우에만)
147if [ -n "$FIRST" ]; then
148 logger "🔄 나머지 파일들을 병렬로 처리합니다..."
149 for shp in "$SHP_DIR"/*.shp; do
150 # 첫 번째 파일은 건너뛰기
151 if [[ "$shp" == "$FIRST" ]]; then
152 logger "⏭️ Skipping $(basename "$shp") (already processed during table creation)"
153 continue
154 fi
155
156 wait_for_jobs
157 import_append "$shp" &
158 done
159 wait
160else
161 logger "🔄 모든 파일을 병렬로 처리합니다..."
162 for shp in "$SHP_DIR"/*.shp; do
163 wait_for_jobs
164 import_append "$shp" &
165 done
166 wait
167fi
168
169# 데이터 입력 완료 시간 기록
170DATA_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
171DATA_END_TIMESTAMP=$(date +%s)
172DATA_DURATION=$((DATA_END_TIMESTAMP - START_TIMESTAMP))
173
174# 데이터 입력 시간을 시:분:초 형식으로 변환
175DATA_HOURS=$((DATA_DURATION / 3600))
176DATA_MINUTES=$(((DATA_DURATION % 3600) / 60))
177DATA_SECONDS=$((DATA_DURATION % 60))
178
179# 1보다 작으면 0으로 표시
180if [ $DATA_HOURS -lt 1 ]; then DATA_HOURS=0; fi
181if [ $DATA_MINUTES -lt 1 ]; then DATA_MINUTES=0; fi
182
183logger "=================================="
184logger "📊 데이터 입력 완료: $DATA_END_TIME"
185logger "📊 데이터 입력 소요시간: ${DATA_HOURS}시간 ${DATA_MINUTES}${DATA_SECONDS}"
186logger "=================================="
187
188# 3. (선택) 인덱스 재생성 (권장: 한 번에 생성)
189INDEX_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
190INDEX_START_TIMESTAMP=$(date +%s)
191
192logger "🔍 공간 인덱스 생성 시작: $INDEX_START_TIME"
193
194# 공간 인덱스 생성 (PostGIS 확장이 활성화되어 있어야 함)
195psql -U "$USER" -d "$DB" -c "CREATE INDEX IF NOT EXISTS ${TABLE_LOWER}_geom_idx ON $SCHEMA_LOWER.$TABLE_LOWER USING GIST (geom);" >/dev/null 2>&1
196INDEX_EXIT_CODE=$?
197
198if [ $INDEX_EXIT_CODE -eq 0 ]; then
199 logger "✅ Spatial index created successfully"
200else
201 logger "❌ Failed to create spatial index"
202 logger "⚠️ PostGIS 확장이 활성화되어 있는지 확인하세요: CREATE EXTENSION IF NOT EXISTS postgis;"
203fi
204
205# 인덱스 재생성 완료 시간 기록
206INDEX_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
207INDEX_END_TIMESTAMP=$(date +%s)
208INDEX_DURATION=$((INDEX_END_TIMESTAMP - INDEX_START_TIMESTAMP))
209
210# 인덱스 재생성 시간을 시:분:초 형식으로 변환
211INDEX_HOURS=$((INDEX_DURATION / 3600))
212INDEX_MINUTES=$(((INDEX_DURATION % 3600) / 60))
213INDEX_SECONDS=$((INDEX_DURATION % 60))
214
215# 1보다 작으면 0으로 표시
216if [ $INDEX_HOURS -lt 1 ]; then INDEX_HOURS=0; fi
217if [ $INDEX_MINUTES -lt 1 ]; then INDEX_MINUTES=0; fi
218
219# 전체 종료 시간 및 소요 시간 계산
220END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
221END_TIMESTAMP=$(date +%s)
222TOTAL_DURATION=$((END_TIMESTAMP - START_TIMESTAMP))
223
224# 전체 시간을 시:분:초 형식으로 변환
225TOTAL_HOURS=$((TOTAL_DURATION / 3600))
226TOTAL_MINUTES=$(((TOTAL_DURATION % 3600) / 60))
227TOTAL_SECONDS=$((TOTAL_DURATION % 60))
228
229# 1보다 작으면 0으로 표시
230if [ $TOTAL_HOURS -lt 1 ]; then TOTAL_HOURS=0; fi
231if [ $TOTAL_MINUTES -lt 1 ]; then TOTAL_MINUTES=0; fi
232
233logger "=================================="
234logger "✅ 전체 작업 완료: $END_TIME"
235logger "📊 전체 소요시간: ${TOTAL_HOURS}시간 ${TOTAL_MINUTES}${TOTAL_SECONDS}"
236logger "📋 상세 요약:"
237logger " - 전체 시작시간: $START_TIME"
238logger " - 데이터 입력 완료: $DATA_END_TIME (소요: ${DATA_HOURS}시간 ${DATA_MINUTES}${DATA_SECONDS}초)"
239logger " - 공간 인덱스 생성 시작: $INDEX_START_TIME"
240logger " - 공간 인덱스 생성 완료: $INDEX_END_TIME (소요: ${INDEX_HOURS}시간 ${INDEX_MINUTES}${INDEX_SECONDS}초)"
241logger " - 전체 종료시간: $END_TIME"
242logger " - 대상테이블: $SCHEMA_LOWER.$TABLE_LOWER"
243if [ "$SRID_NEW" -ne 0 ]; then
244 logger " - 좌표계: $SRID_ORI$SRID_NEW (변환됨)"
245else
246 logger " - 좌표계: $SRID_ORI (원본)"
247fi
248logger "📊 데이터 처리 완료"
249logger "=================================="
250logger "로그 파일: $LOG_FILE"