shp2pgsql_remote.md
· 11 KiB · Markdown
Исходник
원격서버에 적재시 .pgpass파일이 필요
```bash
nano ~/.pgpass
```
.pgpass파일에 다음 형식으로 작성
```pgsql
hostname:port:database:username:password
```
이후 퍼미션 설정 필수
```bash
chmod 600 ~/.pgpass
```
이후 sh파일 작성
```sh
#!/bin/bash
HOST="hostName" # 실제 호스트 이름으로 변경
PORT="portNumber" # 실제 호스트 이름으로 변경
DB="dbName" # 실제 데이터베이스 이름으로 변경
USER="postgres" # 실제 PostgreSQL 사용자명으로 변경
SCHEMA="schemaName" # 스키마 이름
TABLE="tableName" # 생성할 테이블 이름
# 대소문자 구분 문제 해결을 위해 소문자로 변환
SCHEMA_LOWER=$(echo "$SCHEMA" | tr '[:upper:]' '[:lower:]')
TABLE_LOWER=$(echo "$TABLE" | tr '[:upper:]' '[:lower:]')
SRID_ORI=5186 # 원본 좌표계
SRID_NEW=0 # 변환 좌표계 (0이면 좌표변환 안함)
CHARSET="UTF-8" # 문자 인코딩
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개"
# 필수 변수 검증
if [ -z "$DB" ]; then
logger "❌ 오류: DB 변수가 설정되지 않았습니다. 스크립트 상단에서 DB 변수를 설정해주세요."
exit 1
fi
if [ -z "$TABLE" ]; then
logger "❌ 오류: TABLE 변수가 설정되지 않았습니다. 스크립트 상단에서 TABLE 변수를 설정해주세요."
exit 1
fi
logger "📋 설정된 변수:"
logger " - 데이터베이스: $DB"
logger " - 사용자: $USER"
logger " - 스키마: $SCHEMA"
logger " - 테이블: $TABLE"
# PostgreSQL 연결 테스트
if ! psql -h $HOST -p $PORT -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_LOWER.$TABLE_LOWER"
# 테이블 존재 여부를 더 안정적으로 확인 (소문자로 비교)
TABLE_EXISTS=$(psql -h $HOST -p $PORT -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)
logger "🔍 테이블 존재 확인 결과: '$TABLE_EXISTS'"
# 모든 SHP 파일을 배열로 수집
SHP_FILES=($(find "$SHP_DIR" -name "*.shp" | sort))
TOTAL_FILES=${#SHP_FILES[@]}
if [ "$TABLE_EXISTS" = "t" ]; then
logger "📋 테이블 $SCHEMA_LOWER.$TABLE_LOWER이 이미 존재합니다. Append 모드로 진행합니다."
logger "🔄 총 $TOTAL_FILES개 파일을 append 모드로 처리합니다..."
# 모든 파일을 append 모드로 처리
for shp in "${SHP_FILES[@]}"; do
wait_for_jobs
import_append "$shp" &
done
wait
else
logger "📋 테이블 $SCHEMA_LOWER.$TABLE_LOWER이 존재하지 않습니다. 새로 생성합니다."
logger "🔄 총 $TOTAL_FILES개 파일을 처리합니다..."
# 첫 번째 파일로 테이블 생성
FIRST_FILE="${SHP_FILES[0]}"
FIRST_BASENAME=$(basename "$FIRST_FILE")
# 테이블 생성 시작 시간 기록
TABLE_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
TABLE_START_TIMESTAMP=$(date +%s)
logger "🚀 [시작] 테이블 생성 시작: $FIRST_BASENAME - $TABLE_START_TIME"
# 좌표변환 여부에 따라 shp2pgsql 명령어 결정
if [ "$SRID_NEW" -ne 0 ]; then
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW "$FIRST_FILE" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
else
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI "$FIRST_FILE" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
fi
EXIT_CODE=$?
# 테이블 생성 종료 시간 기록
TABLE_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
TABLE_END_TIMESTAMP=$(date +%s)
TABLE_DURATION=$((TABLE_END_TIMESTAMP - TABLE_START_TIMESTAMP))
# 테이블 생성 소요시간을 시:분:초 형식으로 변환
TABLE_HOURS=$((TABLE_DURATION / 3600))
TABLE_MINUTES=$(((TABLE_DURATION % 3600) / 60))
TABLE_SECONDS=$((TABLE_DURATION % 60))
# 1보다 작으면 0으로 표시
if [ $TABLE_HOURS -lt 1 ]; then TABLE_HOURS=0; fi
if [ $TABLE_MINUTES -lt 1 ]; then TABLE_MINUTES=0; fi
if [ $EXIT_CODE -eq 0 ]; then
logger "✅ [완료] 테이블 생성 완료: $TABLE_END_TIME (소요: ${TABLE_HOURS}시간 ${TABLE_MINUTES}분 ${TABLE_SECONDS}초)"
# 나머지 파일들을 append 모드로 처리
if [ $TOTAL_FILES -gt 1 ]; then
logger "🔄 나머지 $((TOTAL_FILES - 1))개 파일을 append 모드로 처리합니다..."
for ((i=1; i<TOTAL_FILES; i++)); do
shp="${SHP_FILES[i]}"
wait_for_jobs
import_append "$shp" &
done
wait
fi
else
logger "❌ [실패] 테이블 생성 실패: $TABLE_END_TIME (소요: ${TABLE_HOURS}시간 ${TABLE_MINUTES}분 ${TABLE_SECONDS}초)"
echo "$OUTPUT" >> "$LOG_FILE"
exit 1
fi
fi
# 2. 병렬로 나머지 파일 append (shp2pgsql -a)
function import_append() {
SHP="$1"
BASENAME=$(basename "$SHP")
# 처리 시작 시간 기록
FILE_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
FILE_START_TIMESTAMP=$(date +%s)
logger "🚀 [시작] $BASENAME 처리 시작: $FILE_START_TIME"
# 좌표변환 여부에 따라 shp2pgsql 명령어 결정
if [ "$SRID_NEW" -ne 0 ]; then
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
else
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
fi
EXIT_CODE=$?
# 처리 종료 시간 기록
FILE_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
FILE_END_TIMESTAMP=$(date +%s)
FILE_DURATION=$((FILE_END_TIMESTAMP - FILE_START_TIMESTAMP))
# 파일별 소요시간을 시:분:초 형식으로 변환
FILE_HOURS=$((FILE_DURATION / 3600))
FILE_MINUTES=$(((FILE_DURATION % 3600) / 60))
FILE_SECONDS=$((FILE_DURATION % 60))
# 1보다 작으면 0으로 표시
if [ $FILE_HOURS -lt 1 ]; then FILE_HOURS=0; fi
if [ $FILE_MINUTES -lt 1 ]; then FILE_MINUTES=0; fi
if [ $EXIT_CODE -eq 0 ]; then
logger "✅ [완료] $BASENAME 처리 완료: $FILE_END_TIME (소요: ${FILE_HOURS}시간 ${FILE_MINUTES}분 ${FILE_SECONDS}초)"
else
logger "❌ [실패] $BASENAME 처리 실패: $FILE_END_TIME (소요: ${FILE_HOURS}시간 ${FILE_MINUTES}분 ${FILE_SECONDS}초)"
# 오류 메시지만 추출하여 로그에 기록
ERROR_MSG=$(echo "$OUTPUT" | grep -E "(ERROR|FATAL|WARNING|오류|실패|실패했습니다)" || echo "$OUTPUT")
if [ -n "$ERROR_MSG" ]; then
logger "⚠️ 오류 내용: $ERROR_MSG"
echo "=== $BASENAME 처리 오류 상세 내용 ===" >> "$LOG_FILE"
echo "$OUTPUT" >> "$LOG_FILE"
echo "=====================================" >> "$LOG_FILE"
fi
logger "🔄 다음 파일 처리를 계속 진행합니다."
fi
}
# job control 함수
function wait_for_jobs() {
while (( $(jobs -rp | wc -l) >= MAX_JOBS )); do
sleep 1
done
}
# 병렬 처리는 이미 위에서 완료되었습니다.
logger "🔄 병렬 처리 완료"
# 데이터 입력 완료 시간 기록
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
# 3. (선택) 인덱스 재생성 (권장: 한 번에 생성)
INDEX_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
INDEX_START_TIMESTAMP=$(date +%s)
logger "🔍 공간 인덱스 생성 시작: $INDEX_START_TIME"
# 공간 인덱스 생성 (PostGIS 확장이 활성화되어 있어야 함)
INDEX_OUTPUT=$(psql -h $HOST -p $PORT -U "$USER" -d "$DB" -c "CREATE INDEX IF NOT EXISTS ${TABLE_LOWER}_geom_idx ON $SCHEMA_LOWER.$TABLE_LOWER USING GIST (geom);" 2>&1)
INDEX_EXIT_CODE=$?
if [ $INDEX_EXIT_CODE -eq 0 ]; then
logger "✅ Spatial index created successfully"
else
logger "❌ Failed to create spatial index"
# 오류 메시지만 추출하여 로그에 기록
INDEX_ERROR_MSG=$(echo "$INDEX_OUTPUT" | grep -E "(ERROR|FATAL|WARNING|오류|실패|실패했습니다)" || echo "$INDEX_OUTPUT")
if [ -n "$INDEX_ERROR_MSG" ]; then
logger "⚠️ 인덱스 생성 오류 내용: $INDEX_ERROR_MSG"
echo "=== 공간 인덱스 생성 오류 상세 내용 ===" >> "$LOG_FILE"
echo "$INDEX_OUTPUT" >> "$LOG_FILE"
echo "=====================================" >> "$LOG_FILE"
fi
logger "⚠️ PostGIS 확장이 활성화되어 있는지 확인하세요: CREATE EXTENSION IF NOT EXISTS postgis;"
logger "🔄 인덱스 생성에 실패했지만 스크립트는 계속 진행됩니다."
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
logger "=================================="
logger "✅ 작업 완료"
logger "📋 대상테이블: $SCHEMA_LOWER.$TABLE_LOWER"
if [ "$SRID_NEW" -ne 0 ]; then
logger "🗺️ 좌표계: $SRID_ORI → $SRID_NEW (변환됨)"
else
logger "🗺️ 좌표계: $SRID_ORI (원본)"
fi
logger "⏱️ 데이터 입력 소요시간: ${DATA_HOURS}시간 ${DATA_MINUTES}분 ${DATA_SECONDS}초"
logger "⏱️ 공간 인덱스 소요시간: ${INDEX_HOURS}시간 ${INDEX_MINUTES}분 ${INDEX_SECONDS}초"
logger "=================================="
```
이후 sh파일 퍼미션 설정
```bash
chmod +x shp2pgsql.sh
```
sh파일 실행
```bash
./shp2pgsql.sh
```
원격서버에 적재시 .pgpass파일이 필요
nano ~/.pgpass
.pgpass파일에 다음 형식으로 작성
hostname:port:database:username:password
이후 퍼미션 설정 필수
chmod 600 ~/.pgpass
이후 sh파일 작성
#!/bin/bash
HOST="hostName" # 실제 호스트 이름으로 변경
PORT="portNumber" # 실제 호스트 이름으로 변경
DB="dbName" # 실제 데이터베이스 이름으로 변경
USER="postgres" # 실제 PostgreSQL 사용자명으로 변경
SCHEMA="schemaName" # 스키마 이름
TABLE="tableName" # 생성할 테이블 이름
# 대소문자 구분 문제 해결을 위해 소문자로 변환
SCHEMA_LOWER=$(echo "$SCHEMA" | tr '[:upper:]' '[:lower:]')
TABLE_LOWER=$(echo "$TABLE" | tr '[:upper:]' '[:lower:]')
SRID_ORI=5186 # 원본 좌표계
SRID_NEW=0 # 변환 좌표계 (0이면 좌표변환 안함)
CHARSET="UTF-8" # 문자 인코딩
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개"
# 필수 변수 검증
if [ -z "$DB" ]; then
logger "❌ 오류: DB 변수가 설정되지 않았습니다. 스크립트 상단에서 DB 변수를 설정해주세요."
exit 1
fi
if [ -z "$TABLE" ]; then
logger "❌ 오류: TABLE 변수가 설정되지 않았습니다. 스크립트 상단에서 TABLE 변수를 설정해주세요."
exit 1
fi
logger "📋 설정된 변수:"
logger " - 데이터베이스: $DB"
logger " - 사용자: $USER"
logger " - 스키마: $SCHEMA"
logger " - 테이블: $TABLE"
# PostgreSQL 연결 테스트
if ! psql -h $HOST -p $PORT -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_LOWER.$TABLE_LOWER"
# 테이블 존재 여부를 더 안정적으로 확인 (소문자로 비교)
TABLE_EXISTS=$(psql -h $HOST -p $PORT -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)
logger "🔍 테이블 존재 확인 결과: '$TABLE_EXISTS'"
# 모든 SHP 파일을 배열로 수집
SHP_FILES=($(find "$SHP_DIR" -name "*.shp" | sort))
TOTAL_FILES=${#SHP_FILES[@]}
if [ "$TABLE_EXISTS" = "t" ]; then
logger "📋 테이블 $SCHEMA_LOWER.$TABLE_LOWER이 이미 존재합니다. Append 모드로 진행합니다."
logger "🔄 총 $TOTAL_FILES개 파일을 append 모드로 처리합니다..."
# 모든 파일을 append 모드로 처리
for shp in "${SHP_FILES[@]}"; do
wait_for_jobs
import_append "$shp" &
done
wait
else
logger "📋 테이블 $SCHEMA_LOWER.$TABLE_LOWER이 존재하지 않습니다. 새로 생성합니다."
logger "🔄 총 $TOTAL_FILES개 파일을 처리합니다..."
# 첫 번째 파일로 테이블 생성
FIRST_FILE="${SHP_FILES[0]}"
FIRST_BASENAME=$(basename "$FIRST_FILE")
# 테이블 생성 시작 시간 기록
TABLE_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
TABLE_START_TIMESTAMP=$(date +%s)
logger "🚀 [시작] 테이블 생성 시작: $FIRST_BASENAME - $TABLE_START_TIME"
# 좌표변환 여부에 따라 shp2pgsql 명령어 결정
if [ "$SRID_NEW" -ne 0 ]; then
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW "$FIRST_FILE" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
else
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI "$FIRST_FILE" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
fi
EXIT_CODE=$?
# 테이블 생성 종료 시간 기록
TABLE_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
TABLE_END_TIMESTAMP=$(date +%s)
TABLE_DURATION=$((TABLE_END_TIMESTAMP - TABLE_START_TIMESTAMP))
# 테이블 생성 소요시간을 시:분:초 형식으로 변환
TABLE_HOURS=$((TABLE_DURATION / 3600))
TABLE_MINUTES=$(((TABLE_DURATION % 3600) / 60))
TABLE_SECONDS=$((TABLE_DURATION % 60))
# 1보다 작으면 0으로 표시
if [ $TABLE_HOURS -lt 1 ]; then TABLE_HOURS=0; fi
if [ $TABLE_MINUTES -lt 1 ]; then TABLE_MINUTES=0; fi
if [ $EXIT_CODE -eq 0 ]; then
logger "✅ [완료] 테이블 생성 완료: $TABLE_END_TIME (소요: ${TABLE_HOURS}시간 ${TABLE_MINUTES}분 ${TABLE_SECONDS}초)"
# 나머지 파일들을 append 모드로 처리
if [ $TOTAL_FILES -gt 1 ]; then
logger "🔄 나머지 $((TOTAL_FILES - 1))개 파일을 append 모드로 처리합니다..."
for ((i=1; i<TOTAL_FILES; i++)); do
shp="${SHP_FILES[i]}"
wait_for_jobs
import_append "$shp" &
done
wait
fi
else
logger "❌ [실패] 테이블 생성 실패: $TABLE_END_TIME (소요: ${TABLE_HOURS}시간 ${TABLE_MINUTES}분 ${TABLE_SECONDS}초)"
echo "$OUTPUT" >> "$LOG_FILE"
exit 1
fi
fi
# 2. 병렬로 나머지 파일 append (shp2pgsql -a)
function import_append() {
SHP="$1"
BASENAME=$(basename "$SHP")
# 처리 시작 시간 기록
FILE_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
FILE_START_TIMESTAMP=$(date +%s)
logger "🚀 [시작] $BASENAME 처리 시작: $FILE_START_TIME"
# 좌표변환 여부에 따라 shp2pgsql 명령어 결정
if [ "$SRID_NEW" -ne 0 ]; then
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI:$SRID_NEW -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
else
OUTPUT=$(shp2pgsql -W "$CHARSET" -s $SRID_ORI -a "$SHP" $SCHEMA_LOWER.$TABLE_LOWER | psql -h $HOST -p $PORT -U "$USER" -d "$DB" 2>&1)
fi
EXIT_CODE=$?
# 처리 종료 시간 기록
FILE_END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
FILE_END_TIMESTAMP=$(date +%s)
FILE_DURATION=$((FILE_END_TIMESTAMP - FILE_START_TIMESTAMP))
# 파일별 소요시간을 시:분:초 형식으로 변환
FILE_HOURS=$((FILE_DURATION / 3600))
FILE_MINUTES=$(((FILE_DURATION % 3600) / 60))
FILE_SECONDS=$((FILE_DURATION % 60))
# 1보다 작으면 0으로 표시
if [ $FILE_HOURS -lt 1 ]; then FILE_HOURS=0; fi
if [ $FILE_MINUTES -lt 1 ]; then FILE_MINUTES=0; fi
if [ $EXIT_CODE -eq 0 ]; then
logger "✅ [완료] $BASENAME 처리 완료: $FILE_END_TIME (소요: ${FILE_HOURS}시간 ${FILE_MINUTES}분 ${FILE_SECONDS}초)"
else
logger "❌ [실패] $BASENAME 처리 실패: $FILE_END_TIME (소요: ${FILE_HOURS}시간 ${FILE_MINUTES}분 ${FILE_SECONDS}초)"
# 오류 메시지만 추출하여 로그에 기록
ERROR_MSG=$(echo "$OUTPUT" | grep -E "(ERROR|FATAL|WARNING|오류|실패|실패했습니다)" || echo "$OUTPUT")
if [ -n "$ERROR_MSG" ]; then
logger "⚠️ 오류 내용: $ERROR_MSG"
echo "=== $BASENAME 처리 오류 상세 내용 ===" >> "$LOG_FILE"
echo "$OUTPUT" >> "$LOG_FILE"
echo "=====================================" >> "$LOG_FILE"
fi
logger "🔄 다음 파일 처리를 계속 진행합니다."
fi
}
# job control 함수
function wait_for_jobs() {
while (( $(jobs -rp | wc -l) >= MAX_JOBS )); do
sleep 1
done
}
# 병렬 처리는 이미 위에서 완료되었습니다.
logger "🔄 병렬 처리 완료"
# 데이터 입력 완료 시간 기록
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
# 3. (선택) 인덱스 재생성 (권장: 한 번에 생성)
INDEX_START_TIME=$(date '+%Y-%m-%d %H:%M:%S')
INDEX_START_TIMESTAMP=$(date +%s)
logger "🔍 공간 인덱스 생성 시작: $INDEX_START_TIME"
# 공간 인덱스 생성 (PostGIS 확장이 활성화되어 있어야 함)
INDEX_OUTPUT=$(psql -h $HOST -p $PORT -U "$USER" -d "$DB" -c "CREATE INDEX IF NOT EXISTS ${TABLE_LOWER}_geom_idx ON $SCHEMA_LOWER.$TABLE_LOWER USING GIST (geom);" 2>&1)
INDEX_EXIT_CODE=$?
if [ $INDEX_EXIT_CODE -eq 0 ]; then
logger "✅ Spatial index created successfully"
else
logger "❌ Failed to create spatial index"
# 오류 메시지만 추출하여 로그에 기록
INDEX_ERROR_MSG=$(echo "$INDEX_OUTPUT" | grep -E "(ERROR|FATAL|WARNING|오류|실패|실패했습니다)" || echo "$INDEX_OUTPUT")
if [ -n "$INDEX_ERROR_MSG" ]; then
logger "⚠️ 인덱스 생성 오류 내용: $INDEX_ERROR_MSG"
echo "=== 공간 인덱스 생성 오류 상세 내용 ===" >> "$LOG_FILE"
echo "$INDEX_OUTPUT" >> "$LOG_FILE"
echo "=====================================" >> "$LOG_FILE"
fi
logger "⚠️ PostGIS 확장이 활성화되어 있는지 확인하세요: CREATE EXTENSION IF NOT EXISTS postgis;"
logger "🔄 인덱스 생성에 실패했지만 스크립트는 계속 진행됩니다."
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
logger "=================================="
logger "✅ 작업 완료"
logger "📋 대상테이블: $SCHEMA_LOWER.$TABLE_LOWER"
if [ "$SRID_NEW" -ne 0 ]; then
logger "🗺️ 좌표계: $SRID_ORI → $SRID_NEW (변환됨)"
else
logger "🗺️ 좌표계: $SRID_ORI (원본)"
fi
logger "⏱️ 데이터 입력 소요시간: ${DATA_HOURS}시간 ${DATA_MINUTES}분 ${DATA_SECONDS}초"
logger "⏱️ 공간 인덱스 소요시간: ${INDEX_HOURS}시간 ${INDEX_MINUTES}분 ${INDEX_SECONDS}초"
logger "=================================="
이후 sh파일 퍼미션 설정
chmod +x shp2pgsql.sh
sh파일 실행
./shp2pgsql.sh