1. 프로세스 개념

프로세스란?

프로세스는 실행 중인 프로그램의 인스턴스다. 프로그램(디스크의 실행 파일)이 메모리에 로드되어 CPU에 의해 실행되면 프로세스가 된다. 각 프로세스는 독립된 가상 주소 공간, 파일 디스크립터, 환경 변수, 시그널 핸들러 등을 갖는다.

PID, PPID

용어설명
PID (Process ID)프로세스 고유 식별 번호. 커널이 할당하며, 1부터 시작
PPID (Parent PID)부모 프로세스의 PID. 모든 프로세스는 부모가 있다
PID 1init / systemd. 커널이 부팅 시 최초로 생성하는 사용자 공간 프로세스. 모든 프로세스의 최상위 조상
PID 0커널 자체(swapper/idle). 사용자 공간에서는 보이지 않는다
# 현재 셸의 PID
echo $$
 
# 부모 프로세스 PID
echo $PPID
 
# 마지막 백그라운드 프로세스 PID
echo $!

프로세스 상태 (Process States)

상태코드설명
RunningR실행 중 또는 실행 가능(run queue에서 대기)
Sleeping (Interruptible)S이벤트 대기 중 (I/O, 시그널 등). 시그널로 깨울 수 있음
Sleeping (Uninterruptible)D디스크 I/O 등 대기 중. 시그널로 깨울 수 없음. 보통 매우 짧은 시간
StoppedT중지됨 (SIGSTOP 또는 Ctrl+Z). SIGCONT로 재개 가능
ZombieZ종료되었지만 부모가 아직 wait()하지 않은 상태. 프로세스 테이블 엔트리만 남아 있음
ps aux 출력의 STAT 열 추가 문자:
+  포그라운드 프로세스 그룹
s  세션 리더
l  멀티스레드
<  높은 우선순위 (nice < 0)
N  낮은 우선순위 (nice > 0)

프로세스 트리

모든 프로세스는 fork() 시스템 콜로 생성된다. 부모 프로세스가 자식 프로세스를 생성하므로 트리 구조를 형성한다.

systemd (PID 1)
├── sshd
│   └── sshd
│       └── bash
│           └── vim
├── cron
├── nginx
│   ├── nginx (worker)
│   └── nginx (worker)
└── systemd-journald
# 프로세스 트리 확인
pstree
pstree -p              # PID 표시
pstree -u              # 사용자 전환 표시
pstree -a              # 명령줄 인자 표시
pstree user            # 특정 사용자의 프로세스 트리

2. 프로세스 확인

ps - 프로세스 상태 스냅샷

BSD 스타일 (가장 많이 사용)

ps aux
# USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
# root         1  0.0  0.1 168936 11532 ?        Ss   Jan15   0:08 /sbin/init
# root         2  0.0  0.0      0     0 ?        S    Jan15   0:00 [kthreadd]
# user      1234  1.2  2.5 412356 98765 pts/0    Sl+  10:30   0:15 python app.py
설명
USER프로세스 소유자
PID프로세스 ID
%CPUCPU 사용률
%MEM메모리 사용률
VSZ가상 메모리 크기 (KB)
RSS실제 사용 물리 메모리 (KB, Resident Set Size)
TTY연결된 터미널 (?: 터미널 없음)
STAT프로세스 상태
START시작 시간
TIME누적 CPU 사용 시간
COMMAND실행 명령

System V 스타일

ps -ef
# UID        PID  PPID  C STIME TTY          TIME CMD
# root         1     0  0 Jan15 ?        00:00:08 /sbin/init
# user      1234  1100  1 10:30 pts/0    00:00:15 python app.py

커스텀 포맷 (-o)

# 원하는 열만 선택
ps -eo pid,ppid,user,%cpu,%mem,stat,cmd
ps -eo pid,ppid,ni,pri,stat,cmd          # nice값, 우선순위 포함
 
