글 목록

DevOps

Linux를 이해하는 가장 실용적인 방법: 구조부터 명령어, 트러블슈팅까지

Linux의 Kernel, Process, File System, Permission 구조를 살펴보고, 자주 사용하는 명령어와 실제 서버 트러블슈팅 방법까지 하나의 흐름으로 정리합니다.

Linux를 이해하는 가장 실용적인 방법: 구조부터 명령어, 트러블슈팅까지

개발을 하다 보면 Linux를 피하기는 꽤 어렵습니다.

로컬에서는 macOS나 Windows를 사용하더라도 서비스를 배포하는 순간 Linux를 만나게 되는 경우가 많습니다. Docker container 안으로 들어가도 Linux가 있고, AWS EC2 같은 서버를 생성해도 Linux를 사용하게 됩니다.

처음 Linux를 접했을 때는 ls, cd, grep, ps 같은 명령어부터 외우기 쉽습니다.

물론 명령어를 아는 것도 중요합니다. 하지만 실제 서버에서 장애를 만났을 때는 명령어 자체보다 Linux가 process, file, memory, permission을 어떻게 관리하는지 이해하고 있는 것이 훨씬 도움이 됩니다.

이 글에서는 Linux를 명령어 모음이 아니라 하나의 운영체제 구조로 살펴보겠습니다.


1. Linux는 정확히 무엇일까?

엄밀하게 이야기하면 Linux는 운영체제 전체가 아니라 Kernel을 의미합니다.

Kernel은 application과 hardware 사이에서 CPU, memory, storage, network 같은 system resource를 관리합니다.

개념적으로 단순화하면 다음과 같습니다.

Application
    ↓
System Call
    ↓
Linux Kernel
    ↓
CPU / Memory / Disk / Network

우리가 terminal에서 실행하는 ls, cat, grep 같은 프로그램도 결국 Kernel이 제공하는 기능을 이용합니다.

예를 들어 파일을 읽는 프로그램은 직접 disk hardware를 제어하지 않습니다. Kernel에 파일을 열고 읽어 달라고 요청합니다.

이 경계에서 사용되는 것이 system call입니다.

대표적인 system call에는 다음과 같은 것들이 있습니다.

open()
read()
write()
fork()
exec()
socket()

이 구조를 알고 있으면 Linux에서 발생하는 여러 문제를 조금 다른 시각으로 볼 수 있습니다.

Application이 느리다고 해서 항상 application code가 원인은 아닙니다. CPU가 부족할 수도 있고, disk I/O가 병목일 수도 있으며, network connection이 문제일 수도 있습니다.

Linux troubleshooting은 결국 이런 resource들을 하나씩 확인하는 과정에 가깝습니다.


2. "Everything is a file"

Linux를 공부하면서 자주 듣게 되는 표현이 있습니다.

Everything is a file.

조금 과장된 표현이지만 Linux의 설계를 이해하는 데 상당히 유용합니다.

일반적인 파일뿐 아니라 device나 process와 관련된 많은 정보도 file system을 통해 접근할 수 있습니다.

예를 들어 다음 경로를 살펴볼 수 있습니다.

/dev
/proc
/sys

/dev에는 device를 나타내는 파일이 있습니다.

ls /dev

/proc에는 실행 중인 process와 Kernel 상태에 대한 정보가 노출됩니다.

현재 system의 memory 정보를 보고 싶다면 다음 파일을 확인할 수 있습니다.

cat /proc/meminfo

CPU 정보도 마찬가지입니다.

cat /proc/cpuinfo

특정 process의 PID가 1234라면 해당 process의 정보도 확인할 수 있습니다.

ls /proc/1234

Linux에서는 이렇게 Kernel 내부의 여러 정보를 file interface를 통해 관찰할 수 있습니다.


3. Linux File System 구조

Linux server에 처음 접속하면 가장 먼저 익숙해져야 하는 것 중 하나가 directory 구조입니다.

