지난 회차에서 우리는 리눅스 인프라 운영의 핵심인 텍스트 스트림 가공 도구 sed와 awk를 활용하여 방대한 로그 데이터를 정제하는 방법을 알아보았습니다. 이제 시스템 내부의 데이터를 자유자재로 제어할 수 있게 되었으니, 이번에는 현재 서버 안에서 살아 움직이는 프로그램들의 상태를 실시간으로 추적하고 관리하는 '프로세스 감시 기술'을 마스터할 차례입니다.
개발자가 작성한 백엔드 애플리케이션이나 Nginx, MySQL 같은 핵심 데몬이 실행되면, 운영체제(OS)는 이를 프로세스(Process)라는 단위로 메모리에 올려 CPU 자원을 할당합니다. 서버를 안정적으로 운영하다가도 갑자기 웹사이트 응답 속도가 느려지거나 CPU 사용률이 100%까지 치솟는 비상 상황이 발생할 수 있습니다.
이때 시스템 엔지니어가 가장 먼저 수행해야 하는 작업이 바로 시스템 자원을 비정상적으로 갉아먹고 있는 프로세스를 찾아내어 격리하는 것입니다. 이번 8회차에서는 리눅스 프로세스 감시의 3대 무기인 ps, top, htop 명령어의 메커니즘과 실무 트러블슈팅 활용법을 상세히 살펴보겠습니다.
ps(Process Status) 명령어는 현재 시스템에서 실행 중인 프로세스들의 정적인 스냅샷(현재 상태의 단면)을 캡처하여 화면에 보여줍니다. 실시간으로 변하는 움직임을 지속해서 보여주지는 않지만, 특정 프로세스가 정상적으로 구동 중인지, 어떤 옵션(인자)을 가지고 실행되었는지 핀포인트로 확인할 때 독보적으로 유용합니다.
-ef와 auxps 명령어는 크게 POSIX 표준 옵션 방식과 BSD 옵션 방식으로 나뉘며, 실무에서는 다음 두 가지 조합이 표준처럼 사용됩니다.
ps -ef: 시스템의 모든 프로세스(-e)를 친숙한 전체 포맷(-f)으로 인쇄합니다.
ps aux: 실행 중인 모든 프로세스를 CPU 및 메모리 점유율 정보와 함께 정밀하게 인쇄합니다.
Nginx 웹 서비스가 정상적으로 살아있는지, 마스터 프로세스와 워커 프로세스가 규칙대로 포크(Fork)되어 작동 중인지 확인할 때 앞서 배운 grep과 파이프라인으로 연결하여 사용합니다.
Bash
ps -ef | grep "nginx"
위 명령어를 실행하면 다음과 같은 정형화된 프로세스 메타데이터 덤프가 출력됩니다. 각 열의 의미를 명확히 해석할 수 있어야 구조적인 장애 추적이 가능합니다.
Plaintext
UID PID PPID C STIME TTY TIME CMD
root 1024 1 0 Jun18 ? 00:00:00 nginx: master process /usr/sbin/nginx
www-data 1025 1024 2 Jun18 ? 00:15:30 nginx: worker process
www-data 1026 1024 1 Jun18 ? 00:10:12 nginx: worker process
UID: 프로세스를 실행한 소유자 계정입니다. 보안 규정에 따라 웹 서버 워커 프로세스가 root가 아닌 권한이 낮은 www-data 계정으로 정상 격리되어 작동하는지 감시하는 지표가 됩니다.
PID (Process ID): 운영체제가 프로세스에 부여한 고유 식별 번호입니다. 해당 프로세스를 제어하거나 종료할 때 커널에 전달하는 주소가 됩니다.
PPID (Parent Process ID): 이 프로세스를 낳은 부모 프로세스의 ID입니다. 위 예시에서 워커 프로세스(1025, 1026)의 부모는 마스터 프로세스(1024)임을 직관적으로 알 수 있습니다. 부모 프로세스가 예기치 않게 종료되어 고아가 된 프로세스를 추적할 때 요긴하게 쓰입니다.
CMD: 프로세스를 구동한 실제 실행 명령어 경로와 인자 값입니다.
ps가 단면 사진을 찍는다면, top(Table of Processes)은 대화형 대시보드 형태로 시스템 자원 사용량과 전체 프로세스 목록을 실시간(기본 3초 주기)으로 갱신하여 보여주는 동영상과 같습니다. 별도의 패키지 설치 없이 모든 리눅스 배포판에 기본 탑재되어 있어 원격지 서버에 접속했을 때 가장 먼저 실행하게 되는 보안 및 가용성 진단 도구입니다.
top 명령어를 입력하면 화면이 크게 상단의 '시스템 요약 영역'과 하단의 '프로세스 상세 리스트 영역'으로 이원화되어 출력됩니다.
Load Average: 현재 CPU가 처리하기 위해 대기 중인 작업 큐의 길이를 1분, 5분, 15분 단위의 평균치로 보여줍니다. 이 값이 서버의 물리 CPU 코어 수보다 높다면 현재 연산 자원이 병목 상태에 빠졌음을 경고하는 강력한 신호입니다.
%Cpu(s): CPU 자원이 어디에 소모되는지 세분화하여 보여줍니다. us(User space, 애플리케이션 연산), sy(System space, 커널 내부 처리), id(Idle, 유휴 자원), wa(I/O Wait, 디스크 읽기/쓰기 대기 대기) 등이 표기됩니다. 만약 wa 수치가 지나치게 높다면 CPU 연산 자체보다는 하드디스크나 스토리지 속도 한계로 인해 전체 시스템이 느려지고 있음을 파악할 수 있습니다.
top 실행 중에 터미널 화면에서 다음 단축키를 입력하면 실시간으로 정렬 기준을 바꾸며 문제 프로세스를 정밀 타격할 수 있습니다.
P (대문자): CPU 점유율이 가장 높은 프로세스 순으로 내림차순 정렬합니다. (폭주하는 프로세스 스캔 시 필수)
M (대문자): 메모리(RAM) 점유율이 가장 높은 프로세스 순으로 정렬합니다. (메모리 누수 소스 추적 시 필수)
k: top 화면을 벗어나지 않고 그 자리에서 즉시 특정 PID를 지정하여 프로세스를 종료(Kill) 시그널을 보냅니다.
q: 모니터링을 종료하고 원래 터미널 화면으로 복귀합니다.
top 명령어가 훌륭하긴 하지만 텍스트 기반의 출력이 가독성이 떨어지고 멀티 코어 CPU 환경에서 각 코어별 부하를 한눈에 파악하기 어렵다는 단점이 있습니다. 이를 완벽하게 보완하여 모던하게 발전시킨 도구가 바로 htop입니다.
htop은 풍부한 컬러 텍스트와 텍스트 기반 그래픽 바(Bar) 차트를 활용하여 CPU 코어별 점유율, 메모리 사용량, 스왑(Swap) 영역의 상태를 시각적으로 보여줍니다. 또한 마우스 스크롤과 클릭을 지원하며 터미널 하단에 기능 키(F1 ~ F10) 메뉴를 배치하여 직관적인 프로세스 제어를 가능하게 만듭니다.
기본 내장 도구가 아니므로 각 배포판의 패키지 관리자를 통해 수동으로 구성해야 합니다.
Bash
# Rocky Linux / RHEL 계열 설치 (EPEL 저장소 활성화 상태 필요)
sudo dnf install htop -y
# Ubuntu / Debian 계열 설치
sudo apt update && sudo apt install htop -y
htop을 실행(sudo htop)하면 상단에 멀티 코어 CPU의 부하 상태가 개별 번호(1, 2, 3, 4...)별로 실시간 막대차트로 동적 표기됩니다.
F3 (Filter): 복잡한 프로세스 목록 중에서 내가 찾고자 하는 프로그램 명칭(예: python)을 입력하면 해당 프로세스들만 실시간으로 필터링되어 화면에 남습니다.
F5 (Tree): 부모 프로세스와 자식 프로세스의 종속 관계를 트리 구조의 선으로 연결하여 시각화해 줍니다. 어떤 프로세스가 다른 자식 프로세스들을 무분별하게 포크(Fork)하여 시스템 자원을 고갈시키고 있는지 추적할 때 최고의 효율을 발휘합니다.
F6 (Sort): 단축키를 외울 필요 없이 메뉴 창에서 CPU, MEMORY, PID 등 원하는 정렬 기준 필드를 마우스나 방향키로 선택해 정렬할 수 있습니다.
실제 웹 서비스 운영 중 모니터링 시스템으로부터 CPU 임계치 초과 경보 알림을 받았을 때 엔지니어가 취해야 하는 표준 트러블슈팅 절차입니다.
Bash
# htop을 켜서 CPU 구조 전체가 병목인지, 특정 코어만 풀 부하인지 식별
sudo htop
분석 결과: 상단 CPU 바가 모두 임계치에 도달했고, 하단 목록에서 특정 파이썬 스크립트 프로세스(PID: 5432)의 %CPU 수치가 99.9%를 기록하고 있음을 확인했습니다.
해당 프로세스가 시스템 관리자가 정상적으로 구동한 연산 작업인지, 아니면 외부 해커에 의해 무단 주입된 악성 마이너 프로그램인지 CMD 전체 경로와 구동 인자를 ps 명령어로 재차 교차 검증합니다.
Bash
ps -fp 5432
# 출력 결과를 분석하여 비정상적인 임시 경로(/tmp/.hidden/crypto)에서 실행된 악성 코드임을 확정합니다.
자원을 독점하는 악성 프로세스를 방치하면 다른 정상적인 대고객 서비스까지 먹통이 되므로, 안전하게 프로세스를 강제 종료 처리하여 자원을 회수합니다.
Bash
sudo kill -9 5432
리눅스 시스템 인프라를 무중단 상태로 안전하게 가동하기 위해서는 내부에서 돌아가는 프로세스들의 움직임을 빈틈없이 감시하고 통제할 수 있어야 합니다.
특정 단일 프로세스의 구동 여부와 부모-자식 관계의 단면을 정밀 스캔할 때는 ps -ef 조합을 사용하고,
추가 패키지 설치가 불가능한 긴급한 환경에서 시스템의 Load Average와 CPU/메모리 요약을 상시 모니터링할 때는 top을 활용하며,
멀티 코어 환경에서 시각적인 가독성을 극대화하고 트리 구조와 필터 기능을 통해 장애 원인 프로세스를 핀포인트로 색출해 낼 때는 htop을 전면에 배치해야 합니다.
이 프로세스 감시 명령어들을 숙달하고 자원 병목의 본질을 정확히 짚어낼 수 있을 때, 급작스러운 인프라 장애 앞에서도 당황하지 않고 단 몇 초 만에 시스템을 정상 상태로 복구해내는 숙련된 정예 엔지니어로 거듭날 수 있습니다. 다음 9회차에서는 이렇게 찾아낸 폭주 프로세스들과 좀비 프로세스들에게 안전하게 종료 신호를 보내고 시스템 커널 수준에서 깔끔하게 정리하는 '프로세스 강제 종료와 시그널 제어(kill, killall, pkill)' 기술에 대해 자세히 알아보겠습니다.