프로세스 관리
Linux 프로세스의 생성, 모니터링, 제어 및 최적화 완벽 가이드
Linux 프로세스의 생성, 모니터링, 제어 및 최적화 완벽 가이드
목표: 프로세스 문제를 실시간으로 진단하고 해결할 수 있는 수준
🧬 프로세스 기초
프로세스 vs 스레드
| 구분 | 프로세스 (Process) | 스레드 (Thread) |
|---|---|---|
| 정의 | 실행 중인 프로그램 인스턴스 | 프로세스 내 실행 단위 |
| 메모리 | 독립된 주소 공간 | 프로세스 메모리 공유 |
| 통신 | IPC (파이프, 소켓, 공유메모리) | 직접 메모리 접근 |
| 생성 비용 | 높음 (fork + exec) | 낮음 |
| 격리 | 강함 (한 프로세스 충돌이 다른 프로세스에 영향 없음) | 약함 |
프로세스 상태 (Process States)
[생성]
│
▼
[준비 Ready] ◄──────┐
│ │
▼ (스케줄러) │ (시간 만료)
[실행 Running] │
│ │
┌─────┴─────┐ │
▼ ▼ │
[대기 Waiting] [종료] │
(I/O, 이벤트) │
│ │
└───────────────────┘
주요 상태:
| 상태 | 코드 | 의미 |
|---|---|---|
| 실행 중 | R (running) | CPU에서 실행 중 또는 실행 대기 |
| 대기 중 | S (sleeping) | 인터럽트 가능한 수면 (I/O 대기) |
| 디스크 대기 | D (disk sleep) | 인터럽트 불가능한 수면 |
| 중지됨 | T (stopped) | SIGSTOP에 의해 중지 |
| 좀비 | Z (zombie) | 종료되었으나 부모가 wait()하지 않음 |
| 고아 | 부모가 먼저 종료된 프로세스 (init/systemd가 입양) |
PID (Process ID) 체계
| PID | 프로세스 | 설명 |
|---|---|---|
| 1 | systemd (또는 init) | 모든 프로세스의 조상 |
| 2 | kthreadd | 커널 스레드의 부모 |
| 자동 할당 | 일반 프로세스 | 순차적 또는 무작위 할당 |
🔍 프로세스 조회
ps — 프로세스 스냅샷
# 기본 출력
ps
# 모든 프로세스 상세 정보
ps aux
# BSD 스타일
ps -ef
# 사용자 지정 출력
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem
# 특정 사용자
ps -u username
# 특정 프로세스 검색
ps aux | grep nginx
# 프로세스 트리
ps axjf
ps -ejH
ps aux 필드 설명:
| 필드 | 의미 |
|---|---|
| USER | 소유자 |
| PID | 프로세스 ID |
| %CPU | CPU 사용률 |
| %MEM | 메모리 사용률 |
| VSZ | 가상 메모리 크기 (KB) |
| RSS | 실제 메모리 크기 (KB) |
| TTY | 제어 터미널 |
| STAT | 상태 |
| START | 시작 시간 |
| TIME | CPU 사용 시간 |
| COMMAND | 실행 명령 |
STAT 코드 상세:
| 코드 | 의미 |
|---|---|
| R | 실행 중 |
| S | 수면 중 |
| D | 디스크 대기 (중단 불가) |
| T | 중지됨 |
| Z | 좀비 |
| s | 세션 리더 |
| + | 포그라운드 프로세스 그룹 |
| l | 멀티스레드 |
| < | 높은 우선순위 |
| N | 낮은 우선순위 |
top — 실시간 모니터링
top # 기본 실행
top -u username # 특정 사용자만
top -p PID1,PID2 # 특정 PID만
top -b -n 1 # 배치 모드 (1회 실행)
top 화면 구성:
top - 10:30:00 up 5 days, 2:15, 3 users, load average: 0.52, 0.58, 0.59
Tasks: 235 total, 1 running, 234 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.3 us, 1.0 sy, 0.0 ni, 96.3 id, 0.3 wa, 0.0 hi, 0.0 si
MiB Mem : 15923.2 total, 2341.5 free, 8234.1 used, 5347.6 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1234 root 20 0 234567 12345 6789 S 5.2 0.8 0:12.34 nginx
top 단축키:
| 키 | 기능 |
|---|---|
h | 도움말 |
q | 종료 |
Space | 즉시 갱신 |
k | 프로세스 종료 (PID 입력) |
r | nice 값 변경 |
M | 메모리 사용량 순서 |
P | CPU 사용량 순서 |
T | 실행 시간 순서 |
u | 특정 사용자 필터 |
c | 전체 명령줄 표시 토글 |
1 | 개별 CPU 코어 표시 |
d | 갱신 간격 변경 |
htop — 향상된 top (설치 필요)
# 설치
apt-get install htop # Debian/Ubuntu
yum install htop # RHEL/CentOS
# 실행
htop
htop 특징:
- 색상으로 시각적 표현
- 마우스 지원
- 트리 뷰 (F5)
- 검색 (F3)
- 필터 (F4)
- 정렬 기준 변경 (F6)
pgrep / pkill — 프로세스 검색/종료
# 이름으로 PID 검색
pgrep nginx
# 이름과 함께 출력
pgrep -l nginx
# 정규식 검색
pgrep -f "python app.py"
# 특정 사용자
pgrep -u www-data nginx
# 가장 오래된/최신 프로세스
pgrep -o nginx
pgrep -n nginx
# 개수 출력
pgrep -c nginx
# 패턴으로 종료
pkill nginx
pkill -f "python app.py"
pkill -9 -u username # 사용자의 모든 프로세스 강제 종료
pidof — PID 찾기
pidof nginx # nginx 프로세스의 PID
pidof -x script.sh # 셸 스크립트의 PID
⚡ 프로세스 제어
kill — 시그널 보내기
# 기본 종료 (SIGTERM = 15)
kill PID
# 강제 종료 (SIGKILL = 9)
kill -9 PID
# 설정 재로드 (SIGHUP = 1)
kill -1 PID
# 사용자 정의 시그널
kill -USR1 PID
kill -USR2 PID
# 시그널 목록
kill -l
주요 시그널:
| 시그널 | 번호 | 기본 동작 | 설명 |
|---|---|---|---|
| SIGHUP | 1 | 종료 | 터미널 연결 끊김 (설정 재로드로 활용) |
| SIGINT | 2 | 종료 | Ctrl+C |
| SIGQUIT | 3 | 종료+코어덤프 | Ctrl+\ |
| SIGKILL | 9 | 종료 (강제) | 무조건 즉시 종료, 처리 불가 |
| SIGTERM | 15 | 종료 | 정상 종료 요청 (기본) |
| SIGUSR1 | 10 | 사용자 정의 | 로그 로테이션 등 |
| SIGUSR2 | 12 | 사용자 정의 | 사용자 정의 동작 |
| SIGSTOP | 19 | 중지 | 일시 중지 (SIGCONT로 재개) |
| SIGCONT | 18 | 계속 | 중지된 프로세스 재개 |
시그널 처리 순서:
- SIGTERM (15) 먼저 시도 — 정상 종료 기회 제공
- **SIGKILL (9)**는 최후의 수단 — 데이터 손실 가능
killall — 이름으로 종료
killall nginx # nginx 프로세스 모두 종료
killall -9 nginx # 강제 종료
killall -u username # 사용자의 모든 프로세스
killall -r "pattern" # 정규식 매칭
pkill — 패턴으로 종료
pkill python # python 프로세스 종료
pkill -f "python app.py" # 전체 명령줄 매칭
pkill -u username # 사용자의 모든 프로세스
nice / renice — 우선순위 조정
# 새 프로세스를 낮은 우선순위로 실행
nice -n 10 ./script.sh
# 실행 중인 프로세스 우선순위 변경
renice -n 5 -p PID
renice -n -5 -u username # 사용자의 모든 프로세스
nice 값 범위:
| 범위 | 우선순위 | 설명 |
|---|---|---|
| -20 ~ -1 | 높음 | 더 많은 CPU 시간 할당 |
| 0 | 기본 | 일반 우선순위 |
| 1 ~ 19 | 낮음 | 다른 프로세스에 양보 |
주의: 음수 nice 값은 root만 설정 가능
🔄 백그라운드 & 포그라운드
기본 개념
- 포그라운드 (Foreground): 터미널과 연결된 프로세스, 터미널 제어
- 백그라운드 (Background): 터미널과 분리된 프로세스, 계속 실행
작업 제어 (Job Control)
# 백그라운드로 실행
command &
cmd1 && cmd2 & # 조건부 실행
# 실행 중인 프로세스를 백그라운드로 (Ctrl+Z 후)
Ctrl+Z # 일시 중지
bg # 백그라운드로 재개
bg %1 # 작업 번호 1을 백그라운드로
# 백그라운드 작업을 포그라운드로
fg
fg %1 # 작업 번호 1을 포그라운드로
# 작업 목록
jobs
jobs -l # PID 포함
jobs -r # 실행 중인 작업
jobs -s # 중지된 작업
nohup — 터미널 독립 실행
nohup ./script.sh & # 터미널 종료 후에도 계속 실행
nohup python app.py > app.log 2>>1 &
cat nohup.out # 출력 확인
disown — 셸 작업 목록에서 제거
./script.sh &
disown # 현재 작업 제거
disown %1 # 특정 작업 제거
disown -a # 모든 작업 제거
disown -h # 작업은 유지하나 SIGHUP 무시
🖥️ systemd 서비스 관리
서비스 제어
# 서비스 시작
systemctl start nginx
# 서비스 중지
systemctl stop nginx
# 서비스 재시작
systemctl restart nginx
# 설정 재로드 (재시작 없이)
systemctl reload nginx
# 상태 확인
systemctl status nginx
# 부팅 시 자동 시작
systemctl enable nginx
# 부팅 시 자동 시작 해제
systemctl disable nginx
# 현재 활성화 상태 확인
systemctl is-enabled nginx
systemctl is-active nginx
서비스 상태 해석
systemctl status nginx
출력 예시:
● nginx.service - A high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2026-06-01 10:00:00 KST; 5h ago
Docs: man:nginx(8)
Process: 1234 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Main PID: 1235 (nginx)
Tasks: 2 (limit: 4915)
Memory: 3.5M
CGroup: /system.slice/nginx.service
├─1235 nginx: master process /usr/sbin/nginx
└─1236 nginx: worker process
핵심 필드:
| 필드 | 의미 |
|---|---|
| Loaded | 유닛 파일 로드 상태 |
| Active | 현재 상태 (active/inactive/failed) |
| enabled | 부팅 시 자동 시작 여부 |
| Main PID | 주 프로세스 PID |
| CGroup | 컨트롤 그룹 계층 |
서비스 로그 확인
# 최근 로그
journalctl -u nginx
# 실시간 로그
journalctl -u nginx -f
# 특정 시간 이후
journalctl -u nginx --since "2026-06-01 10:00"
# 특정 시간 범위
journalctl -u nginx --since "1 hour ago" --until "30 minutes ago"
# 역순 출력 (최신 먼저)
journalctl -u nginx -r
# 로그 레벨 필터
journalctl -u nginx -p err
# 부팅 이후 로그
journalctl -u nginx -b
📊 프로세스 모니터링 스크립트
CPU/메모리 사용량 Top 10
#!/bin/bash
# top_processes.sh
echo "=== CPU 사용량 Top 10 ==="
ps aux --sort=-%cpu | head -11
echo -e "\n=== 메모리 사용량 Top 10 ==="
ps aux --sort=-%mem | head -11
echo -e "\n=== 좀비 프로세스 ==="
ps aux | awk '$8 ~ /^Z/ {print $0}'
echo -e "\n=== 디스크 대기 프로세스 ==="
ps aux | awk '$8 ~ /^D/ {print $0}'
프로세스 모니터링 (무한 루프)
#!/bin/bash
# monitor.sh
PID=$1
INTERVAL=${2:-5}
if [ -z "$PID" ]; then
echo "Usage: $0 <PID> [interval_seconds]"
exit 1
fi
echo "Monitoring PID $PID (interval: ${INTERVAL}s)"
echo "Timestamp,CPU%,MEM%,VSZ,RSS"
while true; do
if [ -d "/proc/$PID" ]; then
STATS=$(ps -p $PID -o %cpu,%mem,vsz,rss --no-headers)
echo "$(date '+%Y-%m-%d %H:%M:%S'),$STATS"
else
echo "Process $PID not found"
break
fi
sleep $INTERVAL
done
메모리 누수 감지
#!/bin/bash
# memory_leak_detector.sh
PROCESS_NAME=$1
DURATION=${2:-3600} # 기본 1시간
INTERVAL=${3:-60} # 기본 1분마다 체크
START_TIME=$(date +%s)
LOG_FILE="memory_log_$(date +%Y%m%d_%H%M%S).csv"
echo "timestamp,pid,rss_mb,vsz_mb" > $LOG_FILE
while [ $(($(date +%s) - START_TIME)) -lt $DURATION ]; do
PID=$(pgrep -x "$PROCESS_NAME" | head -1)
if [ -n "$PID" ]; then
RSS=$(ps -p $PID -o rss= | awk '{print $1/1024}')
VSZ=$(ps -p $PID -o vsz= | awk '{print $1/1024}')
echo "$(date '+%Y-%m-%d %H:%M:%S'),$PID,$RSS,$VSZ" >> $LOG_FILE
fi
sleep $INTERVAL
done
echo "Monitoring complete. Log saved to $LOG_FILE"
echo "Analyze with: awk -F',' 'NR>1 {sum+=$3; count++} END {print "Avg RSS:", sum/count "MB"}' $LOG_FILE"
🎯 실전 트러블슈팅
CPU 100% 문제
# 1. 원인 프로세스 확인
top
# 2. 특정 프로세스의 스레드 확인
ps -eLf | grep PID
# 3. 시스템콜 추적
strace -p PID
# 4. CPU 사용 패턴 분석
perf top -p PID
메모리 부족 (OOM)
# 1. 메모리 사용 현황
free -h
cat /proc/meminfo
# 2. OOM killer 로그
dmesg | grep -i "out of memory"
journalctl | grep -i "killed process"
# 3. 메모리 사용량 Top
ps aux --sort=-%mem | head -20
# 4. smaps 상세 분석
cat /proc/PID/smaps | grep -E "^(Size|Rss|Pss)"
좀비 프로세스
# 좀비 프로세스 확인
ps aux | awk '$8 ~ /^Z/ {print $0}'
# 부모 프로세스 확인
ps -ef | grep <PPID>
# 부모가 systemd(1)인 경우
# systemd가 주기적으로 수집하므로 자동 해결
# 그 외의 경우: 부모 프로세스 재시작 또는 SIGCHLD 처리 확인
프로세스가 응답 없음
# 1. 상태 확인
ps -p PID -o stat,wchan:20,cmd
# 2. 시스템콜 확인 (무한 대기 중인 시스템콜)
strace -p PID
# 3. 스택 트레이스
cat /proc/PID/stack
# 4. 강제 종료 (최후의 수단)
kill -9 PID
🔗 관련 노트
- 01-01-리눅스-기본-명령어-모음 — 기본 명령어
- 02-02-서비스-관리-systemd — systemd 상세
- 03-02-성능-모니터링 — 고급 모니터링 도구
- 03-01-Linux-내부동작-레퍼런스 — 메모리 심화
- 03-00-Linux-내부동작-자가학습 — 커널 낮은 수준
마지막 업데이트: 2026-06-01