시스템 정보 및 프로세스 관리

LinuxBeginner
지금 연습하기

소개

실행 중인 Linux 시스템은 파일만으로 구성되지 않습니다. 커널은 하드웨어와 프로세스를 관리하고, 각 명령은 식별자를 가진 프로세스로 실행되며, 셸은 포그라운드 및 백그라운드 작업을 추적합니다. 관리자는 먼저 현재 상태를 확인한 다음, 관련된 가장 작은 범위의 프로세스에 작업을 수행합니다.

이 실습에서는 운영 체제와 커널을 식별하고, uptime 과 load average 를 해석하고, 프로세스 관계를 검사하고, 이름으로 프로세스를 찾고, 종료 시그널을 보내고, 대화형 작업 제어를 연습합니다. 또한 종료 상태를 해석하고, nohup으로 분리된 명령을 실행하고, 최근 커널 메시지를 확인합니다.

시스템 식별 및 부하 해석

이 단계에서는 커널과 배포판을 식별하고, 시스템이 실행된 시간을 확인하고, load average 가 의미하는 내용을 학습합니다.

작업 공간을 만들고 이동합니다.

mkdir -p /home/labex/project/process-lab
cd /home/labex/project/process-lab

uname 명령은 커널 정보를 표시합니다. -s, -r, -m 옵션은 각각 커널 이름, 커널 릴리스, 머신 아키텍처를 선택합니다.

uname -srm

uname -a는 사용 가능한 모든 필드를 한 줄에 표시합니다.

uname -a

커널은 Linux 배포판과 같은 것이 아닙니다. 배포판 메타데이터를 확인합니다.

cat /etc/os-release

NAME, VERSION, ID와 같은 필드를 찾습니다. 다음으로 uptime 과 load 를 확인합니다.

uptime

출력에는 현재 시각, 시스템이 실행된 시간, 로그인한 사용자 수, 세 개의 load average 가 포함됩니다. 이 평균값은 약 1 분, 5 분, 15 분 동안 실행 가능했거나 중단할 수 없는 작업량을 나타냅니다. 백분율이 아니며, 의미는 CPU 코어 수에 따라 달라집니다.

커널의 간결한 load 기록을 확인합니다.

cat /proc/loadavg

처음 세 값은 load average 의 개념과 일치합니다. 뒤쪽 필드에는 실행 가능한 작업 수와 가장 최근에 할당된 프로세스 ID 가 표시됩니다.

나중에 참고할 수 있도록 간단한 시스템 요약을 저장합니다.

uname -srm > system-summary.txt
uptime >> system-summary.txt
cat system-summary.txt

파일에는 커널 정보 한 줄과 uptime 정보 한 줄이 있어야 합니다.

프로세스 및 리소스 활동 검사

이 단계에서는 프로세스 식별자, 부모 프로세스 관계, 상태, 시스템 리소스 활동의 스냅샷을 확인합니다.

프로세스는 실행 중인 프로그램입니다. 모든 프로세스에는 process ID 또는 PID 가 있습니다. 대부분의 프로세스에는 해당 프로세스를 시작한 프로세스를 식별하는 parent process ID 또는 PPID 도 있습니다.

ps 명령은 프로세스 스냅샷을 표시합니다. 필요한 필드를 선택하고 PID 순서로 정렬합니다.

cd /home/labex/project/process-lab
ps -eo pid,ppid,user,stat,comm --sort=pid | head -n 15

-e 옵션은 모든 프로세스를 선택하고, -o 옵션은 열을 정의합니다.

  • PID는 프로세스 식별자입니다.
  • PPID는 부모 프로세스 식별자입니다.
  • USER는 프로세스 소유자입니다.
  • STAT는 프로세스 상태와 선택적 플래그입니다.
  • COMMAND는 실행 파일 이름입니다.

일반적인 상태 문자는 다음과 같습니다. R은 실행 중, S는 인터럽트 가능한 대기, D는 인터럽트할 수 없는 대기, T는 중지됨, Z는 좀비 프로세스를 의미합니다. 대기 중인 프로세스는 단순히 작업을 기다리는 경우가 많습니다.

