리눅스 필수 명령어
프로세스·메모리·디스크·텍스트·네트워크·systemd를 다루는 Linux 명령을 서버 운영 상황별로 익힙니다.
서버 개발자에게 리눅스 명령어는 도구 상자입니다.
서버 장애가 발생했을 때, 성능 문제를 추적할 때, 배포 스크립트를 작성할 때 — 이 명령어들을 자유자재로 사용할 수 있어야 합니다.
이 절에서는 실무에서 가장 자주 사용하는 명령어들을 범주별로 정리합니다.
리눅스 명령어는 장애 원인, 리소스 사용량, 배포 스크립트 상태를 터미널에서 직접 확인하는 운영 도구입니다.
- 증상별로 먼저 확인할 명령 선택
ps aux의 PID, STAT, TIME, COMMAND 열로 병목과 종료 대상을 구분합니다. 2 free -h에서 available 열이 실제로 프로세스가 사용할 수 있는 메모리입니다. 3 디스크가 가득 찼는데 df와 du가 맞지 않으면 삭제됐지만 열린 파일을 lsof +L1로 찾습니다. 4 ss -s로 TIME WAIT 소켓 수를 확인합니다.
- 프로세스 관리
ps aux의 PID, STAT, TIME, COMMAND 열로 병목과 종료 대상을 구분합니다.
- 메모리 확인
free -h에서 available 열이 실제로 프로세스가 사용할 수 있는 메모리입니다.
- 디스크와 파일
디스크가 가득 찼는데 df와 du가 맞지 않으면 삭제됐지만 열린 파일을 lsof +L1로 찾습니다.
- 네트워크
ss -s로 TIME WAIT 소켓 수를 확인합니다.
- 종료·메모리·디스크 신호 해석
신호 이름, 번호, 기본 동작, 사용 예시를 함께 비교합니다. 강제 종료 신호는 처리 가능 여부와 정리 기회를 구분해 봅니다. available은 캐시 회수 가능성을 반영하므로 used 값만 보고 메모리 부족을 판단하지 않습니다.
프로세스 관리
# 현재 실행 중인 프로세스 목록
ps aux
# CPU/메모리 사용량 기준 상위 프로세스
ps aux --sort=-%cpu | head -10
ps aux --sort=-%mem | head -10
# 프로세스 트리 (부모-자식 관계)
ps auxf
pstree -p 1234
# 실시간 모니터링
top
htop # 더 직관적인 인터페이스ps aux의 출력에서 각 열의 의미를 알아두면 좋습니다.
| 열 | 의미 | 예시 |
|---|---|---|
| USER | 프로세스 소유자 | root, www-data |
| %CPU | CPU 사용률 | 95.3 |
| %MEM | 메모리 사용률 | 12.4 |
| VSZ | 가상 메모리 크기 (KB) | 주소 공간 전체 |
| RSS | 실제 물리 메모리 (KB) | 실제 사용량 |
| STAT | 상태 | S(sleep), R(run), Z(zombie), D(disk wait) |
| TIME+ | 누적 CPU 시간 | 03:42:15 |
# 시그널 전송
kill -15 1234 # SIGTERM: 정상 종료 요청
kill -9 1234 # SIGKILL: 강제 종료 (최후 수단)
kill -1 1234 # SIGHUP: 설정 다시 읽기 (데몬)
kill -USR1 1234 # SIGUSR1: 애플리케이션 정의 시그널
# 이름으로 프로세스 종료
pkill -f "python.*worker"
killall nginx
# 프로세스 우선순위 변경
nice -n 10 ./heavy_job # 낮은 우선순위로 실행
renice -n -5 -p 1234 # 실행 중 프로세스 우선순위 변경SIGTERM(15)을 먼저 보내고, 응답이 없을 때만 SIGKILL(9)을 사용합니다.
SIGKILL은 프로세스에게 정리할 기회를 주지 않으므로 파일이 손상되거나 임시 자원이 남을 수 있습니다.
| 시그널 | 번호 | 기본 동작 | 잡을 수 있나 | 용도 |
|---|---|---|---|---|
| SIGHUP | 1 | 종료 | O | 데몬 설정 리로드 |
| SIGINT | 2 | 종료 | O | Ctrl+C |
| SIGKILL | 9 | 강제 종료 | X | 최후의 수단 |
| SIGTERM | 15 | 종료 | O | 정상 종료 요청 |
| SIGSTOP | 19 | 일시 정지 | X | 디버깅 |
| SIGCONT | 18 | 재개 | O | 정지된 프로세스 재개 |
백그라운드 작업
# 백그라운드 실행
./long_task.sh &
# 현재 백그라운드 작업 목록
jobs -l
# 포그라운드로 전환
fg %1
# 실행 중인 작업을 백그라운드로
# Ctrl+Z로 일시 정지 후
bg %1
# 터미널 종료 후에도 실행 유지
nohup ./server.sh > output.log 2>&1 &
# 또는 screen/tmux 사용 (권장)
tmux new -s worker
# ... 작업 실행 ...
# Ctrl+B, D 로 detach
tmux attach -t workernohup은 SIGHUP을 무시하여 터미널이 닫혀도 프로세스가 살아남습니다.
하지만 실무에서는 tmux나 screen을 사용하는 것이 더 편리합니다.
서버가 느리거나 멈춘 것처럼 보일 때는 프로세스, 메모리, 디스크, 네트워크, 서비스 순서로 큰 병목부터 확인한다.
- 1프로세스
CPU ps, top, htop으로 점유율과 상태 코드를 먼저 본다.
- 2메모리
MEM free와 vmstat에서 available, swap, I/O wait를 구분한다.
- 3디스크
DISK df, du, lsof +L1로 용량과 삭제된 열린 파일을 확인한다.
- 4네트워크
NET ss, curl, dig, tcpdump로 포트와 연결 흐름을 나눈다.
- 5서비스
SVC systemctl과 journalctl로 재시작 여부와 최근 로그를 확인한다.
메모리 확인
# 시스템 메모리 요약
free -h
# total used free shared buff/cache available
# Mem: 16Gi 8.2Gi 1.1Gi 256Mi 6.7Gi 7.3Gi
# Swap: 4Gi 0.5Gi 3.5Gi
# 상세 메모리 정보
cat /proc/meminfo | grep -E "MemTotal|MemFree|MemAvailable|Buffers|Cached|SwapTotal|SwapFree"
# 가상 메모리 통계 (2초 간격)
vmstat 2
# 특정 프로세스의 메모리 맵
pmap -x 1234
# 공유 메모리 확인
ipcs -mfree -h에서 available 열이 실제로 프로세스가 사용할 수 있는 메모리입니다.
buff/cache는 OS가 I/O 성능을 위해 사용 중이지만, 필요하면 반환되는 메모리입니다.
used가 높아도 available이 충분하면 메모리 부족이 아닙니다.
import subprocess
import re
def check_memory():
"""시스템 메모리 상태를 확인하고 경고"""
result = subprocess.run(["free", "-b"], capture_output=True, text=True)
lines = result.stdout.strip().split("\n")
mem = lines[1].split()
total = int(mem[1])
available = int(mem[6])
usage_pct = (1 - available / total) * 100
print(f"전체: {total // (1024**3)}GB")
print(f"사용 가능: {available // (1024**3)}GB")
print(f"사용률: {usage_pct:.1f}%")
if usage_pct > 90:
print("[위험] 메모리 부족!")
# 메모리 많이 쓰는 프로세스 상위 5개
ps = subprocess.run(
["ps", "aux", "--sort=-%mem"],
capture_output=True, text=True
)
for line in ps.stdout.split("\n")[1:6]:
print(f" {line}")
elif usage_pct > 70:
print("[주의] 메모리 사용률이 높습니다.")
check_memory()디스크와 파일
# 파일 시스템 사용량
df -h
# inode 사용량 (파일 수 제한)
df -i
# 디렉토리 크기 (깊이 1)
du -h --max-depth=1 /var | sort -rh | head -10
# 큰 파일 찾기
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null
# 최근 24시간 내 수정된 파일
find /var/log -type f -mtime -1
# 파일을 열고 있는 프로세스 확인
lsof /var/log/syslog
# 삭제되었지만 프로세스가 잡고 있는 파일 찾기 (공간 미회복)
lsof +L1디스크가 가득 찬 상황에서 lsof +L1은 매우 유용합니다.
파일을 삭제했는데 공간이 회복되지 않는다면, 프로세스가 여전히 삭제된 파일의 파일 디스크립터를 열고 있는 것입니다.
해당 프로세스를 재시작하면 공간이 회복됩니다.
# 프로세스별 I/O 사용량
iotop
# 디스크별 I/O 통계 (2초 간격)
iostat -xz 2
# 출력 핵심 열:
# %util: 디스크 사용률 (100%에 가까우면 병목)
# await: 평균 I/O 대기 시간 (ms)
# r/s, w/s: 초당 읽기/쓰기 요청 수텍스트 처리
서버 로그 분석에 필수인 텍스트 처리 명령어입니다.
# 패턴 검색
grep -rn "ERROR" /var/log/app/ # 재귀, 줄 번호 포함
grep -c "404" access.log # 404 에러 횟수
grep -v "healthcheck" access.log # healthcheck 제외
# 실시간 로그 모니터링
tail -f /var/log/app/error.log
tail -f /var/log/app/error.log | grep --line-buffered "CRITICAL"
# 정렬과 중복 제거
sort access.log | uniq -c | sort -rn | head -20
# 필드 추출 (awk)
# 접속 IP별 요청 수 (Apache/Nginx 로그)
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# 특정 시간대의 요청 수
awk '/15:3[0-9]:/' access.log | wc -l
# 문자열 치환 (sed)
sed -i 's/old_domain/new_domain/g' config.conf
# JSON 처리 (jq)
cat response.json | jq '.data[] | {id, name, status}'로그를 줄이고, 필요한 필드만 모아, 빈도와 원본을 차례로 확인한다.
- 1필터링
grep으로 오류, 상태 코드, 시간대를 먼저 줄인다.
- 2필드 추출
awk와 jq로 IP, 경로, 응답 시간 같은 열만 남긴다.
- 3정렬과 집계
sort와 uniq로 많이 등장한 값과 패턴을 찾는다.
- 4원본 확인
집계 결과의 실제 로그 줄을 다시 열어 원인을 확인한다.
- 5실시간 대응
tail과 grep을 조합해 배포 직후 새 오류가 늘어나는지 관찰한다.
- 6반복 분석
자주 쓰는 파이프라인은 스크립트로 남겨 장애 대응 시간을 줄인다.
네트워크
# 열린 포트와 연결 상태
ss -tlnp # TCP 리스닝 포트
ss -tanp # 모든 TCP 연결
ss -s # 연결 상태 요약 (established, time-wait 수)
# 특정 포트에 연결된 프로세스
ss -tlnp | grep :8080
# 네트워크 인터페이스 정보
ip addr show
ip route show # 라우팅 테이블
# 연결 테스트
ping -c 4 10.0.0.1
traceroute 10.0.0.1
mtr 10.0.0.1 # ping + traceroute 합체
# DNS 조회
dig example.com
nslookup example.com
# 특정 포트 연결 테스트
nc -zv 10.0.0.1 3306 # MySQL 포트 열려있는지
# 패킷 캡처 (tcpdump)
tcpdump -i eth0 port 80 -c 100
tcpdump -i any host 10.0.0.1 -w capture.pcap
# HTTP 요청 테스트
curl -v https://api.example.com/health
curl -o /dev/null -s -w "%{http_code} %{time_total}s\n" https://api.example.comss -s로 TIME_WAIT 소켓 수를 확인합니다.
TIME_WAIT이 수만 개라면 짧은 연결이 과도하게 생성되고 있다는 뜻이며, Connection Pool이나 Keep-Alive를 검토해야 합니다.
CPU, 메모리, 디스크, 네트워크 신호를 한 번에 보지 말고 증상별로 먼저 볼 지점을 정한다.
- 1Symptom
느림/멈춤/오류 사용자 관찰
- 2Signal
CPU/mem/disk/net 첫 지표
- 3Command
top, df, ss 확인 도구
- 4Decision
원인 좁힘 다음 조치
방화벽과 포트 관리
# iptables 규칙 확인
iptables -L -n -v
# ufw (Ubuntu 방화벽)
ufw status
ufw allow 22/tcp
ufw allow from 10.0.0.0/24 to any port 3306
# firewalld (CentOS/RHEL)
firewall-cmd --list-all
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reloadsystemd 서비스 관리
# 서비스 상태 확인
systemctl status nginx
# 서비스 시작/중지/재시작
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl reload nginx # 무중단 설정 리로드
# 부팅 시 자동 시작
systemctl enable nginx
systemctl disable nginx
# 서비스 로그 확인
journalctl -u nginx -f
journalctl -u nginx --since "1 hour ago"
# 실패한 서비스 확인
systemctl --failed[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server
Restart=on-failure
RestartSec=5
LimitNOFILE=65535
[Install]
WantedBy=multi-user.targetRestart=on-failure로 프로세스가 비정상 종료되면 5초 후 자동 재시작합니다.
LimitNOFILE로 파일 디스크립터 제한을 설정합니다.
다음 절에서는 시스템 콜 추적과 로그 분석 등 심층 디버깅 기법을 다루겠습니다.
운영 중 프로세스를 볼 때는 이름보다 PID, 상태, CPU/메모리 사용량, 열린 파일, signal 처리 관계가 더 중요하다.
- 상태 우선 검토
CPU를 쓰는지, I/O를 기다리는지, zombie로 남았는지 상태 문자와 wait channel을 확인한다.
- 자원 사용량을 묶는다
CPU만 높은지, RSS가 커지는지, fd가 누수되는지 지표별로 원인을 나눈다.
- 부모 관계를 추적한다
서비스 매니저, shell, worker parent가 자식을 어떻게 시작하고 회수하는지 본다.
- 상태
프로세스가 CPU bound인지 I/O wait인지 상태로 구분하는가.
- 자원
메모리 증가가 heap 누수인지 cache인지 추가 관찰하는가.
- 종료
SIGTERM으로 graceful shutdown이 가능한지 확인하는가.
ps -o pid,ppid,state,pcpu,pmem,comm
lsof -p <pid>
kill -TERM <pid>