# 정렬
ps -eo pid,%cpu,%mem,cmd --sort=-%cpu    # CPU 사용률 내림차순
ps -eo pid,%cpu,%mem,cmd --sort=-%mem    # 메모리 사용률 내림차순
 
# 특정 프로세스
ps -p 1234                               # PID로 조회
ps -u username                           # 특정 사용자의 프로세스
ps -C nginx                              # 명령 이름으로 조회
 
# 스레드 표시
ps -eLf                                  # 모든 스레드 포함
ps -p 1234 -T                            # 특정 프로세스의 스레드

top - 실시간 프로세스 모니터링

top

화면 구성:

top - 10:30:45 up 15 days,  3:22,  2 users,  load average: 0.52, 0.38, 0.25
Tasks: 312 total,   1 running, 310 sleeping,   0 stopped,   1 zombie
%Cpu(s):  5.2 us,  1.3 sy,  0.0 ni, 93.0 id,  0.3 wa,  0.0 hi,  0.2 si,  0.0 st
MiB Mem :  16384.0 total,   8192.0 free,   4096.0 used,   4096.0 buff/cache
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.  11264.0 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1234 user      20   0  412356  98765  12345 S   5.2  0.6   0:15.30 python
약어설명
us사용자 공간 CPU
sy커널 공간 CPU
ninice로 변경된 프로세스
ididle (유휴)
waI/O 대기
hi하드웨어 인터럽트
si소프트웨어 인터럽트
ststeal time (가상화 환경)

인터랙티브 명령:

동작
h도움말
q종료
Space즉시 갱신
k프로세스 종료 (kill)
rnice 값 변경 (renice)
M메모리 사용률 순 정렬
PCPU 사용률 순 정렬 (기본)
TCPU 시간 순 정렬
NPID 순 정렬
1각 CPU 코어별 사용률 표시 토글
c전체 명령줄 표시 토글
H스레드 표시 토글
V트리 형태 표시
u특정 사용자 필터
d / s갱신 간격 변경
W현재 설정 저장 (~/.toprc)
# 배치 모드 (스크립트에서 사용)
top -bn1                              # 1회만 출력
top -bn1 | head -20                   # 상위 프로세스만
 
# 특정 프로세스만 모니터링
top -p 1234,5678
 
# 갱신 간격 지정
top -d 0.5                            # 0.5초마다 갱신

htop - 향상된 실시간 모니터링

top의 개선 버전. 색상, 스크롤, 마우스 지원, 트리 뷰 등.

htop
# F1: 도움말  F2: 설정  F3: 검색  F4: 필터
# F5: 트리 뷰  F6: 정렬  F9: 시그널  F10: 종료
 
# 설치
# Debian/Ubuntu: sudo apt install htop
# Red Hat/CentOS: sudo yum install htop

pgrep - 패턴으로 PID 검색

pgrep nginx                          # nginx 프로세스 PID 목록
pgrep -u root                        # root 사용자 프로세스
pgrep -f "python app.py"             # 전체 명령줄에서 매칭 (-f: full)
pgrep -l nginx                       # PID와 프로세스 이름 함께
pgrep -a nginx                       # PID와 전체 명령줄
pgrep -c nginx                       # 매칭 프로세스 수
pgrep -n nginx                       # 가장 최근 시작된 PID
pgrep -o nginx                       # 가장 오래된 PID

3. 프로세스 제어 (시그널)

시그널 개요

시그널은 프로세스에 비동기적으로 전달되는 소프트웨어 인터럽트다. 프로세스 간 통신이나 커널에서 프로세스로 이벤트를 알리는 데 사용된다.

주요 시그널