BSD 스타일의 ps aux 형식은 CPU 및 메모리 열과 전체 명령줄을 제공합니다.

ps aux | head -n 10

대화형으로 실행하면 top은 지속적으로 업데이트됩니다. 배치 모드는 안정적인 스냅샷 하나를 만듭니다. -b는 배치 출력을 선택하고 -n 1은 한 번만 업데이트하도록 지정합니다.

top -b -n 1 | head -n 12

헤더에는 uptime, load, 작업 상태, CPU 사용량, 메모리 정보가 요약되어 있습니다. 그 아래의 프로세스 테이블에서는 리소스를 많이 사용하는 프로세스를 찾을 수 있습니다.

이제 대화형 화면을 엽니다.

top

값이 업데이트되는 것을 확인하고 %CPU%MEM 열을 찾은 다음 q를 눌러 셸로 돌아옵니다. 대화형 top은 시간에 따른 변화를 관찰할 때 유용하고, 출력을 저장하거나 다른 명령으로 처리해야 할 때는 배치 모드가 더 적합합니다.

관찰 가능한 결과로 사용할 프로세스 스냅샷을 저장합니다.

ps -eo pid,ppid,user,stat,comm --sort=pid > process-snapshot.txt
head -n 5 process-snapshot.txt

연습용 프로세스 시작 및 찾기

이 단계에서는 안전한 백그라운드 프로세스를 시작하고 PID 를 저장한 다음, pspgrep을 사용해 프로세스를 찾습니다.

끝에 &를 붙이면 셸이 명령을 백그라운드에서 실행하고 즉시 프롬프트를 반환합니다. 이름이 labex-worker로 표시되는 5 분짜리 sleep 프로세스를 시작합니다.

cd /home/labex/project/process-lab
bash -c 'exec -a labex-worker sleep 300' &

특수한 셸 값 $!에는 가장 최근에 시작한 백그라운드 프로세스의 PID 가 들어 있습니다. 다른 백그라운드 명령을 시작하기 전에 이 값을 저장합니다.

worker_pid=$!
echo "$worker_pid" > worker.pid

해당 프로세스만 정확히 검사합니다. -p 옵션은 PID 를 선택하고, -o 옵션은 필드를 선택합니다.

ps -o pid,ppid,user,stat,etime,args -p "$worker_pid"

ETIME은 경과한 실행 시간을 표시하고, ARGS에는 표시되는 프로세스 이름이 포함됩니다. pgrep -f를 사용하면 전체 명령줄을 검색할 수 있으며, -a를 함께 사용하면 명령줄도 출력됩니다.

pgrep -af labex-worker

pgrep의 PID 는 worker.pid의 PID 와 일치해야 합니다. 정확한 패턴으로 검색하면 범위가 넓은 이름으로 모든 프로세스에 작업을 수행하는 것보다 안전합니다.

시그널로 프로세스 중지

이 단계에서는 SIGTERM 으로 정상적인 종료를 요청하고, 해당 요청을 무시하도록 설계된 프로세스에만 SIGKILL 을 사용합니다.

kill 명령은 PID 에 시그널을 보냅니다. 시그널을 명시하지 않으면 시그널 15 인 SIGTERM 을 보냅니다. SIGTERM 은 정상적인 종료를 요청하며, 프로세스가 정리 작업을 수행할 기회를 제공합니다.

작업자 프로세스의 PID 를 읽고 SIGTERM 을 보냅니다.

cd /home/labex/project/process-lab
worker_pid=$(cat worker.pid)
kill "$worker_pid"
sleep 1

다음 명령에서 ps가 실패하면 프로세스가 종료된 것입니다.

ps -p "$worker_pid" || echo "labex-worker stopped after SIGTERM"

이제 SIGTERM 을 의도적으로 무시하는 제어된 프로세스를 시작합니다.

bash -c 'trap "" TERM; exec -a labex-stubborn sleep 300' &
stubborn_pid=$!
echo "$stubborn_pid" > stubborn.pid

새 셸이 시그널 핸들러를 설치할 시간을 잠시 줍니다.

sleep 1

SIGTERM 을 보내고 잠시 기다린 다음 프로세스를 확인합니다.

