最後活躍 1756818083

修訂 d97342f83660f60c46e2be566b4e62d0c6891a35

shp2pgsql.sh 原始檔案
1#!/bin/bash
2
3DB="yourDb" # 실제 데이터베이스 이름으로 변경
4USER="postgres" # 실제 PostgreSQL 사용자명으로 변경
5SCHEMA="yourSchema" # 스키마 이름
6TABLE="yourTable" # 생성할 테이블 이름
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="UTF-8" # 문자 인코딩
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 FIRST_BASENAME=$(basename "$FIRST")
98
99 # 테이블 생성 시작 시간 기록
100 TABLE_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
101 TABLE_START_TIMESTAMP=$(date +%s)
102
103 logger "🚀 [시작] 테이블 생성 시작: $FIRST_BASENAME - $TABLE_START_TIME"
104
105 # 좌표변환 여부에 따라 shp2pgsql 명령어 결정
106 if [ "$SRID_NEW" -ne 0 ]; then
107 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW "$FIRST" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
108 else
109 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI "$FIRST" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
110 fi
111 EXIT_CODE=$?
112
113 # 테이블 생성 종료 시간 기록
114 TABLE_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
115 TABLE_END_TIMESTAMP=$(date +%s)
116 TABLE_DURATION=$((TABLE_END_TIMESTAMP - TABLE_START_TIMESTAMP))
117
118 # 테이블 생성 소요시간을 시:분:초 형식으로 변환
119 TABLE_HOURS=$((TABLE_DURATION / 3600))
120 TABLE_MINUTES=$(((TABLE_DURATION % 3600) / 60))
121 TABLE_SECONDS=$((TABLE_DURATION % 60))
122
123 # 1보다 작으면 0으로 표시
124 if [ $TABLE_HOURS -lt 1 ]; then TABLE_HOURS=0; fi
125 if [ $TABLE_MINUTES -lt 1 ]; then TABLE_MINUTES=0; fi
126
127 if [ $EXIT_CODE -eq 0 ]; then
128 logger "✅ [완료] 테이블 생성 완료: $TABLE_END_TIME (소요: ${TABLE_HOURS}시간 ${TABLE_MINUTES}${TABLE_SECONDS}초)"
129 else
130 logger "❌ [실패] 테이블 생성 실패: $TABLE_END_TIME (소요: ${TABLE_HOURS}시간 ${TABLE_MINUTES}${TABLE_SECONDS}초)"
131 echo "$OUTPUT" >> "$LOG_FILE"
132 exit 1
133 fi
134fi
135
136# 2. 병렬로 나머지 파일 append (shp2pgsql -a)
137function import_append() {
138 SHP="$1"
139 BASENAME=$(basename "$SHP")
140
141 # 처리 시작 시간 기록
142 FILE_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
143 FILE_START_TIMESTAMP=$(date +%s)
144
145 logger "🚀 [시작] $BASENAME 처리 시작: $FILE_START_TIME"
146
147 # 좌표변환 여부에 따라 shp2pgsql 명령어 결정
148 if [ "$SRID_NEW" -ne 0 ]; then
149 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
150 else
151 OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -U "$USER" -d "$DB" 2>&1)
152 fi
153 EXIT_CODE=$?
154
155 # 처리 종료 시간 기록
156 FILE_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
157 FILE_END_TIMESTAMP=$(date +%s)
158 FILE_DURATION=$((FILE_END_TIMESTAMP - FILE_START_TIMESTAMP))
159
160 # 파일별 소요시간을 시:분:초 형식으로 변환
161 FILE_HOURS=$((FILE_DURATION / 3600))
162 FILE_MINUTES=$(((FILE_DURATION % 3600) / 60))
163 FILE_SECONDS=$((FILE_DURATION % 60))
164
165 # 1보다 작으면 0으로 표시
166 if [ $FILE_HOURS -lt 1 ]; then FILE_HOURS=0; fi
167 if [ $FILE_MINUTES -lt 1 ]; then FILE_MINUTES=0; fi
168
169 if [ $EXIT_CODE -eq 0 ]; then
170 logger "✅ [완료] $BASENAME 처리 완료: $FILE_END_TIME (소요: ${FILE_HOURS}시간 ${FILE_MINUTES}${FILE_SECONDS}초)"
171 else
172 logger "❌ [실패] $BASENAME 처리 실패: $FILE_END_TIME (소요: ${FILE_HOURS}시간 ${FILE_MINUTES}${FILE_SECONDS}초)"
173 echo "$OUTPUT" >> "$LOG_FILE"
174 fi
175}
176
177# job control 함수
178function wait_for_jobs() {
179 while (( $(jobs -rp | wc -l) >= MAX_JOBS )); do
180 sleep 1
181 done
182}
183
184# 병렬 실행 (테이블이 새로 생성된 경우에만)
185if [ -n "$FIRST" ]; then
186 logger "🔄 나머지 파일들을 병렬로 처리합니다..."
187 for shp in "$SHP_DIR"/*.shp; do
188 # 첫 번째 파일은 건너뛰기
189 if [[ "$shp" == "$FIRST" ]]; then
190 logger "⏭️ Skipping $(basename "$shp") (already processed during table creation)"
191 continue
192 fi
193
194 wait_for_jobs
195 import_append "$shp" &
196 done
197 wait
198else
199 logger "🔄 모든 파일을 병렬로 처리합니다..."
200 for shp in "$SHP_DIR"/*.shp; do
201 wait_for_jobs
202 import_append "$shp" &
203 done
204 wait
205fi
206
207# 데이터 입력 완료 시간 기록
208DATA_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
209DATA_END_TIMESTAMP=$(date +%s)
210DATA_DURATION=$((DATA_END_TIMESTAMP - START_TIMESTAMP))
211
212# 데이터 입력 시간을 시:분:초 형식으로 변환
213DATA_HOURS=$((DATA_DURATION / 3600))
214DATA_MINUTES=$(((DATA_DURATION % 3600) / 60))
215DATA_SECONDS=$((DATA_DURATION % 60))
216
217# 1보다 작으면 0으로 표시
218if [ $DATA_HOURS -lt 1 ]; then DATA_HOURS=0; fi
219if [ $DATA_MINUTES -lt 1 ]; then DATA_MINUTES=0; fi
220
221# 3. (선택) 인덱스 재생성 (권장: 한 번에 생성)
222INDEX_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
223INDEX_START_TIMESTAMP=$(date +%s)
224
225logger "🔍 공간 인덱스 생성 시작: $INDEX_START_TIME"
226
227# 공간 인덱스 생성 (PostGIS 확장이 활성화되어 있어야 함)
228psql -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
229INDEX_EXIT_CODE=$?
230
231if [ $INDEX_EXIT_CODE -eq 0 ]; then
232 logger "✅ Spatial index created successfully"
233else
234 logger "❌ Failed to create spatial index"
235 logger "⚠️ PostGIS 확장이 활성화되어 있는지 확인하세요: CREATE EXTENSION IF NOT EXISTS postgis;"
236fi
237
238# 인덱스 재생성 완료 시간 기록
239INDEX_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
240INDEX_END_TIMESTAMP=$(date +%s)
241INDEX_DURATION=$((INDEX_END_TIMESTAMP - INDEX_START_TIMESTAMP))
242
243# 인덱스 재생성 시간을 시:분:초 형식으로 변환
244INDEX_HOURS=$((INDEX_DURATION / 3600))
245INDEX_MINUTES=$(((INDEX_DURATION % 3600) / 60))
246INDEX_SECONDS=$((INDEX_DURATION % 60))
247
248# 1보다 작으면 0으로 표시
249if [ $INDEX_HOURS -lt 1 ]; then INDEX_HOURS=0; fi
250if [ $INDEX_MINUTES -lt 1 ]; then INDEX_MINUTES=0; fi
251
252logger "=================================="
253logger "✅ 작업 완료"
254logger "📋 대상테이블: $SCHEMA_LOWER.$TABLE_LOWER"
255if [ "$SRID_NEW" -ne 0 ]; then
256 logger "🗺️ 좌표계: $SRID_ORI$SRID_NEW (변환됨)"
257else
258 logger "🗺️ 좌표계: $SRID_ORI (원본)"
259fi
260logger "⏱️ 데이터 입력 소요시간: ${DATA_HOURS}시간 ${DATA_MINUTES}${DATA_SECONDS}"
261logger "⏱️ 공간 인덱스 소요시간: ${INDEX_HOURS}시간 ${INDEX_MINUTES}${INDEX_SECONDS}"
262logger "=================================="