번호이름기본 동작설명처리 가능
1SIGHUP종료터미널 연결 끊김. 데몬의 설정 재로드에도 사용O
2SIGINT종료키보드 인터럽트 (Ctrl+C)O
3SIGQUIT코어 덤프 + 종료키보드 종료 (Ctrl+\)O
9SIGKILL종료강제 종료. 무시/처리 불가. 커널이 직접 처리X
15SIGTERM종료정상 종료 요청 (기본 시그널). 프로세스가 정리 후 종료 가능O
18SIGCONT재개정지된 프로세스 재개O
19SIGSTOP정지프로세스 정지. 무시/처리 불가.X
20SIGTSTP정지터미널 정지 (Ctrl+Z). SIGSTOP과 달리 처리 가능O
10SIGUSR1종료사용자 정의 시그널 1O
12SIGUSR2종료사용자 정의 시그널 2O
11SIGSEGV코어 덤프 + 종료세그멘테이션 폴트 (잘못된 메모리 접근)O
13SIGPIPE종료끊어진 파이프에 쓰기O
14SIGALRM종료alarm() 타이머 만료O
17SIGCHLD무시자식 프로세스 종료/정지 시 부모에게 전달O

시그널 번호는 아키텍처에 따라 다를 수 있다. 위 번호는 x86_64 Linux 기준.

kill - 시그널 전송

kill PID                             # SIGTERM(15) 전송 (기본)
kill -15 PID                         # SIGTERM 명시적
kill -SIGTERM PID                    # 이름으로 지정
kill -9 PID                          # SIGKILL - 강제 종료 (최후의 수단)
kill -KILL PID                       # 위와 동일
kill -1 PID                          # SIGHUP - 설정 재로드 (데몬)
kill -0 PID                          # 프로세스 존재 여부 확인 (시그널 전송 안 함)
 
# 여러 프로세스
kill 1234 5678 9012
 
# 시그널 목록
kill -l
# 1) SIGHUP  2) SIGINT  3) SIGQUIT  ... 15) SIGTERM  ...
 
# 프로세스 그룹 전체에 시그널 (음수 PID)
kill -TERM -1234                     # PGID 1234 전체

종료 순서 (권장):

  1. kill PID (SIGTERM) - 프로세스에 정상 종료 요청
  2. 잠시 대기 (프로세스가 정리 작업 수행)
  3. 여전히 살아있으면 kill -9 PID (SIGKILL) - 강제 종료

kill -9를 바로 사용하면 프로세스가 임시 파일 정리, 데이터 저장 등의 정리 작업을 수행할 수 없다. 항상 SIGTERM을 먼저 시도하라.

killall - 이름으로 종료

killall nginx                        # 'nginx'라는 이름의 모든 프로세스에 SIGTERM
killall -9 nginx                     # 강제 종료
killall -u user                      # 특정 사용자의 모든 프로세스
killall -i nginx                     # 확인 후 종료
killall -w nginx                     # 모두 종료될 때까지 대기

pkill - 패턴으로 종료

pgrep과 동일한 패턴 매칭으로 시그널 전송.

pkill nginx                          # 이름 패턴 매칭
pkill -f "python app.py"             # 전체 명령줄 매칭
pkill -9 -f "zombie_script"          # 강제 종료
pkill -u user                        # 특정 사용자 프로세스
pkill -t pts/0                       # 특정 터미널 프로세스
pkill -P 1234                        # 특정 PPID의 자식 프로세스

4. 작업 제어 (Job Control)

개념

셸에서 실행하는 명령을 작업(job)이라 하며, 포그라운드(전면)와 백그라운드(후면)에서 실행할 수 있다.

기본 조작

조작설명
command &백그라운드에서 실행
Ctrl+Z현재 포그라운드 작업을 정지(SIGTSTP)
Ctrl+C현재 포그라운드 작업에 인터럽트(SIGINT) - 보통 종료
jobs현재 셸의 작업 목록
fg가장 최근 백그라운드/정지 작업을 포그라운드로
fg %N작업 번호 N을 포그라운드로
bg가장 최근 정지된 작업을 백그라운드에서 재개
bg %N작업 번호 N을 백그라운드에서 재개

실전 예시

# 백그라운드 실행
sleep 300 &
# [1] 12345     <- 작업번호 1, PID 12345
 