kill -TERM "$stubborn_pid"
sleep 1
ps -o pid,stat,args -p "$stubborn_pid"

이 연습용 프로세스는 SIGTERM 을 무시하므로 여전히 표시되어야 합니다. 시그널 9 인 SIGKILL 은 가로채거나 무시할 수 없습니다. 정상적인 종료 시그널이 효과가 없을 때만 사용합니다.

kill -KILL "$stubborn_pid"

종료된 백그라운드 작업을 회수합니다. 0 이 아닌 상태가 예상되므로 || true를 사용하면 연습 순서를 계속 진행할 수 있습니다.

wait "$stubborn_pid" 2>/dev/null || true
ps -p "$stubborn_pid" || echo "labex-stubborn required SIGKILL"

SIGKILL 은 프로세스가 상태를 저장하거나 애플리케이션 리소스를 정상적으로 해제할 기회를 주지 않으므로 최후의 수단으로 사용해야 합니다.

kill은 알고 있는 PID 를 대상으로 합니다. 이름이나 전체 명령줄로 프로세스를 선택해야 할 때는 pkill이 검색과 시그널 전송을 함께 수행합니다. 구분하기 쉬운 명령줄을 가진 제어된 프로세스를 하나 더 시작합니다.

bash -c 'exec -a labex-helper sleep 300' &
helper_pid=$!
echo "$helper_pid" > helper.pid

작업을 수행하기 전에 전체 명령줄이 정확히 일치하는지 확인합니다.

pgrep -af '^labex-helper 300$'

pkill -f로 정확히 일치하는 프로세스에 SIGTERM 을 보냅니다. ^$ 앵커를 사용하면 이 연습용 패턴이 관련 없는 명령줄과 일치하지 않습니다.

pkill -TERM -f '^labex-helper 300$'
wait "$helper_pid" 2>/dev/null || true
ps -p "$helper_pid" || echo "labex-helper stopped by pkill"

정확한 pkill 패턴을 사용하고, 먼저 pgrep으로 일치 항목을 확인합니다. 범위가 넓은 패턴은 의도한 것보다 많은 프로세스를 중지할 수 있습니다.

포그라운드 및 백그라운드 작업 제어

이 단계에서는 포그라운드 명령을 일시 중지하고, 백그라운드에서 재개하고, 다시 포그라운드로 가져온 다음 중단합니다.

작업 제어는 현재 대화형 셸에 속합니다. 구분하기 쉬운 이름의 포그라운드 sleep 프로세스를 시작합니다.

cd /home/labex/project/process-lab
bash -c 'exec -a labex-job sleep 300'

이제 터미널은 포그라운드 프로세스가 사용하고 있습니다. Ctrl+Z를 누릅니다. 셸이 중지 시그널을 보내고 프롬프트를 다시 표시합니다.

이 셸이 알고 있는 작업을 나열합니다. -l 옵션을 사용하면 프로세스 ID 도 표시됩니다.

jobs -l

Stopped 상태의 작업이 표시되어야 합니다. 작업 번호 1 을 백그라운드에서 재개합니다.

bg %1
jobs -l

상태가 Running으로 바뀌고 프롬프트를 계속 사용할 수 있어야 합니다. 작업을 다시 포그라운드로 가져옵니다.

fg %1

Ctrl+C를 눌러 포그라운드 작업에 인터럽트 시그널을 보냅니다. 프롬프트가 다시 표시되어야 합니다. 연습용 작업이 남아 있지 않은지 확인합니다.

pgrep -af labex-job || echo "No labex-job process remains"

대화형 순서를 마친 뒤 완료 표시 파일을 만듭니다.

touch job-control.done

현재 터미널에 연결된 명령에는 작업 제어를 사용합니다. 이후에는 터미널 세션에 의존하지 않아야 하는 작업에 nohup을 사용합니다.

종료 상태 확인 및 분리된 작업 실행

이 단계에서는 명령의 종료 상태를 해석하고, 터미널 화면과 독립적으로 출력이 유지되는 짧은 백그라운드 작업을 실행합니다.

