Step 26. 프로세스 관리 — 보고, 찾고, 신호를 보내라
Level 0 — 컴퓨터 조작과 구조의 이해 | 난이도 ★★☆☆☆ | 예상 소요 시간 3시간
전제: Step 18~21의 리눅스 기본 명령을 쓸 수 있어야 합니다. 우분투 가상머신(또는 WSL 우분투)이 필요합니다.
- 준비물: 우분투 터미널. 새로 설치하는 것은 없습니다.
- 주의: 오늘 실습은 대부분 조회이지만, 프로세스를 종료하는
kill이 나옵니다. 우리가 직접 만든 실험용 프로세스(sleep)에만 쓰세요. 다른 프로세스 번호에 함부로 kill을 내면 작업 중인 것이 날아가거나 시스템이 멈출 수 있습니다.
지금 이 순간에도 여러분의 우분투 안에서는 수십 개의 프로그램이 동시에 돌고 있습니다. 네트워크를 관리하는 것, 로그를 기록하는 것, 여러분의 터미널을 띄운 것 — 전부 각각이 살아 있는 실행 단위, 프로세스(process)입니다. 서버가 이상할 때 관리자가 제일 먼저 하는 일은 "지금 뭐가 돌고 있지?"를 보는 것이고, 침해 사고 조사의 첫 장도 "프로세스 목록 확보"입니다. 오늘은 프로세스를 보고, 만들고, 찾고, 끝내는 법을 배웁니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
- 실행 중인 프로세스의 목록을 보고 PID(번호)와 PPID(부모 번호)를 찾는다
&,jobs,fg,bg로 작업을 앞뒤로 오가며 실행한다- kill이 "죽이기"가 아니라 "시그널 보내기"임을 설명한다
- SIGTERM(15)과 SIGKILL(9)의 차이와 올바른 사용 순서를 말한다
top으로 CPU를 많이 쓰는 프로세스를 실시간으로 찾는다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | bash — 우분투 터미널 (가상머신 또는 WSL) |
| 오늘의 명령어 | ps aux(전체 목록), ps -ef(부모 번호 포함), jobs/bg/fg(작업 오가기), kill [PID](신호 보내기), top(실시간 감시) |
| 필요한 개념 | PID와 PPID, 시그널(SIGTERM·SIGKILL·SIGINT), 포그라운드와 백그라운드, 데몬 |
2-1. PID와 PPID — 프로세스의 번호표와 계보
모든 프로세스에는 태어날 때 고유 번호가 붙습니다. PID(Process ID)입니다. 그리고 "나를 실행시킨 부모 프로세스"의 번호인 PPID(Parent PID)도 함께 기록됩니다. Step 13에서 윈도우의 프로세스 계보를 추적해 봤죠. 같은 개념이 리눅스에도 있습니다.
이 계보가 보안에서 중요한 이유는 같습니다. 정상 프로그램은 예상 가능한 부모에게서 태어나는데, 악성코드는 이상한 부모에게서 태어나는 경우가 많기 때문입니다.
2-2. 시그널 — 프로세스에게 보내는 신호
리눅스에서 실행 중인 프로세스와 대화하는 방법이 시그널(signal)입니다. 초인종처럼 "띵동" 하고 의사를 전달하는 체계입니다. 대표적인 것들:
| 시그널 | 번호 | 의미 |
|---|---|---|
| SIGTERM | 15 | "정리하고 종료해 주세요" — 정중한 종료 요청. kill의 기본값 |
| SIGKILL | 9 | "즉시 소멸" — 거부 불가, 뒷정리 기회 없음 |
| SIGINT | 2 | Ctrl+C를 눌렀을 때 가는 신호 (인터럽트) |
| SIGHUP | 1 | "터미널 연결 끊김" — 데몬은 이걸 받으면 설정을 다시 읽는 관례가 있음 |
kill이라는 이름은 오해를 부릅니다. kill은 "죽이는 명령"이 아니라 시그널을 보내는 명령입니다. 다만 기본 시그널이 종료 요청(SIGTERM)이라 주로 죽이는 용도로 쓰일 뿐입니다.
2-3. 왜 -9가 마지막 수단인가
SIGTERM을 받은 프로세스는 "나가야겠다"고 판단하고 스스로 뒷정리를 합니다. 열린 파일을 닫고, 저장할 것을 저장하고, 네트워크 연결을 정돈합니다. 반면 SIGKILL(-9)은 커널이 프로세스를 그 자리에서 소멸시킵니다. 뒷정리 기회가 없으니 저장 못 한 데이터는 날아가고, 임시 파일은 널브러집니다.
그래서 순서는 항상 정해져 있습니다: ① 기본 kill(SIGTERM) → ② 잠시 기다렸다가 확인 → ③ 그래도 안 들으면 kill -9. 현장에서 kill -9를 첫 번째 선택지로 쓰는 것은 초보의 표식입니다.
2-4. 포그라운드와 백그라운드
터미널에서 명령을 치면 보통 그 명령이 끝날 때까지 프롬프트가 돌아오지 않습니다. 이것이 포그라운드(foreground, 전면) 실행입니다. 명령 뒤에 &를 붙이면 명령은 뒤에서 돌고 프롬프트는 즉시 돌아옵니다. 백그라운드(background, 후면) 실행입니다.
이미 앞에서 실행 중인 것을 뒤로내려면 Ctrl+Z(일시정지) 뒤 bg, 다시 앞으로 부를 때는 fg입니다. 그리고 jobs는 이 터미널에서 오가는 작업들의 명단을 보여 줍니다.
2-5. 데몬 — 묵묵히 상주하는 일꾼
데몬(daemon)은 화면 없이 백그라운드에 상주하며 일하는 프로세스입니다. 웹서버, 로그 수집기, 시간 동기화기 같은 것들이죠. 이름 끝에 d가 붙는 관례가 있습니다 — sshd, cron, syslogd처럼요. 윈도우의 "서비스"(Step 5, 13)와 같은 자리입니다.
3. 따라 하기
3-1. 지금 뭐가 돌고 있나 — ps aux
ps aux | head -12
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 12.1 0.1 21740 13188 ? Ss 11:28 0:00 /sbin/init
root 2 0.0 0.0 3180 2204 hvc0 Sl+ 11:28 0:00 /init
root 6 0.0 0.0 3604 2412 hvc0 Sl+ 11:28 0:00 plan9 --control-socket 7 ...
root 49 3.7 0.1 33916 12648 ? S<s 11:28 0:00 /usr/lib/systemd/systemd-journald
root 98 3.2 0.0 25148 6488 ? Ss 11:28 0:00 /usr/lib/systemd/systemd-udevd
systemd+ 114 2.0 0.1 21468 13284 ? Ss 11:28 0:00 /usr/lib/systemd/systemd-resolved
...
(2026-09-09 WSL 우분투 24.04에서 실측. 여러분 가상머신의 목록·번호·사용자명은 다릅니다 — 여러분 계정명이 USER 칸에 보이면 정상입니다.)
출력 읽는 법: 컬럼을 해석합니다. USER는 프로세스 주인, PID는 번호표, %CPU와 %MEM은 자원 점유율, STAT은 상태(S=잠, R=실행 중, Z=좀비), COMMAND는 실행된 명령입니다. 맨 위의 1번 프로세스가 보이죠? 모든 프로세스의 조상입니다. 옵션 a는 모든 사용자, u는 자세히, x는 터미널 없는 것까지 포함하라는 뜻입니다.
왜: 시스템 점검의 첫걸은 항상 "목록 보기"입니다. 이 표를 편하게 읽는 눈이 오늘의 첫 수확입니다.
3-2. 부모 번호까지 보기 — ps -ef
ps aux에는 부모 번호가 없습니다. 부모를 보려면 형식을 바꿉니다:
ps -ef | head -10
UID PID PPID C STIME TTY TIME CMD
root 1 0 12 11:28 ? 00:00:00 /sbin/init
root 2 1 0 11:28 hvc0 00:00:00 /init
root 6 2 0 11:28 hvc0 00:00:00 plan9 --control-socket 7 ...
root 49 1 3 11:28 ? 00:00:00 /usr/lib/systemd/systemd-journald
root 98 1 3 11:28 ? 00:00:00 /usr/lib/systemd/systemd-udevd
systemd+ 114 1 2 11:28 ? 00:00:00 /usr/lib/systemd/systemd-resolved
...
(2026-09-09 실측.)
출력 읽는 법: 세 번째 컬럼이 PPID — 나를 실행시킨 프로세스의 번호입니다. 실측 표로 계보를 읽어 봅시다. PID 1의 PPID는 0(위에 없음, 시조라는 뜻). journald(49)의 PPID는 1, 즉 1번이 직접 실행시켰습니다. udev-worker들의 PPID는 98, 바로 위의 systemd-udevd — "누가 누구를 실행했나"가 추측이 아니라 숫자로 증명됩니다.
3-3. 실험용 프로세스 만들기 — 백그라운드 실행
이제 직접 프로세스를 만들어 봅니다. sleep은 "아무것도 안 하고 N초 자는" 명령으로, 실험용 가짜 작업으로 완벽합니다:
sleep 300 &
[1] 652
(출력 예시 — 형식은 실측과 동일합니다. [1]은 작업 번호(job), 뒤의 숫자가 이 프로세스의 PID입니다. 여러분 화면의 번호는 다릅니다.)
끝의 &가 "이걸 백그라운드로 돌려라"는 뜻입니다. 프롬프트가 바로 돌아왔죠. 이 터미널의 작업 명단을 봅니다:
jobs
[1]+ Running sleep 300 &
(2026-09-09 실측 — 실측에서는 sleep 5로 확인했으며, 형식은 동일합니다.)
왜: & 하나면 터미널을 점유하지 않고 프로그램을 돌릴 수 있습니다. 오래 걸리는 작업을 뒤로 보내고 계속 다른 일을 하는 기본기입니다.
3-4. 찾아서 종료하기 — ps + grep + kill
만든 프로세스를 시스템 전체 목록에서 찾습니다:
ps aux | grep sleep
root 652 0.0 0.0 3132 1904 pts/0 S+ 11:28 0:00 sleep 300
root 660 0.0 0.0 4096 2088 pts/0 S+ 11:29 0:00 grep sleep
(두 번째 줄은 2026-09-09 실측으로 확인된 형태입니다.)
출력 읽는 법: 두 줄이 나옵니다. 첫 줄이 진짜 sleep, 두 번째 줄은 방금 친 grep 자신입니다 — 명령줄에 검색어가 들어 있어서 자기 자신도 걸리는, 초보가 헷갈리는 유명한 함정입니다. ps aux | grep sleep | grep -v grep처럼 grep -v grep("grep 들어간 줄은 빼고")을 붙이면 자기 자신을 걸러 냅니다. 실무자들의 손에 밴 단골 조합입니다.
⚠️ 주의 — kill은 신중하게: 이제 프로세스를 종료하는 명령이 나옵니다.
kill뒤의 번호가 방금 확인한 실험용 sleep의 PID인지 반드시 확인하고 실행하세요. 번호를 잘못 적어 다른 프로세스를 종료하면, 그 프로그램의 저장 안 된 작업이 날아갈 수 있습니다.
kill 652
jobs
[1]+ Terminated sleep 300
(출력 예시 — 형식은 실제 동작과 동일합니다. 652는 여러분이 확인한 PID로 바꾸세요.)
읽는 법: 기본 시그널(SIGTERM)을 받은 sleep이 순순히 종료했습니다. "Terminated"는 정리 후 퇴장했다는 뜻입니다.
왜: "목록 보기(ps) → 번호 찾기(grep) → 신호 보내기(kill)" — 이 3연타가 프로세스 관리의 기본 동작입니다.
3-5. 강제 종료와 안전성 확인 — kill -9, 그리고 없는 번호
이번엔 강제 종료의 형태를 봅니다:
sleep 600 &
kill -9 655
jobs
[1]+ Killed sleep 600
(출력 예시 — 실제 동작과 같은 형식입니다. PID는 여러분 것으로 바꾸세요.)
읽는 법: 메시지가 "Terminated"가 아니라 "Killed"입니다. 정리 절차 없이 즉사했다는 뜻입니다. 이 차이가 2-3절의 "마지막 수단" 감각입니다.
예측해 보기: 만약 PID를 잘못 써서
kill 99999처럼 없는 번호에 kill을 내면? ① 아무 일도 없음 ② 오류 메시지 ③ 컴퓨터가 꺼진다. 예측하고 확인해 보세요. (정답: ② — 실측 결과bash: kill: (99999) - No such process라는 오류가 뜹니다. kill은 조심해서 써야 하는 명령이지만, 없는 번호는 그냥 거절합니다. 2026-09-09 실측.)
3-6. 실시간 관찰 — top
top
화면 전체가 실시간 표로 바뀌고, 몇 초마다 숫자가 움직입니다. 실측 화면의 윗부분:
top - 11:29:11 up 0 min, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 30 total, 1 running, 29 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 7655.7 total, 6382.1 free, 597.3 used, 827.9 buff/cache
(2026-09-09 실측 — 일괄 출력 모드로 캡처했습니다. 여러분 화면에서는 숫자가 계속 움직입니다.)
읽는 법: 위쪽은 CPU·메모리 요약, 아래쪽은 %CPU 순으로 정렬된 프로세스 순위입니다. 어떤 프로세스가 일을 많이 하는지 한눈에 보이죠. 종료는 q입니다.
왜: "서버가 느린데 뭐가 먹고 있지?"라는 질문의 표준 첫 도구입니다.
4. 미션과 연습문제
미션 — 프로세스 관리 3연타 카드 만들기
sleep 500 &을 세 번 실행해 실험용 프로세스 셋을 만드세요jobs로 셋이 보이는지 확인하고,ps aux | grep sleep | grep -v grep으로 시스템 목록에서도 찾으세요- 하나는 기본
kill로, 하나는kill -9로 정리하고 메시지(Terminated / Killed)의 차이를 기록하세요 ps -ef | head -20에서 PPID가 1인 프로세스를 세 개 찾아 종이에 적으세요- 나머지 한 개까지 정리해
jobs가 비는 것을 확인한 뒤, 오늘 배운 시그널 셋(15, 9, 2)을 언제 쓰는지signals.txt에 정리하세요
연습문제
문제 1. kill은 왜 "죽이는 명령"이 아니라 "시그널을 보내는 명령"이라고 설명해야 정확한가요? 기본으로 가는 시그널은 무엇인가요?
문제 2. SIGTERM과 SIGKILL의 차이를 "뒷정리"의 관점에서 설명하고, 왜 항상 SIGTERM을 먼저 써야 하는지 말해 보세요.
문제 3. ps aux | grep sleep을 쳤더니 두 줄이 나왔습니다. 두 번째 줄의 정체는 무엇이며, 어떻게 걸러 내나요?
문제 4. 터미널을 닫았더니 &로 돌려 둔 백그라운드 작업이 함께 죽었습니다. 어떤 시그널 때문이며, 오래 돌릴 작업은 어떻게 해야 할까요?
5. 모범 답안과 완료 기준
미션 모범 답안
sleep 500 &
sleep 500 &
sleep 500 &
jobs
ps aux | grep sleep | grep -v grep
kill <첫째PID> # → Terminated
kill -9 <둘째PID> # → Killed
ps -ef | head -20 # PPID 1인 프로세스 세 개 찾기
kill <셋째PID>
jobs # 비어 있으면 완료
검증하는 법: ① jobs 출력에서 세 작업이 전부 보였는가. ② 두 종료 메시지가 Terminated와 Killed로 다르게 찍혔는가 — 다르면 두 시그널의 차이를 눈으로 확인한 것입니다. ③ 마지막 jobs가 비어 있는가. 남은 것이 있으면 정리 누락입니다. ④ PPID가 1인 프로세스는 실측 환경에서 systemd-journald(49), systemd-udevd(98), systemd-resolved(114)처럼 systemd 계열이 대표적입니다 — 1번이 직접 키우는 시스템 일꾼들입니다.
연습문제 해답
문제 1 해답. kill의 본래 기능은 프로세스에 시그널을 전달하는 것이고(kill -l로 보낼 수 있는 시그널 목록을 볼 수 있습니다 — 2026-09-09 실측으로 1번 SIGHUP부터 15번 SIGTERM까지 확인), 종료는 그중 하나의 용도일 뿐이기 때문입니다. 기본 시그널은 SIGTERM(15번)입니다.
문제 2 해답. SIGTERM은 프로세스에게 종료를 "요청"해서, 프로세스가 열린 파일을 닫고 데이터를 저장하는 등 뒷정리를 할 시간을 줍니다. SIGKILL은 커널이 프로세스를 즉시 소멸시켜 뒷정리 기회가 없습니다. 그래서 항상 SIGTERM을 먼저 보내고, 응답이 없을 때만 SIGKILL을 씁니다 — 데이터를 지키는 순서입니다.
문제 3 해답. 두 번째 줄은 방금 실행한 grep 명령 자신입니다. 명령줄에 검색어("sleep")가 들어 있어서 프로세스 목록에 자기가 잡히는 것입니다. ps aux | grep sleep | grep -v grep으로 자기 자신을 걸러 냅니다.
문제 4 해답. 터미널이 닫힐 때 자식 프로세스들에게 SIGHUP(연결 끊김)이 가고, 기본적으로 받으면 종료하기 때문입니다. 터미널을 닫아도 살아 있어야 하는 오래된 작업은 nohup이나 tmux 같은 도구를 씁니다 — 지금은 존재만 기억해 두면 됩니다.
완료 기준 체크리스트
- [ ] PID와 PPID의 의미를 설명할 수 있다
- [ ]
ps aux출력의 주요 컬럼(USER, PID, %CPU, STAT, COMMAND)을 읽을 수 있다 - [ ] kill이 시그널을 보내는 명령임을 설명할 수 있다
- [ ] SIGTERM과 SIGKILL의 차이와 사용 순서를 말할 수 있다
- [ ]
&와 jobs로 백그라운드 작업을 만들고 확인할 수 있다 - [ ] grep이 자기 자신을 검색하는 함정과
grep -v grep해결법을 안다 - [ ] 미션: 3연타 카드와 signals.txt를 완성했다
6. 흔한 실수와 해결
벽 1. "kill을 쳤는데 안 죽어요"
증상: kill 뒤에도 ps에서 프로세스가 그대로 보입니다.
원인: SIGTERM을 무시하도록 만들어진 프로그램이거나, 정리 작업이 길어서 죽는 중입니다.
해결: 몇 초 기다렸다가 다시 확인하세요. 그래도 살아 있으면 그때 kill -9를 씁니다. 처음부터 -9를 쓰는 습관은 데이터 유실을 부릅니다.
벽 2. "grep 결과에 내가 찾는 게 두 개예요"
증상: ps aux | grep 뭐시기 하면 진짜 프로세스와 grep 자신이 함께 나옵니다 (2026-09-09 실측으로 재현 확인).
원인: grep 명령줄에도 검색어가 들어 있어서 자기 자신이 검색됩니다.
해결: | grep -v grep을 붙여 자기 자신을 빼세요.
벽 3. "터미널을 닫았더니 백그라운드 작업이 죽었어요"
증상: &로 돌려 둔 작업이 터미널 종료와 함께 사라집니다.
원인: 터미널이 닫힐 때 자식 프로세스들에게 SIGHUP("연결 끊김")이 갑니다. 기본 동작은 종료입니다.
해결: 지금은 "백그라운드 작업은 터미널과 운명을 함께한다"로 이해하면 충분합니다. 서버에서 오래 돌릴 작업은 tmux나 nohup을 쓴다는 것만 기억해 두세요.
벽 4. "다른 사람 프로세스를 못 죽여요"
증상: kill을 쳤더니 Operation not permitted가 뜹니다.
원인: 프로세스에도 소유자가 있습니다. 남의 프로세스는 못 건드립니다 — 권한(Step 23~24)의 연장선입니다.
해결: 오류가 아니라 정상 동작입니다. 시스템 프로세스를 정리해야 한다면 sudo가 필요하고, 그 전에 "이걸 죽여도 되나"를 먼저 물어야 합니다.
벽 5. "jobs에는 있는데 ps aux에는 안 보여요(또는 그 반대)"
증상: 두 명령의 결과가 서로 다릅니다.
원인: jobs는 "지금 이 터미널에서 시작한 작업"만 보고, ps aux는 시스템 전체를 봅니다. 범위가 다른 도구입니다.
해결: 방금 &로 띄운 것은 jobs로, 시스템 어딘가의 프로세스를 찾을 때는 ps로. 용도를 구분하면 헷갈리지 않습니다.
7. 정리
오늘의 개념
| 개념 | 한 줄 설명 |
|---|---|
| PID / PPID | 프로세스의 고유 번호 / 나를 실행시킨 부모의 번호 |
| 시그널 | 프로세스에게 의사를 전달하는 신호 체계 |
| SIGTERM(15) | 정중한 종료 요청 — 뒷정리 가능, kill의 기본값 |
| SIGKILL(9) | 즉시 소멸 — 거부 불가, 마지막 수단 |
| 포그라운드 / 백그라운드 | 프롬프트를 잡고 도는가 / 뒤에서 도는가 (&) |
| 데몬 | 화면 없이 상주하는 백그라운드 일꾼 (이름 끝 d 관례) |
오늘의 명령어
| 명령 | 하는 일 |
|---|---|
ps aux |
전체 프로세스 목록 (자원 점유 포함) |
ps -ef |
부모 번호(PPID)까지 보는 목록 |
명령 & |
백그라운드 실행 |
jobs / fg / bg |
이 터미널의 작업 명단 / 앞으로 / 뒤로 |
kill [PID] |
시그널 보내기 (기본 SIGTERM) ⚠️ 대상 확인 필수 |
kill -9 [PID] |
강제 소멸 (SIGKILL) ⚠️ 마지막 수단 |
top |
실시간 프로세스 감시 (종료 q) |
kill -l |
보낼 수 있는 시그널 전체 목록 |
명령어보다 중요한 감각
현장에서 "서버가 죽었다"는 말은 대부분 "컴퓨터가 꺼졌다"가 아니라 "어떤 프로세스가 응답하지 않는다"입니다. 이때 초보는 재부팅부터 생각하고, 숙련자는 ps와 top부터 엽니다. 어느 프로세스가 CPU를 다 먹는지, 응답 없는 서비스의 PID는 살아 있는지 — 목록이 말해 주기 때문입니다. 재부팅은 "모든 프로세스를 SIGKILL하는 것"과 같아서, 원인 파악의 기회를 스스로 걷어차는 최후의 카드입니다.
그리고 관점 하나: 프로세스를 "죽이는" 것이 아니라 "대화하는" 것으로 보면 명령이 다르게 보입니다. kill은 협박이 아니라 초인종입니다. 정중하게(SIGTERM) 눌러 보고, 응답이 없을 때만 문을 부수는(SIGKILL) 것 — 이 순서가 데이터를 지키는 예의입니다.
두 가지를 더 기억해 두세요. 첫째, 1번 프로세스는 모든 프로세스의 조상으로, 요즘 우분투에서는 systemd가 그 자리에 있습니다 — 시스템 서비스(데몬)들의 시작·감시·재시작을 관리하는 "프로세스계의 왕"입니다. 오늘 ps -ef에서 PPID 1의 자식들을 본 것이 그 증거입니다. 둘째, 침해 사고 대응 매뉴얼의 공통 첫 장은 "프로세스 목록 확보"입니다 — 평소에 없던 이름이 있는가, 부모가 이상하지 않은가, 시스템 이름을 흉내 낸 가짜(svch0st 같은)는 없는가를 오늘 배운 ps와 계보 읽기로 묻습니다. 오늘의 3연타가 그 조사의 원시 형태입니다.
프로세스를 다룰 수 있다는 것은 컴퓨터의 "지금"을 읽을 수 있다는 뜻입니다. 파일이 과거의 기록이라면 프로세스는 현재의 호흡입니다. 죽이는 법보다 살피는 법을 먼저 배운 것, 그것이 오늘의 진짜 수확입니다.
전부 체크되면 Step 26 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.