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

LinuxBeginner
지금 연습하기

소개

실행 중인 Linux 시스템은 파일만으로 이루어져 있지 않습니다. 커널은 하드웨어와 프로세스를 관리하며, 각 명령은 식별자를 가진 프로세스로 실행됩니다. 또한 셸은 포그라운드 및 백그라운드 작업을 추적합니다. 관리자는 먼저 이러한 상태를 관찰한 다음, 필요한 범위 내에서 가장 관련성 높은 프로세스에 조치를 취합니다.

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

시스템 식별 및 부하 해석

이 단계에서는 커널과 배포판을 식별하고, 시스템이 실행된 시간을 확인하며, 평균 부하가 의미하는 바를 알아봅니다.

작업 디렉터리를 생성하고 이동합니다.

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

출력에는 현재 시각, 시스템이 실행된 시간, 로그인한 사용자 수, 세 개의 평균 부하가 포함됩니다. 이 평균값은 약 1 분, 5 분, 15 분 동안 실행 가능 상태이거나 인터럽트할 수 없는 작업의 양을 나타냅니다. 백분율이 아니며, 의미는 CPU 코어 수에도 영향을 받습니다.

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

cat /proc/loadavg

처음 세 값은 평균 부하를 나타내는 값입니다. 뒤쪽 필드에는 실행 가능 상태인 작업 수와 가장 최근에 할당된 프로세스 ID 가 표시됩니다.

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

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

파일에는 커널 정보 한 줄과 가동 시간 정보 한 줄이 있어야 합니다.

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

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

프로세스는 실행 중인 프로그램입니다. 모든 프로세스에는 프로세스 ID, 즉 PID 가 있습니다. 대부분의 프로세스에는 부모 프로세스 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

헤더에는 가동 시간, 평균 부하, 작업 상태, 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 시스템을 식별하고 가동 시간과 평균 부하를 해석했으며, 프로세스 ID, 부모 프로세스, 소유자, 상태 및 리소스 스냅샷을 확인했습니다. 이름이 지정된 프로세스를 시작하고 찾았으며, SIGKILL 보다 먼저 SIGTERM 을 사용하고, 포그라운드 및 백그라운드 작업 제어를 실습했습니다.

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