문서유형ㅣ기술정보
분야ㅣ유틸리티
적용제품버전ㅣTibero 7 (DB 7.2.5) Build 313465
문서번호ㅣTUTTI022
개요
작업을 지원하다 보면 티베로를 재기동하는 일이 빈번하나, 간혹 .proc.list 파일이 삭제되거나 훼손되어 정상적인 종료가 불가능한 경우에 대비하고자 해당 문서를 작성합니다.
테스트 환경
|
방법
tbdown 작동 방식
tbdown 명령어가 수행되면 기동시 생성되었던 $TB_HOME/instance/$TB_SID/.proc.list 파일을 참조하여 명령어를 수행합니다.
다만 .proc.list 파일이 삭제 되었거나 파일 내용이 최초 기동시 정보와 상이할 경우 정상적으로 종료가 되지 않습니다.
1. 삭제 되었을 경우
node1@tibero:/home/tibero/tibero7/instance/tibero # tbdown
tbdown failed. proc info file is deleted.
Hint: Please check if the tbsvr instance was already stopped.2. 수정 되었을 경우 (shm key 내용 임의 수정)
node1@tibero:/home/tibero/tibero7/instance/tibero # tbdown
shared memory attach failed.
please retry...이러한 경우 kill -9를 통해 강제 종료만으로 티베로 종료가 가능합니다.
데이터 파일 손상 확률 최소화를 위해 강제 checkpoint, redo 스위치 후 수행을 권장합니다.
.proc.list 파일 내용
Tibero 7 start at (2026-07-28 15:14:36) by 1000
shared memory: 139623464435712 size: 1073741824
shm_key: 1497711233 1 sem_key: -5704128 197 listener_pid: 3400 listener_port: 8629 listener_special_port: 8630 epa_pid: -1
3399 MONP
3401 MGWP
3402 FGWP0000
3403 FGWP0001
3404 PEWP0000
3405 PEWP0001
3406 PEWP0002
3407 PEWP0003
3408 PEWP0004
3409 AGNT
3410 DBWR
3411 RCWP가장 상단은 Tibero Process가 어떤 User ID에 의해서 Fork 되었는지에 대한 정보입니다.
그 아래로는 공유 메모리상 주소 정보와 크기 정보들입니다.
하단 부분들은 tbdown pid 명령어로 확인 가능한 정보들이며 process 별 pid 정보입니다. (pid로 정렬)
다만 tbdown pid 역시 .proc.list 파일이 삭제되거나 훼손 되었을 경우 정상적인 수행이 불가능 할 수 있습니다.
.proc.list 생성 스크립트
환경 구성 제약으로 single linux 환경에서만 테스트 된 스크립트라는 점을 유의해야합니다.
#!/bin/bash
#==============================================================================
# tbdown_make_pid.sh (v2)
# Tibero 인스턴스 부팅 헤더 블록을 "실행 중" OS 상태에서 재구성해 출력.
#
# 사용법 : ./tbdown_make_pid.sh [SID]
# SID 미지정 시 $TB_SID 사용. 포트는 $TB_HOME/config/<SID>.tip 참조.
# 디버그 : TB_DEBUG=1 ./tbdown_make_pid.sh <SID>
# 실행권한: tibero OS 계정(또는 root). /proc/<pid>/{exe,maps} 와
# 소켓-PID 매핑(ss -p / lsof)이 동일 uid 또는 root 에서만 보인다.
#
# v1 대비 변경점
# [FIX-1] 프로세스 탐색을 comm("tbsvr") 의존 → /proc/<pid>/exe 기반으로 교체.
# Tibero가 프로세스 타이틀을 워커명(FGWP0000 등)으로 바꿔 달면
# `pgrep -x tbsvr` 가 0건이 되는 문제 해결.
# [FIX-2] 워커명 추출을 'tbsvr_ 접미사' 가정 → comm/cmdline 토큰 매칭으로 교체.
# 접미사 없는 MGWP/AGNT/DBWR/RCWP 를 전부 MONP 로 찍던 버그 해결.
# [FIX-3] epa_pid 를 special 포트 점유자로 잡던 것 제거. EPA(외부프로시저
# 에이전트)는 리스너 special 포트와 무관 → 실제 EPA 프로세스로 탐지,
# 없으면 -1(원본 동작과 일치).
#==============================================================================
set -u
SID="${1:-${TB_SID:-}}"
TB_HOME="${TB_HOME:-}"
DEBUG="${TB_DEBUG:-0}"
dbg(){ [ "$DEBUG" = "1" ] && printf '[debug] %s\n' "$*" >&2; }
[ -z "$SID" ] && { echo "ERROR: SID를 인자로 주거나 \$TB_SID 를 설정하세요." >&2; exit 1; }
# Tibero는 IPC 키를 signed int32로 출력. unsigned -> signed 변환.
to_int32(){ local v=$1; [ "$v" -ge 2147483648 ] && v=$((v-4294967296)); echo "$v"; }
# 알려진 Tibero 워커명 토큰(필요시 추가). 마지막 [A-Z]{3,4}[0-9]* 는 미지 워커 대비.
TB_WK_RE='MONP|MGWP|FGWP[0-9]+|PEWP[0-9]+|AGNT|DBWR|RCWP|LGWR|CKPT|SNNP|GWHP[0-9]*'
#--- 0) tbsvr 프로세스 집합 (exe 심볼릭링크 기준, comm 변조에 안전) -----------
find_tbsvr_pids(){
local pid exe cmd hits="" all=""
for d in /proc/[0-9]*; do
pid=${d#/proc/}
exe=$(readlink "/proc/$pid/exe" 2>/dev/null)
cmd=$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null)
case "${exe##*/}|$cmd" in *tbsvr*) ;; *) continue ;; esac
all="$all $pid"
case "$cmd $exe" in *"$SID"*) hits="$hits $pid" ;; esac
done
# SID가 cmdline/exe 에 박혀있으면 그걸로 필터, 아니면(단일 인스턴스) 전체.
[ -n "$hits" ] && echo $hits | tr ' ' '\n' | sort -n \
|| echo $all | tr ' ' '\n' | sort -n
}
mapfile -t PIDS < <(find_tbsvr_pids)
[ "${#PIDS[@]}" -eq 0 ] && { echo "ERROR: SID=${SID} 의 tbsvr 프로세스를 찾지 못함(권한/SID 확인)." >&2; exit 1; }
MASTER_PID="${PIDS[0]}" # 최저 PID = MONP(마스터)
dbg "tbsvr pids: ${PIDS[*]} master=$MASTER_PID"
#--- 1) start at = 마스터 기동시각, by = UID --------------------------------
OWNER_UID=$(awk '/^Uid:/{print $2; exit}' "/proc/$MASTER_PID/status")
OWNER_NAME=$(id -nu "$OWNER_UID" 2>/dev/null || echo "$OWNER_UID")
START_RAW=$(ps -o lstart= -p "$MASTER_PID")
START_AT=$(date -d "$START_RAW" "+%Y-%m-%d %H:%M:%S" 2>/dev/null)
[ -z "$START_AT" ] && START_AT="$START_RAW"
#--- 2) /proc/<pid>/maps 의 SysV 공유메모리(최대 세그먼트) ------------------
# maps 라인: <start>-<end> rw-s <off> <dev> <inode> /SYSV<keyhex> (deleted)
# 주의: attach 주소는 부팅마다 달라짐(ASLR). 원본 로그값 복원은 불가, 현재값만.
SHM_ADDR_DEC=0; SHM_KEY_HEX=""; MAXSZ=0
while read -r start end key; do
s=$((16#$start)); e=$((16#$end)); sz=$((e-s))
[ "$sz" -gt "$MAXSZ" ] && { MAXSZ=$sz; SHM_ADDR_DEC=$s; SHM_KEY_HEX=$key; }
done < <(awk '$6 ~ /^\/SYSV/ {split($1,a,"-"); k=$6; sub(/^\/SYSV/,"",k); print a[1],a[2],k}' \
"/proc/$MASTER_PID/maps" 2>/dev/null)
[ -z "$SHM_KEY_HEX" ] && { echo "ERROR: SysV 공유메모리 매핑을 못 찾음(권한/버전 확인)." >&2; exit 1; }
SHM_KEY_U=$((16#$SHM_KEY_HEX))
SHM_KEY=$(to_int32 "$SHM_KEY_U")
SHM_KEY_NORM=$(printf '0x%x' "$SHM_KEY_U")
dbg "shm addr=$SHM_ADDR_DEC keyhex=$SHM_KEY_HEX key=$SHM_KEY size=$MAXSZ"
#--- 3) ipcs -m : size(= 매칭 key 의 bytes), 그리고 두번째 필드 = 세그먼트 개수 ---
# 배너의 'shm_key: <key> <N>' 에서 N = 인스턴스 소유자(tibero)의 공유메모리
# 세그먼트 개수(Tibero는 보통 SGA 1개 → 1). shmid 가 아님(같은 인스턴스라도
# shmid 와 N 이 달라 id 가 아님이 확인됨).
SHM_SIZE="-1"; SHM_NSEG=0
while read -r key id owner perms bytes rest; do
case "$key" in 0x*) ;; *) continue ;; esac
[ "$owner" = "$OWNER_NAME" ] && SHM_NSEG=$((SHM_NSEG+1))
[ "$(printf '0x%x' "$((key))")" = "$SHM_KEY_NORM" ] && SHM_SIZE=$bytes
done < <(ipcs -m)
[ "$SHM_SIZE" = "-1" ] && SHM_SIZE=$MAXSZ
#--- 4) ipcs -s : sem_key(첫 소유 set), 두번째 필드 = 세마포어 set 개수 ------
# 'sem_key: <key> <M>' 에서 M = 소유자가 만든 세마포어 set 개수.
# (nsems 합계가 아님: 실측 set 197개 × set당 nsems 2 = 합 394 였고 배너는 197)
# shm 의 '세그먼트 개수' 와 대칭으로 둘 다 'IPC 객체 개수'.
SEM_KEY="0"; SEM_NSET=0; first_sem=1
while read -r key id owner perms nsems rest; do
case "$key" in 0x*) ;; *) continue ;; esac
[ "$owner" = "$OWNER_NAME" ] || continue
SEM_NSET=$((SEM_NSET + 1))
if [ "$first_sem" = "1" ]; then SEM_KEY=$(to_int32 "$((key))"); first_sem=0; fi
done < <(ipcs -s)
#--- 5) 리스너 포트(.tip), special = +1 -------------------------------------
LPORT="-1"
TIP="${TB_HOME:+$TB_HOME/config/${SID}.tip}"
if [ -n "$TIP" ] && [ -r "$TIP" ]; then
LPORT=$(awk -F= '/^[[:space:]]*LISTENER_PORT[[:space:]]*=/{gsub(/[[:space:]]/,"",$2);print $2;exit}' "$TIP")
[ -z "$LPORT" ] && LPORT="-1"
fi
LSPECIAL="-1"; [ "$LPORT" != "-1" ] && LSPECIAL=$((LPORT+1))
#--- 6) 리스너 PID : LISTENER_PORT 점유 프로세스 ----------------------------
listen_pid_of(){
local port=$1 pid=""
[ "$port" = "-1" ] && { echo -1; return; }
command -v ss >/dev/null 2>&1 && \
pid=$(ss -ltnp "sport = :$port" 2>/dev/null | grep -oE 'pid=[0-9]+' | head -1 | cut -d= -f2)
[ -z "$pid" ] && command -v lsof >/dev/null 2>&1 && \
pid=$(lsof -nP -iTCP:"$port" -sTCP:LISTEN -t 2>/dev/null | head -1)
[ -z "$pid" ] && command -v fuser >/dev/null 2>&1 && \
pid=$(fuser "$port/tcp" 2>/dev/null | tr -s ' ' '\n' | grep -E '^[0-9]+$' | head -1)
echo "${pid:--1}"
}
LPID=$(listen_pid_of "$LPORT")
#--- 7) epa_pid : 실제 EPA 프로세스 탐지. 없으면 -1 -------------------------
# EPA(외부 프로시저 에이전트)는 별도 프로세스(tbepa/EPA 워커). special 포트와 무관.
EPA_PID=-1
for p in "${PIDS[@]}"; do
blob="$(cat /proc/$p/comm 2>/dev/null) $(tr '\0' ' ' < /proc/$p/cmdline 2>/dev/null)"
case "$blob" in *EPA*|*tbepa*) EPA_PID=$p; break ;; esac
done
#--- 8) 버전 ----------------------------------------------------------------
VER=$( { tbboot -h 2>&1; tbsql -v 2>&1; } | grep -oiE 'Tibero[[:space:]]*[0-9]+' | head -1)
[ -z "$VER" ] && VER="Tibero 7"
#--- 9) 워커명 추출 ---------------------------------------------------------
# - 마스터(최저 PID)는 '-t NORMAL' 로 떠서 NORMAL 로 보이나 배너명은 MONP.
# - OS 타이틀의 인덱스는 3자리(FGWP000)지만 배너는 4자리(FGWP0000) → 재패딩.
worker_name(){
local pid=$1 comm cmd tok cls num
if [ "$pid" = "$MASTER_PID" ]; then echo "MONP"; return; fi
comm=$(cat "/proc/$pid/comm" 2>/dev/null)
cmd=$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null)
dbg "pid=$pid comm='$comm' cmdline='$cmd'"
tok=""
for s in "$comm" "$cmd"; do
tok=$(grep -oE "$TB_WK_RE" <<<"$s" | head -1)
[ -n "$tok" ] && break
done
if [ -z "$tok" ]; then
tok=$(grep -oE '\-t[[:space:]]+[A-Z0-9]+' <<<"$cmd" | head -1 | awk '{print $2}')
fi
case "$tok" in
NORMAL|"") echo "MONP" ;; # 안전망: 태그 없으면 MONP
FGWP*|PEWP*)
cls=${tok%%[0-9]*}; num=${tok#$cls}
if [ -n "$num" ]; then printf '%s%04d\n' "$cls" "$((10#$num))"; else echo "$tok"; fi
;;
*) echo "$tok" ;;
esac
}
#--- 출력 -------------------------------------------------------------------
printf '%s start at (%s) by %s\n' "$VER" "$START_AT" "$OWNER_UID"
printf 'shared memory: %s size: %s\n' "$SHM_ADDR_DEC" "$SHM_SIZE"
printf 'shm_key: %s %s sem_key: %s %s listener_pid: %s listener_port: %s listener_special_port: %s epa_pid: %s\n' \
"$SHM_KEY" "$SHM_NSEG" "$SEM_KEY" "$SEM_NSET" "$LPID" "$LPORT" "$LSPECIAL" "$EPA_PID"
for pid in "${PIDS[@]}"; do
printf '%s %s\n' "$pid" "$(worker_name "$pid")"
done
.proc.list 수동 생성 후 tbdown 테스트
1. 삭제 되었을 경우
node1@tibero:/home/tibero/tibero7/instance/tibero # ll -a
합계 16
drwxr-xr-x. 3 tibero dba 20 7월 22 16:45 ..
drwxr-xr-x. 4 tibero dba 29 7월 22 16:45 out
drwxr-xr-x. 9 tibero dba 113 7월 22 16:47 log
drwxr-xr-x. 5 tibero dba 54 7월 22 16:49 dump
drwxr-xr-x. 2 tibero dba 177 7월 28 15:14 path
-rw-r--r--. 1 tibero dba 366 7월 28 15:19 .proc.list
-rw-r--r--. 1 tibero dba 8764 7월 28 15:28 make.sh
drwxr-xr-x. 6 tibero dba 85 7월 28 15:28 .
node1@tibero:/home/tibero/tibero7/instance/tibero #
node1@tibero:/home/tibero/tibero7/instance/tibero # ps -ef | grep tbsvr
tibero 3399 1 0 15:14 pts/0 00:00:00 tbsvr -t NORMAL -SVR_SID tibero
tibero 3401 3399 0 15:14 pts/0 00:00:00 tbsvr_MGWP -t NORMAL -SVR_SID tibero
tibero 3402 3399 0 15:14 pts/0 00:00:00 tbsvr_FGWP000 -t NORMAL -SVR_SID tibero
tibero 3403 3399 0 15:14 pts/0 00:00:01 tbsvr_FGWP001 -t NORMAL -SVR_SID tibero
tibero 3404 3399 0 15:14 pts/0 00:00:00 tbsvr_PEWP000 -t NORMAL -SVR_SID tibero
tibero 3405 3399 0 15:14 pts/0 00:00:00 tbsvr_PEWP001 -t NORMAL -SVR_SID tibero
tibero 3406 3399 0 15:14 pts/0 00:00:00 tbsvr_PEWP002 -t NORMAL -SVR_SID tibero
tibero 3407 3399 0 15:14 pts/0 00:00:00 tbsvr_PEWP003 -t NORMAL -SVR_SID tibero
tibero 3408 3399 0 15:14 pts/0 00:00:00 tbsvr_PEWP004 -t NORMAL -SVR_SID tibero
tibero 3409 3399 0 15:14 pts/0 00:00:01 tbsvr_AGNT -t NORMAL -SVR_SID tibero
tibero 3410 3399 0 15:14 pts/0 00:00:00 tbsvr_DBWR -t NORMAL -SVR_SID tibero
tibero 3411 3399 0 15:14 pts/0 00:00:00 tbsvr_RCWP -t NORMAL -SVR_SID tibero
tibero 3575 1207 0 15:28 pts/0 00:00:00 grep --color=auto tbsvr
node1@tibero:/home/tibero/tibero7/instance/tibero #
node1@tibero:/home/tibero/tibero7/instance/tibero # rm .proc.list
node1@tibero:/home/tibero/tibero7/instance/tibero #
node1@tibero:/home/tibero/tibero7/instance/tibero # tbdown
tbdown failed. proc info file is deleted.
Hint: Please check if the tbsvr instance was already stopped.
node1@tibero:/home/tibero/tibero7/instance/tibero #
node1@tibero:/home/tibero/tibero7/instance/tibero # sh make.sh > .proc.list
node1@tibero:/home/tibero/tibero7/instance/tibero #
node1@tibero:/home/tibero/tibero7/instance/tibero # ll -a
합계 16
drwxr-xr-x. 3 tibero dba 20 7월 22 16:45 ..
drwxr-xr-x. 4 tibero dba 29 7월 22 16:45 out
drwxr-xr-x. 9 tibero dba 113 7월 22 16:47 log
drwxr-xr-x. 5 tibero dba 54 7월 22 16:49 dump
drwxr-xr-x. 2 tibero dba 177 7월 28 15:14 path
-rw-r--r--. 1 tibero dba 8764 7월 28 15:28 make.sh
drwxr-xr-x. 6 tibero dba 85 7월 28 15:29 .
-rw-r--r--. 1 tibero dba 369 7월 28 15:29 .proc.list
node1@tibero:/home/tibero/tibero7/instance/tibero #
node1@tibero:/home/tibero/tibero7/instance/tibero # tbdown
Tibero instance terminated (NORMAL mode).
2. 수정 되었을 경우 (shm key 내용 임의 수정)
".proc.list" 15L, 365B written
node1@tibero:/home/tibero/tibero7/instance/tibero # tbdown
shared memory attach failed.
please retry...
node1@tibero:/home/tibero/tibero7/instance/tibero # sh make.sh > .proc.list
node1@tibero:/home/tibero/tibero7/instance/tibero #
node1@tibero:/home/tibero/tibero7/instance/tibero # tbdown
Tibero instance terminated (NORMAL mode).주의
TAC 환경이나 TSC 환경, 그리고 Linux가 아닌 타 OS 경우 기존 스크립트로 작동되지 않을 수 있습니다.