LabHub
배우기 러닝패스 코스

Linux Fundamentals

Working With Processes and Signals

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

프로세스에 시그널을 보내며 정지·종료·강제 종료가 각각 무엇이 다른지 확인하고, 좀비가 어떻게 생기는지 직접 만들어 봅니다.

왜 중요한가

"프로세스가 안 죽는다"는 신고는 최소 네 가지 다른 상황을 뭉뚱그린 말입니다. 애플리케이션이 SIGTERM 을 잡아 무시했을 수도 있고, D 상태라 시그널 처리 자체가 미뤄졌을 수도 있고, 이미 죽어서 좀비로 남은 것일 수도 있습니다. 대응이 전부 다르기 때문에 어느 계층에서 멈췄는지를 먼저 물어야 합니다. 그리고 SIGKILL 과 SIGSTOP 만 잡을 수 없다는 규칙은 커널이 운영자에게 남겨 둔 최후의 수단입니다 - 그래서 SIGKILL 은 정리 기회를 주지 않고, DB 나 큐 소비자에게는 전원을 뽑는 것과 같습니다.

단계

  1. sleep 3600 을 백그라운드로 띄우고 그 PID 를 /root/proc/pid.txt 에 적으세요.
  2. 그 프로세스의 부모 PID/root/proc/ppid.txt 에 적으세요.
  3. 또 다른 sleep 을 띄워 정지(SIGSTOP) 시키고, PID 를 /root/proc/stopped_pid.txt 에, 정지 후의 상태 글자 한 개를 /root/proc/state_stopped.txt 에 적으세요.
  4. 또 다른 sleep 을 띄워 PID 를 /root/proc/killed_pid.txt 에 적은 뒤 SIGTERM 으로 종료시키세요.
  5. /root/proc/trapper.sh 를 만드세요. SIGTERM 을 받으면 /root/proc/term.logcaught SIGTERM 한 줄을 추가해야 합니다. 실행 권한을 주고 백그라운드로 띄운 뒤 SIGTERM 을 보내 로그가 쌓이는지 확인하세요.
  6. trapper.sh 를 다시 띄우고 이번엔 SIGKILL 을 보내세요. 보내기 직전 term.log 의 줄 수를 /root/proc/before_kill.txt 에, 보낸 직후의 줄 수를 /root/proc/after_kill.txt 에 적으세요. 실습이 끝나면 trapper.sh 는 하나도 살아 있으면 안 됩니다.
  7. 자식을 하나 낳고 그 자식이 먼저 끝나도록 하되, 부모는 wait 하지 않고 계속 살아 있게 만드세요. 그 부모의 PID/root/proc/zombie_parent.txt 에 적으세요.
  8. /root/proc/cleanup.sh <패턴> 을 만드세요. 명령줄이 그 패턴에 맞는 프로세스를 모두 종료하고, 종료한 개수를 terminated=<n> 형식으로 한 줄 출력해야 합니다. 자기 자신은 세지도 죽이지도 않아야 합니다.

참고

백그라운드 프로세스 띄우기

sleep 3600 을 백그라운드로 띄우고 그 PID 를 /root/proc/pid.txt 에 적으세요.

명령 뒤에 & 를 붙이면 백그라운드로 갑니다. 바로 다음에 $! 안에 그 PID 가 들어 있습니다.

부모 PID 확인하기

그 프로세스의 부모 PID/root/proc/ppid.txt 에 적으세요.

/proc//status 의 PPid 줄을 보거나 ps -o ppid= -p 를 씁니다.

프로세스 정지시키기

또 다른 sleep 을 띄워 정지(SIGSTOP) 시키고, PID 를 /root/proc/stopped_pid.txt 에, 정지 후의 상태 글자 한 개를 /root/proc/state_stopped.txt 에 적으세요.

정지와 종료는 다릅니다. 정지된 프로세스는 목록에 남아 있고 상태 글자가 바뀝니다.

정중하게 종료 요청하기

또 다른 sleep 을 띄워 PID 를 /root/proc/killed_pid.txt 에 적은 뒤 SIGTERM 으로 종료시키세요.

kill 은 기본적으로 SIGTERM 을 보냅니다. 보내기 전에 PID 를 파일에 적어 두세요.

SIGTERM 을 잡는 스크립트

/root/proc/trapper.sh 를 만드세요. SIGTERM 을 받으면 /root/proc/term.logcaught SIGTERM 한 줄을 추가해야 합니다. 실행 권한을 주고 백그라운드로 띄운 뒤 SIGTERM 을 보내 로그가 쌓이는지 확인하세요.

trap '명령' TERM 형태로 핸들러를 겁니다. 스크립트는 종료되지 않고 계속 살아 있어야 신호를 받을 수 있습니다.

SIGKILL 은 잡히지 않는다

trapper.sh 를 다시 띄우고 이번엔 SIGKILL 을 보내세요. 보내기 직전 term.log 의 줄 수를 /root/proc/before_kill.txt 에, 보낸 직후의 줄 수를 /root/proc/after_kill.txt 에 적으세요. 실습이 끝나면 trapper.sh 는 하나도 살아 있으면 안 됩니다.

trap 이 걸린 그 스크립트에 9번을 보내고, 로그 줄 수가 늘었는지 전후로 비교해 기록하세요.

좀비 만들어 보기

자식을 하나 낳고 그 자식이 먼저 끝나도록 하되, 부모는 wait 하지 않고 계속 살아 있게 만드세요. 그 부모의 PID/root/proc/zombie_parent.txt 에 적으세요.

자식이 먼저 끝나고 부모가 wait 하지 않은 채 살아 있으면 좀비가 됩니다. 부모가 계속 살아 있어야 합니다.

패턴 기반 정리 스크립트

/root/proc/cleanup.sh <패턴> 을 만드세요. 명령줄이 그 패턴에 맞는 프로세스를 모두 종료하고, 종료한 개수를 terminated=<n> 형식으로 한 줄 출력해야 합니다. 자기 자신은 세지도 죽이지도 않아야 합니다.

pgrep -f 로 먼저 세고, 자기 자신은 제외해야 합니다. 종료 후 개수를 terminated= 형식으로 출력하세요.