모든 명령은 정수 상태를 반환합니다. 0 은 성공을 의미하고, 0 이 아닌 값은 어떤 종류의 실패가 발생했음을 의미합니다. 셸 변수 $?에는 방금 완료된 명령의 상태가 들어 있습니다.

성공하는 명령을 실행한 다음 즉시 상태를 출력합니다.

cd /home/labex/project/process-lab
true
echo "true status: $?"

결과는 0이어야 합니다. 이제 경로를 찾을 수 없는 명령을 실행합니다.

ls missing-path

다른 명령이 $?를 덮어쓰기 전에 상태를 저장합니다.

missing_status=$?
echo "missing-path status: $missing_status"

값은 0 이 아니어야 합니다. 예상되는 두 가지 해석을 저장합니다.

printf 'success=0\nfailure=%s\n' "$missing_status" > exit-status.txt

nohup 명령은 프로그램이 터미널 끊김 시그널을 무시하도록 합니다. 마지막의 &는 프로그램을 백그라운드에서 시작합니다. < /dev/null 리디렉션은 터미널 입력을 분리하고, > nohup.log 2>&1은 두 출력 스트림을 모두 로그에 기록합니다.

nohup bash -c 'for item in one two three; do echo "background: $item"; sleep 1; done' < /dev/null > nohup.log 2>&1 &

백그라운드 PID 를 저장하고 짧은 작업이 끝날 때까지 기다립니다.

echo $! > nohup.pid
sleep 4
cat nohup.log

background: one부터 background: three까지 세 줄이 표시되어야 합니다. 장시간 실행되는 작업에서는 저장한 PID 와 로그를 사용해 진행 상황을 확인할 수 있습니다.

최근 커널 메시지 확인

이 단계에서는 커널 메시지 버퍼를 확인하고, 실행 중인 커널 릴리스를 안정적인 참조 정보로 저장합니다.

커널은 시작 과정, 하드웨어, 드라이버, 런타임 이벤트에 관한 메시지를 링 버퍼에 기록합니다. dmesg는 이 버퍼를 읽습니다. 일반적으로 관리자 권한이 필요합니다.

cd /home/labex/project/process-lab
sudo dmesg | tail -n 10

정확한 메시지는 시스템과 시점에 따라 달라집니다. 타임스탬프처럼 보이는 필드와 각 메시지를 생성한 구성 요소 또는 하위 시스템에 주목합니다.

--level 옵션은 심각도에 따라 필터링합니다. 최근 경고와 오류를 표시합니다.

sudo dmesg --level=err,warn | tail -n 10

출력이 없다고 해서 명령이 실패한 것은 아닙니다. 현재 버퍼에 해당 수준의 메시지가 없다는 의미일 수 있습니다. 최근 메시지에서 일반적인 저장 장치 및 네트워크 용어를 검색합니다.

sudo dmesg | grep -Ei 'disk|filesystem|network|eth' | tail -n 10

이 결과 역시 현재 시스템에 따라 달라집니다. uname -r이 보고하는 커널 릴리스를 저장합니다.

uname -r > kernel-version.txt
cat kernel-version.txt

커널 메시지는 자동으로 진단을 내리는 정보가 아니라 근거 자료입니다. 조치를 결정하기 전에 프로세스 상태, 서비스 로그, 관찰된 증상과 함께 검토합니다.

요약

Linux 시스템을 식별하고 uptime 과 load average 를 해석했으며, 스냅샷 및 대화형 도구를 사용해 프로세스 ID, 부모 프로세스, 소유자, 상태, 리소스 활동을 확인했습니다. 이름이 지정된 프로세스를 시작하고 찾았으며, killpkill로 정확히 대상을 지정했습니다. SIGKILL 보다 먼저 SIGTERM 을 사용하고, 포그라운드 및 백그라운드 작업 제어도 연습했습니다.

또한 종료 상태를 해석하고, nohup과 명시적인 로깅을 사용해 분리된 작업을 실행했으며, dmesg로 커널 메시지를 확인했습니다. 이러한 관찰 우선 습관은 안전한 프로세스 문제 해결의 기초이며, 과정 후반에 다룰 서비스, 로깅, 네트워크 진단을 준비하는 데 도움이 됩니다.