# 작업 목록 확인
jobs
# [1]+  Running    sleep 300 &
# [2]-  Stopped    vim file.txt
 
# jobs 옵션
jobs -l                              # PID도 표시
jobs -r                              # Running만
jobs -s                              # Stopped만
 
# 포그라운드로 가져오기
fg %1                                # 작업 1을 포그라운드로
 
# 정지 후 백그라운드로
# (포그라운드에서 Ctrl+Z 누름)
# [1]+  Stopped    python train.py
bg %1                                # 백그라운드에서 계속 실행
 
# 작업 종료
kill %1                              # 작업 번호로 종료

disown - 셸로부터 작업 분리

셸 종료 시 SIGHUP이 전달되어 백그라운드 작업도 종료되는데, disown으로 이를 방지할 수 있다.

long_command &
disown                               # 가장 최근 백그라운드 작업을 작업 목록에서 제거
disown %1                            # 특정 작업
disown -a                            # 모든 작업
 
# disown 후에는 jobs에서 보이지 않지만, 프로세스는 계속 실행
# 다만 stdout/stderr가 터미널에 연결되어 있으면 터미널 종료 시 에러 발생 가능
# -> nohup을 사용하는 것이 더 안전

5. 우선순위: nice, renice

nice 값 개념

  • 범위: -20 (최고 우선순위) ~ 19 (최저 우선순위)
  • 기본값: 0
  • 일반 사용자는 nice 값을 높이기(우선순위 낮추기)만 가능
  • root만 nice 값을 낮출(우선순위 높이기) 수 있다
nice 값과 실제 우선순위(PR)의 관계:
PR = 20 + nice
nice -20 -> PR 0  (최고 우선순위)
nice  0  -> PR 20 (기본)
nice 19  -> PR 39 (최저 우선순위)

nice - 우선순위를 지정하여 프로세스 시작

nice command                         # nice 10으로 실행 (기본)
nice -n 15 command                   # nice 15로 실행
nice -n -5 command                   # nice -5로 실행 (root 필요)
nice -n 19 ./cpu_intensive_task.sh   # 최저 우선순위로 실행
 
# 확인
ps -eo pid,ni,cmd | grep command

renice - 실행 중인 프로세스 우선순위 변경

renice 10 -p 1234                    # PID 1234의 nice를 10으로
renice -5 -p 1234                    # nice를 -5로 (root 필요)
renice 15 -u username                # 특정 사용자의 모든 프로세스
renice 10 -g groupname               # 특정 그룹의 모든 프로세스
 
# top에서도 'r' 키로 renice 가능

6. 백그라운드 실행

nohup - 셸 종료 후에도 실행 지속

SIGHUP을 무시하도록 하여, 터미널/SSH 세션 종료 후에도 프로세스가 계속 실행된다.

nohup command &
# nohup: ignoring input and appending output to 'nohup.out'
 
nohup command > output.log 2>&1 &    # 출력을 지정 파일로
nohup python train.py > train.log 2>&1 &
 
# nohup은:
# 1. SIGHUP을 무시하도록 설정
# 2. stdout이 터미널이면 nohup.out으로 리다이렉트
# 3. stdin을 /dev/null로 리다이렉트

nohup vs disown vs screen/tmux

도구SIGHUP 보호출력 리다이렉트다시 연결 가능용도
nohupO (시작 시)nohup.outX단순 백그라운드 실행
disownO (실행 후)X (수동 필요)X이미 실행 중인 작업 분리
screen/tmuxOO (가상 터미널)O세션 유지, 다시 연결

screen/tmux 기본

# tmux (권장, 더 현대적)
tmux                                 # 새 세션 시작
tmux new -s session_name             # 이름 있는 세션
tmux ls                              # 세션 목록
tmux attach -t session_name          # 세션에 다시 연결
tmux detach                          # 세션 분리 (Ctrl+B, d)
 