최상위에는 /가 있습니다.

/
├── bin
├── dev
├── etc
├── home
├── proc
├── tmp
├── usr
└── var

각 directory에는 대략적인 역할이 있습니다.

/etc

System과 application의 configuration이 주로 위치합니다.

ls /etc

예를 들어 SSH 설정은 일반적으로 다음 경로에서 찾을 수 있습니다.

/etc/ssh/

/var

실행 중인 system에서 지속적으로 변경되는 데이터가 위치합니다.

대표적으로 log가 있습니다.

/var/log

Server에서 문제가 발생했을 때 자주 확인하게 되는 directory입니다.

/home

일반 user의 home directory입니다.

/home/username

현재 사용자의 home directory는 ~로 표현할 수도 있습니다.

cd ~

/tmp

Temporary file을 저장하는 공간입니다.

Application이 임시 데이터를 저장할 때 자주 사용합니다.

/proc

실제 disk에 저장된 일반적인 directory와는 조금 다릅니다.

Kernel이 process와 system 정보를 제공하는 virtual filesystem입니다.

이 구조를 모두 외울 필요는 없습니다. 중요한 것은 어떤 종류의 정보를 어디에서 찾아야 하는지 감을 잡는 것입니다.


4. Process를 이해하면 Linux가 조금 쉬워진다

Linux에서 실행 중인 program은 process가 됩니다.

현재 process를 확인하는 가장 기본적인 방법 중 하나는 ps입니다.

ps aux

특정 application을 찾고 싶다면 grep과 함께 사용할 수도 있습니다.

ps aux | grep nginx

여기서 등장하는 |는 pipe입니다.

앞 명령어의 stdout을 다음 명령어의 stdin으로 전달합니다.

ps aux
   │
   │ stdout
   ↓
grep nginx

Linux shell의 강력함은 작은 program들을 이렇게 조합할 수 있다는 점에서 나옵니다.

예를 들어 log에서 error만 찾고 싶다면 다음처럼 사용할 수 있습니다.

cat application.log | grep ERROR

다만 grep이 직접 파일을 읽을 수 있으므로 실제로는 다음과 같이 쓰는 편이 더 간단합니다.

grep ERROR application.log

실시간으로 process를 관찰하고 싶다면 다음 명령도 유용합니다.

top

환경에 설치되어 있다면 htop을 사용할 수도 있습니다.


5. Process가 종료되지 않는다면?

Server를 운영하다 보면 특정 process를 종료해야 할 때가 있습니다.

먼저 PID를 확인합니다.

ps aux | grep my-application

PID가 1234라고 가정해 보겠습니다.

kill 1234

많은 경우 여기서 바로 kill -9를 사용하는 모습을 볼 수 있습니다.

kill -9 1234

하지만 둘은 의미가 다릅니다.

기본 kill은 일반적으로 SIGTERM을 전달합니다.

SIGTERM
"종료할 시간을 줄 테니 정상적으로 종료해."

반면 kill -9는 SIGKILL입니다.

SIGKILL
"즉시 종료."

SIGKILL은 process가 cleanup 작업을 수행할 기회를 주지 않습니다.

따라서 일반적으로는 SIGTERM으로 정상 종료를 시도하고, process가 응답하지 않을 때 SIGKILL을 고려하는 편이 안전합니다.

kill -TERM 1234

# 종료되지 않는 경우
kill -KILL 1234

작은 차이지만 production server를 다룰 때는 꽤 중요합니다.


6. Permission: "왜 Permission denied가 나오지?"

Linux를 사용하다 보면 높은 확률로 다음 메시지를 만나게 됩니다.

Permission denied

File permission을 확인해 보겠습니다.

ls -l

결과는 다음과 비슷합니다.

-rwxr-xr-- 1 ubuntu developers 1024 Sep 4 09:30 deploy.sh

앞부분의 permission을 나누어 보면 다음과 같습니다.

rwx | r-x | r--
 ↓     ↓     ↓
