프로세스 관리

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프로세스설명
1systemd (또는 init)모든 프로세스의 조상
2kthreadd커널 스레드의 부모
자동 할당일반 프로세스순차적 또는 무작위 할당

🔍 프로세스 조회

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
%CPUCPU 사용률
%MEM메모리 사용률
VSZ가상 메모리 크기 (KB)
RSS실제 메모리 크기 (KB)
TTY제어 터미널
STAT상태
START시작 시간
TIMECPU 사용 시간
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 입력)
rnice 값 변경
M메모리 사용량 순서
PCPU 사용량 순서
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

주요 시그널:

시그널번호기본 동작설명
SIGHUP1종료터미널 연결 끊김 (설정 재로드로 활용)
SIGINT2종료Ctrl+C
SIGQUIT3종료+코어덤프Ctrl+\
SIGKILL9종료 (강제)무조건 즉시 종료, 처리 불가
SIGTERM15종료정상 종료 요청 (기본)
SIGUSR110사용자 정의로그 로테이션 등
SIGUSR212사용자 정의사용자 정의 동작
SIGSTOP19중지일시 중지 (SIGCONT로 재개)
SIGCONT18계속중지된 프로세스 재개

시그널 처리 순서:

  1. SIGTERM (15) 먼저 시도 — 정상 종료 기회 제공
  2. **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