# tmux 내부 키 바인딩 (Ctrl+B가 prefix):
# Ctrl+B, d  - detach (분리)
# Ctrl+B, c  - 새 창
# Ctrl+B, n  - 다음 창
# Ctrl+B, p  - 이전 창
# Ctrl+B, %  - 세로 분할
# Ctrl+B, "  - 가로 분할
# Ctrl+B, 방향키 - 패인 이동
 
# screen
screen                               # 새 세션
screen -S name                       # 이름 있는 세션
screen -ls                           # 세션 목록
screen -r name                       # 세션에 다시 연결
# Ctrl+A, d  - detach

7. 데몬, 좀비, 고아 프로세스

데몬 프로세스 (Daemon)

터미널에 연결되지 않고 백그라운드에서 실행되는 시스템 서비스 프로세스. 관례적으로 이름 끝에 d가 붙는다.

# 데몬 예시: sshd, httpd, mysqld, crond, systemd
 
# 데몬의 특징:
# - 부모 프로세스가 보통 PID 1 (init/systemd)
# - 제어 터미널(TTY)이 없음 (ps 출력에서 '?')
# - 표준 입출력이 /dev/null이나 로그 파일로 리다이렉트
# - 보통 설정 파일 변경 후 SIGHUP으로 재로드
 
# systemctl로 데몬 관리 (systemd 기반)
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
sudo systemctl reload nginx          # 설정 재로드 (무중단)
sudo systemctl status nginx          # 상태 확인
sudo systemctl enable nginx          # 부팅 시 자동 시작
sudo systemctl disable nginx         # 자동 시작 해제

좀비 프로세스 (Zombie)

자식 프로세스가 종료되었지만, 부모 프로세스가 wait() 시스템 콜로 종료 상태를 회수하지 않은 프로세스.

# ps에서 'Z' 상태 또는 'defunct'로 표시
ps aux | grep 'Z'
# USER  PID  ...  STAT  ...  COMMAND
# user  1234 ...  Z     ...  [process_name] <defunct>
 
# 좀비 프로세스의 특징:
# - CPU나 메모리를 거의 사용하지 않음 (프로세스 테이블 엔트리만 차지)
# - kill -9로도 종료 불가 (이미 종료된 상태)
# - 부모 프로세스가 wait()하거나 종료되어야 사라짐
 
# 좀비 해결 방법:
# 1. 부모 프로세스에 SIGCHLD 전송 (wait() 유도)
kill -SIGCHLD PPID
 
# 2. 부모 프로세스 종료 (좀비가 init에 입양되어 자동 회수)
kill PPID
 
# 좀비 수 확인
ps aux | awk '$8 ~ /Z/ {count++} END {print count}'
# 또는 top 상단에서 확인: "0 zombie"

고아 프로세스 (Orphan)

부모 프로세스가 자식보다 먼저 종료된 경우, 자식 프로세스는 고아가 된다. 커널이 자동으로 PID 1(init/systemd)을 새 부모로 재지정(re-parent)한다.

# 고아 프로세스는 문제가 되지 않음
# init/systemd가 자동으로 wait()하여 정리
 
# 확인: PPID가 1인 프로세스 (모두 고아는 아님, 정상 데몬도 포함)
ps -eo pid,ppid,cmd | awk '$2 == 1'

8. /proc/[pid]/ 디렉토리 활용

각 프로세스는 /proc/PID/ 디렉토리에 다양한 런타임 정보를 노출한다.

주요 파일

PID=$$   # 현재 셸 PID (예시용)
 
# cmdline - 실행 명령줄 (인자를 NULL 문자로 구분)
cat /proc/$PID/cmdline | tr '\0' ' '
echo
# /bin/bash --login
 
# status - 프로세스 상태 요약 (사람이 읽기 좋은 형태)
cat /proc/$PID/status
# Name:   bash
# Umask:  0022
# State:  S (sleeping)
# Tgid:   1234      (Thread Group ID = PID)
# Pid:    1234
# PPid:   1100
# Uid:    1000 1000 1000 1000
# Gid:    1000 1000 1000 1000
# VmPeak: 12345 kB  (가상 메모리 최대값)
# VmSize: 12000 kB  (현재 가상 메모리)
# VmRSS:  5000 kB   (물리 메모리)
# Threads: 1
 