user  group others

각 문자는 다음 의미를 가집니다.

r = read
w = write
x = execute

숫자로 표현할 수도 있습니다.

r = 4
w = 2
x = 1

그래서 다음 명령은 owner에게 read/write/execute 권한을 주고, group과 others에는 read/execute 권한을 부여합니다.

chmod 755 deploy.sh

계산하면 다음과 같습니다.

7 = 4 + 2 + 1 = rwx
5 = 4 + 0 + 1 = r-x
5 = 4 + 0 + 1 = r-x

여기서 중요한 습관이 하나 있습니다.

Permission 문제가 발생했다고 무조건 다음과 같이 해결하지 않는 것입니다.

chmod 777 some-file

당장은 문제가 사라질 수 있지만 필요 이상의 권한을 열어 두게 됩니다.

먼저 owner와 group을 확인하고 어떤 process가 해당 파일에 접근해야 하는지 파악하는 편이 좋습니다.

ls -l some-file
id

7. Log를 읽는 기본 도구

Production server에서 문제가 발생하면 가장 먼저 보는 것 중 하나가 log입니다.

파일의 마지막 부분을 확인하려면 tail을 사용할 수 있습니다.

tail application.log

마지막 100줄을 보고 싶다면 다음과 같이 실행합니다.

tail -n 100 application.log

새로운 log를 실시간으로 확인하려면 -f 옵션을 사용합니다.

tail -f application.log

특정 error를 검색하려면 grep을 사용할 수 있습니다.

grep "ERROR" application.log

앞뒤 문맥까지 보고 싶다면 다음과 같이 실행할 수 있습니다.

grep -C 3 "ERROR" application.log

systemd를 사용하는 환경에서는 journalctl도 자주 사용합니다.

journalctl

특정 service의 log를 확인할 수도 있습니다.

journalctl -u nginx

최근 log를 실시간으로 보고 싶다면 다음과 같이 실행합니다.

journalctl -u nginx -f

장애 상황에서는 단순히 error 한 줄만 보는 것보다 그 직전에 어떤 일이 있었는지 함께 확인하는 것이 중요합니다.


8. Disk 문제 확인하기

Application에서 갑자기 파일을 저장하지 못하거나 database가 비정상적으로 동작한다면 disk 상태도 확인해 볼 필요가 있습니다.

가장 먼저 사용할 수 있는 명령은 다음과 같습니다.

df -h

Filesystem별 사용량을 사람이 읽기 쉬운 단위로 보여줍니다.

특정 directory가 얼마나 많은 공간을 사용하는지도 확인할 수 있습니다.

du -sh /var/log

하위 directory별로 확인하려면 다음과 같이 실행할 수 있습니다.

du -h --max-depth=1 /var

여기서 중요한 점은 df와 du가 서로 다른 질문에 답한다는 것입니다.

df → filesystem에 공간이 얼마나 남았는가?
du → 특정 directory/file이 공간을 얼마나 사용하고 있는가?

Disk가 가득 찼다면 큰 파일을 무작정 삭제하기 전에 어떤 application이 생성한 데이터인지 확인해야 합니다.

Log라면 rotation 설정이 잘못되었을 수도 있고, application이 예상보다 많은 temporary file을 생성하고 있을 수도 있습니다.


9. Memory 문제 확인하기

Memory 상태를 빠르게 확인할 때는 다음 명령을 사용할 수 있습니다.

free -h

처음 Linux memory를 확인하면 used 값이 생각보다 커 보여 당황할 수 있습니다.

Linux는 사용하지 않는 memory를 cache 등에 적극적으로 활용합니다.

따라서 단순히 used 숫자 하나만 보고 "memory가 부족하다"고 판단하기보다는 available, swap 사용량, process별 memory 사용량 등을 함께 확인해야 합니다.

Process별 상태는 다음처럼 확인할 수 있습니다.

top

Memory 사용량을 기준으로 process를 정렬할 수도 있습니다.

