最后活跃于 1756818083

修订 7983fe1912c86e032b80407268ca371db8c212e4

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