LabHub
배우기 러닝패스 코스

Linux基礎

プロセスとシグナルを扱う

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= 형식으로 출력하세요.