ps aux --sort=-%mem | head

Memory 부족이 의심된다면 Kernel log에서 OOM(Out Of Memory) 관련 기록도 확인할 수 있습니다.

journalctl -k | grep -i oom

환경에 따라 다음과 같이 확인하는 것도 가능합니다.

dmesg | grep -i oom

10. "서버가 느려요"라는 문제를 만났을 때

이제 실제 상황을 하나 생각해 보겠습니다.

사용자가 다음과 같이 이야기합니다.

서버가 갑자기 느려졌어요.

이 말만으로 원인을 알기는 어렵습니다.

그래서 범위를 하나씩 좁혀 나가야 합니다.

먼저 system load와 process 상태를 확인합니다.

uptime
top

CPU를 많이 사용하는 process가 있는지 확인합니다.

ps aux --sort=-%cpu | head

Memory도 확인합니다.

free -h

Disk 공간도 봅니다.

df -h

그리고 application과 system log를 확인합니다.

journalctl -p err

Network service라면 listening port도 확인해 볼 수 있습니다.

ss -lntp

전체적인 troubleshooting 흐름을 단순화하면 다음과 같습니다.

증상 확인
   ↓
Process / CPU
   ↓
Memory
   ↓
Disk
   ↓
Network
   ↓
Application / System Log
   ↓
원인 범위 좁히기

여기서 핵심은 처음부터 원인을 단정하지 않는 것입니다.

"느리니까 CPU 문제겠지"라고 생각하면 CPU만 보게 됩니다.

반대로 Linux가 관리하는 주요 resource를 순서대로 확인하면 훨씬 체계적으로 문제를 좁혀갈 수 있습니다.


11. 자주 사용하는 Linux 명령어

마지막으로 실제 작업에서 자주 사용하는 명령어를 목적별로 정리해 보겠습니다.

파일 탐색

pwd
ls -al
cd /path
find /var/log -name "*.log"

파일 내용 확인

cat file.txt
less file.txt
head file.txt
tail file.txt
tail -f application.log

문자열 검색

grep "ERROR" application.log
grep -R "DATABASE_URL" .

Process

ps aux
top
kill PID

System resource

free -h
df -h
du -sh /path
uptime

Network

ip addr
ss -lntp
curl https://example.com

Permission

ls -l
chmod 755 file
chown user:group file

이 명령어들을 전부 외우는 것보다 어떤 문제에서 어떤 정보를 확인해야 하는지 연결해서 기억하는 편이 좋습니다.


마무리

Linux를 잘 사용한다는 것은 많은 명령어를 외우는 것과 조금 다릅니다.

Linux가 application을 process로 실행하고, Kernel이 CPU와 memory 같은 resource를 관리하며, file system과 permission을 통해 resource에 접근하도록 만든다는 큰 구조를 이해하는 것이 먼저입니다.

그 구조가 보이기 시작하면 명령어도 자연스럽게 연결됩니다.

Process가 궁금하다 → ps, top
Memory가 궁금하다  → free
Disk가 궁금하다    → df, du
Network가 궁금하다 → ss, ip
Log가 궁금하다     → tail, grep, journalctl

결국 Linux에서 troubleshooting을 한다는 것은 "무슨 명령어를 입력해야 하지?"를 맞히는 일이 아닙니다.

현재 어떤 resource에서 문제가 발생하고 있는지 관찰하고, 증거를 모아 원인의 범위를 좁혀 가는 과정​에 가깝습니다.

Linux를 처음 공부한다면 명령어를 하나 더 외우는 것보다, 오늘 실행한 명령어가 Kernel과 system의 어떤 정보를 보여 주고 있는지 한 번 더 생각해 보는 것을 추천합니다.

그 순간부터 Linux가 단순한 검은 terminal 화면이 아니라, 관찰할 수 있는 하나의 system으로 보이기 시작합니다.

Tags

태그

LinuxDevOpsServerShellBashProcessFile System