# fd/ - 열린 파일 디스크립터
ls -la /proc/$PID/fd/
# lrwx------ 1 user user 0 ... 0 -> /dev/pts/0     (stdin)
# lrwx------ 1 user user 0 ... 1 -> /dev/pts/0     (stdout)
# lrwx------ 1 user user 0 ... 2 -> /dev/pts/0     (stderr)
# lr-x------ 1 user user 0 ... 3 -> /path/to/open/file
# l-wx------ 1 user user 0 ... 4 -> /path/to/log
 
# 열린 파일 디스크립터 수
ls /proc/$PID/fd/ | wc -l
 
# maps - 메모리 매핑 (가상 주소 공간 레이아웃)
cat /proc/$PID/maps
# 주소범위           권한 오프셋  장치  inode  경로
# 55a4b6c00000-55a4b6c28000 r-xp 00000000 08:01 1234  /bin/bash
# 7f8d12345000-7f8d12567000 r-xp 00000000 08:01 5678  /lib/x86_64-linux-gnu/libc-2.31.so
# 7ffd45600000-7ffd45621000 rw-p 00000000 00:00 0     [stack]
# 7ffd456fe000-7ffd45702000 r--p 00000000 00:00 0     [vvar]
# 7ffd45702000-7ffd45704000 r-xp 00000000 00:00 0     [vdso]
 
# environ - 환경 변수 (NULL 문자로 구분)
cat /proc/$PID/environ | tr '\0' '\n'
# HOME=/home/user
# PATH=/usr/local/bin:/usr/bin:/bin
# SHELL=/bin/bash
# ...
 
# exe - 실행 파일 심볼릭 링크
readlink /proc/$PID/exe
# /bin/bash
 
# cwd - 현재 작업 디렉토리 심볼릭 링크
readlink /proc/$PID/cwd
 
# io - I/O 통계
cat /proc/$PID/io
# rchar: 12345678     (읽은 바이트)
# wchar: 9876543      (쓴 바이트)
# read_bytes: 1234567 (실제 디스크 읽기)
# write_bytes: 987654 (실제 디스크 쓰기)
 
# limits - 리소스 제한
cat /proc/$PID/limits
# Max open files            1024                 1048576              files
# Max processes             63338                63338                processes

9. lsof, strace

lsof - 열린 파일 나열

List Open Files. Linux에서 “모든 것은 파일”이므로, 일반 파일뿐 아니라 소켓, 파이프, 장치 등도 포함한다.

# 모든 열린 파일 (매우 많음)
lsof
 
# 특정 프로세스
lsof -p 1234                         # PID로
lsof -c nginx                        # 명령 이름으로
 
# 특정 사용자
lsof -u username
 
# 특정 파일을 사용하는 프로세스
lsof /var/log/syslog
 
# 특정 디렉토리 내 파일을 사용하는 프로세스
lsof +D /var/log/
 
# 네트워크 연결
lsof -i                              # 모든 네트워크 연결
lsof -i :80                          # 포트 80 사용 프로세스
lsof -i :22                          # SSH 포트
lsof -i TCP                          # TCP 연결만
lsof -i TCP:80                       # TCP 포트 80
lsof -i @192.168.1.1                 # 특정 IP와의 연결
 
# 삭제되었지만 아직 열려있는 파일 (디스크 공간 점유)
lsof +L1
# 이 파일들은 프로세스가 종료되거나 fd를 닫아야 디스크 공간이 해제됨
 
# 실전: 특정 포트를 점유한 프로세스 찾아서 종료
lsof -i :8080 | awk 'NR>1 {print $2}' | xargs kill
 
# 실전: 마운트 해제 불가 시 사용 중인 프로세스 확인
lsof +D /mnt/usb/

strace - 시스템 콜 추적

