리눅스 시스템 기초 · 03. 서비스 · 프로세스 관리 — 이 영역 글의 "N편"은 제목 앞 번호(영역 내 번호)다. 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.

서비스 · 프로세스 관리 01 / 50 · Part 1. 프로세스 기초
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (systemd로 부팅한 Docker 격리 컨테이너, 테스트 계정 analyst)

1. 들어가며

「서비스 · 프로세스 관리」 시리즈의 첫 글이다. 이 시리즈는 프로세스가 만들어지고 실행되고 종료되는 원리에서 출발해 시그널, 자원 제한, systemd 서비스, cron·timer 스케줄링을 차례로 다루고, 마지막 Part 5에서는 보안관제(SOC) 관점에서 의심 프로세스와 지속성(persistence) 흔적을 탐지 하는 실습으로 마무리한다.

첫 주제는 가장 기초적이지만 가장 자주 헷갈리는 구분인 프로그램과 프로세스의 차이 다. 관제 화면에서 "의심 프로세스"를 보고했을 때 "그 파일은 지금 어디에 있나요?", "파일을 지우면 끝나나요?"라는 질문에 정확히 답하려면 이 구분이 먼저 서 있어야 한다.

「리눅스 시스템 기초 31편」이 프로세스를 개괄했다면, 이 시리즈는 생성(02편), 트리(03편), 상태(04편), /proc(05편)으로 나누어 각각 깊게 다룬다.


2. 핵심 개념

2-1. 한 줄 정의

구분프로그램 (Program)프로세스 (Process)
정체디스크에 저장된 실행 파일메모리에 올라가 실행 중인 프로그램의 인스턴스
상태정적 (움직이지 않음)동적 (생성 → 실행 → 대기 → 종료)
식별자경로, inodePID
수명삭제하기 전까지 유지종료되면 사라짐 (재부팅 시 모두 사라짐)
개수하나같은 프로그램으로 여러 개 생성 가능
확인 방법ls -l, file, statps, pgrep, /proc/PID

비유하면 프로그램은 요리 레시피 이고, 프로세스는 그 레시피로 지금 요리하고 있는 주방 이다. 레시피 한 장으로 주방 여러 곳이 동시에 요리할 수 있고, 각 주방은 자기 재료(메모리)와 도구(파일 디스크립터)를 따로 가진다.

2-2. 프로세스가 가지는 것

커널은 프로세스마다 task_struct라는 구조체로 다음 정보를 관리한다.

항목설명어디서 보나
PID / PPID자신과 부모의 번호ps -o pid,ppid
자격 증명실행 계정 UID·GID (real/effective)/proc/PID/status의 Uid:
메모리 공간코드, 데이터, 힙, 스택, 공유 라이브러리/proc/PID/maps
실행 파일어떤 프로그램에서 왔는가/proc/PID/exe
열린 파일파일·소켓·파이프 (파일 디스크립터)/proc/PID/fd/
작업 디렉터리상대경로의 기준/proc/PID/cwd
환경변수·인자실행 시 전달된 값/proc/PID/environ, cmdline
상태R, S, D, T, Zps -o stat

2-3. 스레드와의 차이 (짧게)

스레드는 한 프로세스 안에서 메모리를 공유하는 실행 흐름 이다. Linux 커널은 스레드도 task로 관리하므로 각 스레드에 TID가 붙지만, 같은 프로세스의 스레드는 PID(TGID)를 공유한다. ps -eLf나 /proc/PID/task/에서 확인할 수 있다. 이 시리즈에서 "프로세스"는 특별한 언급이 없으면 스레드 그룹 전체를 뜻한다.


3. 동작 원리

프로그램(디스크)과 프로세스(메모리)의 관계

프로그램이 프로세스가 되는 흐름은 다음과 같다.

[디스크] /usr/bin/sleep (ELF 실행 파일)
    ↓  셸이 fork()로 자기 복제본(자식)을 만든다
[자식 프로세스] 아직 bash 코드를 가진 상태
    ↓  execve("/usr/bin/sleep") — 메모리를 sleep 코드로 교체
[프로세스 PID 194] 커널이 PID·메모리·fd·자격 증명을 관리
    ↓  실행이 끝나면 exit() → 부모가 wait()로 회수
[종료] PID 반환, 메모리 해제 — 디스크의 프로그램은 그대로

핵심은 두 가지다.

  1. 실행 = 메모리에 매핑 — 커널은 실행 파일 전체를 복사하지 않고 필요한 부분을 메모리에 매핑 한다. /proc/PID/maps에 /usr/bin/sleep이 여러 줄 나타나는 이유다.
  2. 파일과 프로세스는 참조 관계 — 프로세스는 실행 파일의 inode를 붙잡고 있다. 그래서 실행 중에 파일 이름을 지워도(rm) inode는 바로 해제되지 않고 프로세스는 계속 돈다. fork·exec 과정은 02편에서 strace로 직접 확인한다.

4. 명령어 실습

# 1) 프로그램 (디스크의 파일) 확인
ls -l /usr/bin/sleep
file /usr/bin/sleep