프로세스가 호출하는 시스템 콜(커널 API)을 추적한다. 디버깅에 매우 유용하다.

# 명령어 실행과 함께 추적
strace ls /tmp
# execve("/bin/ls", ["ls", "/tmp"], ...) = 0
# openat(AT_FDCWD, "/tmp", O_RDONLY|O_NONBLOCK|O_DIRECTORY) = 3
# getdents64(3, ...) = 456
# write(1, "file1  file2  file3\n", 20) = 20
# close(3) = 0
# exit_group(0) = ?
 
# 실행 중인 프로세스에 연결
strace -p 1234
 
# 주요 옵션
strace -e trace=open,read,write ls    # 특정 시스템 콜만 추적
strace -e trace=network command       # 네트워크 관련만
strace -e trace=file command          # 파일 관련만
strace -e trace=process command       # 프로세스 관련만 (fork, exec, exit)
strace -c command                     # 시스템 콜 통계 요약
strace -f command                     # fork된 자식 프로세스도 추적
strace -t command                     # 타임스탬프 출력
strace -T command                     # 각 시스템 콜 소요 시간
strace -o output.txt command          # 출력을 파일로
 
# 실전: 프로그램이 어떤 파일을 열려고 하는지 확인
strace -e trace=openat command 2>&1 | grep -v ENOENT
 
# 실전: 프로그램이 멈춘 원인 파악
strace -p $(pgrep stuck_process) 2>&1 | head -20

10. 리소스 제한: ulimit

셸과 그 자식 프로세스의 리소스 사용 제한을 설정한다.

확인

ulimit -a                            # 모든 제한 값 확인 (soft limit)
ulimit -Ha                           # 하드 리밋 확인
 
# 주요 항목별 확인
ulimit -n                            # 열 수 있는 파일 수 (open files)
ulimit -u                            # 최대 프로세스 수
ulimit -s                            # 스택 크기 (KB)
ulimit -v                            # 가상 메모리 (KB)
ulimit -f                            # 파일 크기 제한 (blocks)
ulimit -c                            # 코어 덤프 크기 (blocks, 0=비활성)

Soft Limit vs Hard Limit

구분설명
Soft limit현재 적용되는 제한. 사용자가 hard limit 이하로 변경 가능
Hard limitsoft limit의 상한선. root만 올릴 수 있다
# soft limit 확인/설정
ulimit -Sn                           # 열린 파일 수 soft limit
ulimit -Sn 4096                      # soft limit 변경
 
# hard limit 확인/설정 (root 필요)
ulimit -Hn                           # hard limit
ulimit -Hn 65536                     # hard limit 변경 (root)

영구 설정

# /etc/security/limits.conf
# 형식: <domain> <type> <item> <value>
#
# *         soft    nofile    4096     # 모든 사용자 soft limit
# *         hard    nofile    65536    # 모든 사용자 hard limit
# root      soft    nofile    65536    # root soft limit
# @admin    hard    nproc     1024     # admin 그룹 hard limit
# user1     soft    core      unlimited # user1 코어 덤프 무제한
 
# /etc/security/limits.d/ 디렉토리에 개별 파일로도 설정 가능
 
# systemd 서비스의 제한은 유닛 파일에서 설정
# [Service]
# LimitNOFILE=65536
# LimitNPROC=4096

실전 활용

# 코어 덤프 활성화 (디버깅용)
ulimit -c unlimited
./buggy_program
# 코어 파일 생성됨 -> gdb로 분석 가능
 
# 웹 서버 등에서 파일 디스크립터 부족 시
ulimit -n 65536
# 또는 영구 설정 (/etc/security/limits.conf)
 
# 포크 폭탄 방지 (프로세스 수 제한)
ulimit -u 256
 
# 포크 폭탄 예시 (절대 실행 금지!)
# :(){ :|:& };:
# 위 명령은 자기 자신을 무한 fork하여 시스템을 먹통으로 만든다
# ulimit -u 로 사전 방지 가능