# 2) 같은 프로그램으로 프로세스 두 개 실행
sleep 300 & sleep 300 &
pgrep -a sleep
for p in $(pgrep -x sleep); do echo "PID=$p exe=$(readlink /proc/$p/exe) ..."; done
ps -o pid,ppid,stat,lstart,cmd -C sleep

# 3) 프로세스를 종료해도 프로그램은 남는다
kill %1 %2
pgrep -a sleep || echo "sleep 프로세스 없음"; ls -l /usr/bin/sleep

# 4) (Ubuntu) 실행 파일을 지워도 프로세스는 남는다
cp /usr/bin/sleep ~/mysleep && ~/mysleep 300 &
ls -l /proc/$P/exe
rm ~/mysleep
ls -l /proc/$P/exe      # → '(deleted)' 표시

4)의 삭제 실습은 반드시 자기 홈 디렉터리의 복사본 으로 한다. 시스템 바이너리(/usr/bin/*)를 지우는 실습은 하지 않는다.


5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · analyst@rocky9-lab — 같은 프로그램, 서로 다른 프로세스

실제 실행 결과 — Ubuntu 24.04.5 · analyst@ubuntu-lab — 프로그램 파일을 바꿔도 실행 중인 프로세스는 유지

텍스트 원본(실제 출력):

[analyst@rocky9-lab ~]$ ls -l /usr/bin/sleep
-rwxr-xr-x 1 root root 32224 Sep 10 16:13 /usr/bin/sleep
[analyst@rocky9-lab ~]$ file /usr/bin/sleep
/usr/bin/sleep: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=933051efe29ce3924d09ee266336e9b2366ddd7f, for GNU/Linux 3.2.0, stripped
[analyst@rocky9-lab ~]$ sleep 300 & sleep 300 &
[analyst@rocky9-lab ~]$ pgrep -a sleep
194 sleep 300
195 sleep 300
[analyst@rocky9-lab ~]$ for p in $(pgrep -x sleep); do echo "PID=$p exe=$(readlink /proc/$p/exe) ppid=$(awk '/^PPid/{print $2}' /proc/$p/status) vmrss=$(awk '/^VmRSS/{print $2$3}' /proc/$p/status)"; done
PID=194 exe=/usr/bin/sleep ppid=169 vmrss=1944kB
PID=195 exe=/usr/bin/sleep ppid=169 vmrss=1988kB
[analyst@rocky9-lab ~]$ ps -o pid,ppid,stat,lstart,cmd -C sleep
    PID    PPID STAT                  STARTED CMD
    194     169 S+   Thu Sep 24 09:38:17 2026 sleep 300
    195     169 S+   Thu Sep 24 09:38:17 2026 sleep 300
[analyst@rocky9-lab ~]$ kill %1 %2; wait 2>/dev/null
[analyst@rocky9-lab ~]$ pgrep -a sleep || echo "sleep 프로세스 없음 (프로그램 파일은 그대로)"; ls -l /usr/bin/sleep
sleep 프로세스 없음 (프로그램 파일은 그대로)
-rwxr-xr-x 1 root root 32224 Sep 10 16:13 /usr/bin/sleep
analyst@ubuntu-lab:~$ cp /usr/bin/sleep ~/mysleep && ~/mysleep 300 &
analyst@ubuntu-lab:~$ sleep 0.3; P=$(pgrep -x mysleep); echo "PID=$P"
PID=213
analyst@ubuntu-lab:~$ ls -l /proc/$P/exe
lrwxrwxrwx 1 analyst analyst 0 Sep 24 09:38 /proc/213/exe -> /home/analyst/mysleep
analyst@ubuntu-lab:~$ rm ~/mysleep; ls ~/mysleep
ls: cannot access '/home/analyst/mysleep': No such file or directory
analyst@ubuntu-lab:~$ ls -l /proc/$P/exe
lrwxrwxrwx 1 analyst analyst 0 Sep 24 09:38 /proc/213/exe -> '/home/analyst/mysleep (deleted)'
analyst@ubuntu-lab:~$ ps -o pid,stat,cmd -p $P
    PID STAT CMD
    213 S+   /home/analyst/mysleep 300
analyst@ubuntu-lab:~$ kill $P

6. 결과 해석

관찰의미
file 결과가 ELF 64-bit LSB pie executable디스크의 sleep은 실행 가능한 파일 일 뿐이다. 이 상태에서는 CPU도 메모리도 쓰지 않는다
PID 194, 195 두 개 생성같은 프로그램에서 독립된 프로세스 두 개 가 만들어졌다
두 프로세스 모두 exe=/usr/bin/sleep, ppid=169같은 실행 파일, 같은 부모(내 bash)에서 왔다. 그러나 PID와 메모리(VmRSS 1944kB / 1988kB)는 각자 가진다
STAT S+S = 대기(sleep) 중, + = 터미널의 포그라운드 프로세스 그룹. 상태 코드는 04편에서 자세히 본다
kill 후 pgrep 결과 없음, 파일은 그대로프로세스는 사라졌지만 프로그램은 디스크에 남는다
Ubuntu: rm 후에도 PID 213 유지파일 이름만 사라졌고, 프로세스가 inode를 잡고 있어 실행은 계속된다
/proc/213/exe -> '/home/analyst/mysleep (deleted)'커널이 "원본 경로는 삭제됨"을 표시한다. 관제에서 매우 중요한 지표다

ls는 터미널로 출력할 때 공백이 들어간 이름을 작은따옴표로 감싸서 보여 준다(coreutils 8.25 이후 기본 동작). 그래서 '... (deleted)'처럼 보인다. 스크립트에서 readlink /proc/PID/exe로 읽으면 따옴표 없이 /home/analyst/mysleep (deleted)가 나온다.


7. 보안 관점

주제내용
파일 삭제 ≠ 위협 제거악성 파일을 지워도 이미 실행된 프로세스는 메모리에서 계속 동작 한다. 대응 순서는 "프로세스 정보 수집 → 종료 → 파일·지속성 제거"다
증거 복구삭제된 실행 파일도 프로세스가 살아 있는 동안에는 cp /proc/PID/exe /evidence/sample.bin으로 복사해 낼 수 있다. 프로세스를 먼저 죽이면 이 기회가 사라진다
이름 위장프로세스 이름(comm, cmdline)은 바꿀 수 있지만 /proc/PID/exe는 커널이 관리하는 실제 경로다. 이름보다 exe 경로를 신뢰 한다 (43편)
권한프로세스는 실행한 계정(UID)의 권한으로 동작한다. 같은 프로그램이라도 root로 실행하면 root 권한 프로세스가 된다

8. 보안관제 관점

[Detection]  EDR/스크립트 경보: /proc/*/exe 가 '(deleted)' 인 프로세스 발견
     ↓
[확인]       ls -l /proc/PID/exe · tr '\0' ' ' < /proc/PID/cmdline · ps -o user,ppid,lstart -p PID
     ↓
[증거 확보]  cp /proc/PID/exe  → sha256sum → 샘플 보관
             ls -l /proc/PID/fd · ss -tnp | grep "pid=PID"
     ↓
[판단]       패키지 업데이트 후 재시작 안 한 정상 프로세스인가? 아니면 /tmp·홈에서 실행 후 자기 삭제한 악성인가?
     ↓
[Response]   프로세스 종료 → 지속성(cron·systemd) 점검 → 보고
관점내용
정상 오탐dnf update/apt upgrade로 라이브러리·바이너리가 교체된 뒤 재시작하지 않은 서비스도 (deleted)로 보인다. 경로가 /usr/...이고 패키지 업데이트 시각과 맞으면 정상일 가능성이 높다
고위험/tmp, /dev/shm, /var/tmp, 사용자 홈에서 실행된 뒤 삭제된 프로세스
기록 항목PID, PPID, UID, 시작 시각(lstart), exe, cmdline, 네트워크 연결, 해시

9. 실무에서 자주 발생하는 실수

실수결과예방
악성 파일부터 rm프로세스는 살아 있고 샘플 확보 기회도 줄어든다프로세스 정보·exe 복사 → 종료 → 삭제 순서
프로세스 이름만 보고 판단sshd, kworker로 위장한 프로세스를 놓친다/proc/PID/exe와 PPID를 함께 확인
ps 결과를 PID만 기록PID는 재사용되므로 나중에 다른 프로세스와 혼동PID + 시작 시각 + exe를 함께 기록
업데이트 후 (deleted)를 모두 악성으로 보고과도한 오탐경로·패키지 업데이트 이력과 교차 확인

10. 실습 체크리스트

[ ] ls -l, file 로 실행 파일(프로그램)의 정체를 확인했다
[ ] 같은 프로그램으로 PID가 다른 프로세스 2개를 만들었다
[ ] /proc/PID/exe 로 프로세스의 실제 실행 파일을 확인했다
[ ] 프로세스를 종료해도 프로그램 파일이 남는 것을 확인했다
[ ] 실행 중인 복사본을 삭제하고 '(deleted)' 표시를 확인했다
[ ] 파일 삭제가 위협 제거가 아닌 이유를 설명할 수 있다

11. 핵심 정리

  • 프로그램은 디스크의 정적 파일, 프로세스는 메모리에서 실행 중인 인스턴스 다.
  • 하나의 프로그램으로 여러 프로세스를 만들 수 있고, 각각 PID·메모리·fd를 따로 가진다.
  • 프로세스는 실행 파일의 inode를 참조하므로, 파일을 지워도 프로세스는 계속 돈다.
  • /proc/PID/exe는 커널이 알려 주는 실제 실행 파일 경로 이며, 삭제되면 (deleted)가 붙는다.
  • 침해 대응은 증거 확보(exe 복사) → 프로세스 종료 → 파일·지속성 제거 순서로 한다.

12. 다음 편 예고

다음 글 「02. 프로세스 생성 원리 (fork·exec)」 에서는 셸이 명령어를 실행할 때 내부에서 일어나는 fork()(자기 복제)와 execve()(프로그램 교체)를 strace로 직접 추적 한다. exec가 PID를 바꾸지 않는다는 사실이 왜 보안 로그 분석에서 중요한지도 확인한다.


참고 자료


시리즈 이동

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글