글 목록

DevOps

개발자가 알아두면 좋은 Ubuntu 기본기: 패키지부터 서비스 관리까지

Ubuntu를 개발 및 서버 환경에서 사용하기 위해 알아두면 좋은 디렉터리 구조, APT 패키지 관리, 권한, 프로세스, systemd, 로그와 네트워크 명령어를 정리합니다.

Ubuntu, 단순히 Linux 배포판이라고만 알고 있었다면

개발을 하다 보면 Ubuntu를 꽤 자주 만나게 됩니다.

로컬 개발 환경으로 직접 사용할 수도 있지만, AWS EC2 같은 클라우드 서버에 접속했을 때 Ubuntu가 설치되어 있는 경우도 많습니다. Docker 이미지의 기반 OS로 Ubuntu를 선택하는 경우도 있고요.

처음에는 필요한 명령어를 검색해서 하나씩 실행하는 것만으로도 충분합니다.

sudo apt update
sudo apt install nginx

그런데 서버를 직접 관리하기 시작하면 이야기가 조금 달라집니다.

apt update와 apt upgrade는 무엇이 다른지, /etc에는 왜 그렇게 많은 파일이 있는지, sudo는 정확히 무엇을 하는지, 실행 중인 서비스는 어떻게 확인하는지 알아야 문제가 생겼을 때 원인을 찾을 수 있습니다.

이번 글에서는 Ubuntu를 사용할 때 자주 만나게 되는 기본적인 개념들을 하나씩 살펴보겠습니다.


Ubuntu는 무엇인가?

Ubuntu는 Debian을 기반으로 만들어진 Linux 배포판(Linux distribution)​입니다.

여기서 Linux와 Ubuntu를 같은 것으로 생각하기 쉽지만 정확히는 조금 다릅니다.

Linux는 운영체제의 핵심 역할을 담당하는 kernel을 의미하고, Ubuntu는 Linux kernel을 기반으로 패키지 관리 시스템과 각종 기본 프로그램을 함께 제공하는 Linux distribution입니다.

쉽게 표현하면 다음과 같습니다.

Linux Kernel
    ↓
Debian
    ↓
Ubuntu

Ubuntu가 서버 환경에서 많이 사용되는 이유 중 하나는 비교적 큰 사용자 및 개발자 생태계와 함께 패키지 관리가 편리하다는 점입니다.

특히 서버에서는 GUI 없이 Ubuntu Server를 설치하고 SSH와 CLI를 통해 관리하는 경우가 일반적입니다.


가장 먼저 확인하는 Ubuntu 버전

서버에 처음 접속했다면 현재 어떤 Ubuntu 버전을 사용하고 있는지 확인해 두는 것이 좋습니다.

cat /etc/os-release

또는 다음 명령어를 사용할 수 있습니다.

lsb_release -a

커널 정보는 다음과 같이 확인합니다.

uname -a

여기서 중요한 점은 Ubuntu 버전과 Linux kernel 버전은 서로 다른 정보라는 것입니다.

문제를 검색할 때도 단순히 "Ubuntu에서 안 됩니다"라고 검색하는 것보다 실제 Ubuntu 버전과 관련 소프트웨어 버전을 함께 확인하는 편이 훨씬 정확합니다.


Ubuntu의 디렉터리 구조

Windows 환경에 익숙하다면 Linux의 디렉터리 구조가 처음에는 조금 낯설 수 있습니다.

Ubuntu에서는 /가 파일 시스템의 시작점입니다.

/
├── bin
├── boot
├── dev
├── etc
├── home
├── opt
├── tmp
├── usr
└── var

모든 디렉터리를 외울 필요는 없습니다. 개발이나 서버 운영에서는 몇 가지 위치부터 익혀두면 충분합니다.

/home

일반 사용자의 홈 디렉터리가 위치합니다.

예를 들어 ubuntu 사용자의 홈은 보통 다음과 같습니다.

/home/ubuntu

현재 사용자의 홈 디렉터리는 ~로 표현할 수도 있습니다.

cd ~

/etc

시스템과 애플리케이션의 설정 파일을 주로 찾게 되는 곳입니다.

예를 들어 Nginx를 설치했다면 설정 파일은 일반적으로 /etc/nginx 아래에서 확인합니다.

ls /etc/nginx

/var

로그나 캐시처럼 실행 과정에서 계속 변경되는 데이터를 주로 저장합니다.

서버 문제를 확인하면서 자주 방문하게 되는 위치 중 하나가 다음 디렉터리입니다.

/var/log

/tmp

임시 파일을 저장하는 공간입니다.

애플리케이션에서 일시적으로 필요한 데이터를 저장할 때 사용되지만 영구적인 데이터를 보관하는 장소로 사용해서는 안 됩니다.


apt update와 apt upgrade의 차이

Ubuntu에서 패키지를 관리할 때 가장 자주 사용하는 도구가 APT입니다.

새로운 서버를 설정하면서 다음 명령어를 한 번쯤 실행해 봤을 것입니다.

sudo apt update
sudo apt upgrade

두 명령어는 비슷해 보이지만 역할이 다릅니다.

apt update는 패키지 목록(package index)을 최신 상태로 업데이트​합니다.

즉, 실제 프로그램을 업데이트하는 명령어가 아닙니다.

sudo apt update

반면 apt upgrade는 업데이트된 패키지 정보를 기준으로 설치되어 있는 패키지를 업그레이드합니다.

sudo apt upgrade

따라서 일반적으로 다음과 같이 함께 사용합니다.

sudo apt update
sudo apt upgrade

새로운 패키지를 설치할 때는 다음과 같이 사용합니다.

sudo apt install nginx

삭제는 다음과 같습니다.

sudo apt remove nginx

설치된 패키지를 확인하고 싶다면 dpkg도 사용할 수 있습니다.

dpkg -l

sudo는 왜 사용하는가?

Ubuntu를 사용하다 보면 거의 모든 설치 문서에서 sudo를 만나게 됩니다.

sudo apt install nginx

Linux에서는 일반 사용자와 시스템 관리 권한을 가진 사용자를 구분합니다.

시스템 전체에 영향을 주는 작업은 일반 사용자 권한으로 실행할 수 없는 경우가 많습니다.

sudo를 사용하면 허용된 사용자가 특정 명령을 높은 권한으로 실행할 수 있습니다.

현재 사용자는 다음 명령으로 확인할 수 있습니다.

whoami

현재 사용자의 ID와 그룹 정보는 다음과 같이 확인합니다.

id

모든 작업을 관리자 권한으로 실행하는 습관은 피하는 것이 좋습니다.

권한이 필요하지 않은 작업까지 sudo로 실행하면 실수 하나가 시스템 전체에 영향을 줄 수 있기 때문입니다.


파일 권한 이해하기

Ubuntu에서 파일을 확인하면 다음과 비슷한 정보를 볼 수 있습니다.

ls -l

예를 들어 결과가 다음과 같다고 가정해 보겠습니다.

-rwxr-xr-- 1 ubuntu developers 1024 Sep 4 10:00 deploy.sh

앞부분의 다음 값이 파일의 권한을 나타냅니다.

rwxr-xr--

권한은 크게 세 가지입니다.

권한 의미
r read
w write
x execute

그리고 각각의 권한은 세 그룹에 적용됩니다.

  • owner — 파일 소유자
  • group — 파일이 속한 그룹
  • others — 그 외 사용자

권한을 변경할 때는 chmod를 사용합니다.

chmod +x deploy.sh

파일의 소유자를 변경하려면 chown을 사용합니다.

sudo chown ubuntu:developers deploy.sh

서버에서 발생하는 상당수의 문제는 결국 권한 문제로 이어지기도 합니다.

특히 애플리케이션이 "파일은 존재하는데 읽지 못한다"​거나 "로그 파일을 생성할 수 없다"​고 한다면 파일 및 디렉터리 권한부터 확인해 볼 가치가 있습니다.


프로세스 확인하기

서버에서 애플리케이션이 정상적으로 실행되고 있는지 확인하려면 프로세스를 살펴볼 필요가 있습니다.

가장 기본적인 방법은 ps입니다.

ps aux

특정 프로세스를 찾고 싶다면 grep과 함께 사용할 수 있습니다.

ps aux | grep nginx

실시간으로 시스템 상태를 확인하고 싶다면 top을 사용할 수 있습니다.

top

PID를 알고 있는 프로세스를 종료하려면 다음과 같이 실행합니다.

kill 1234

무조건 kill -9부터 사용하는 것은 권장하지 않습니다.

일반적인 kill은 프로세스가 종료 작업을 처리할 기회를 주지만 SIGKILL은 프로세스를 즉시 종료하기 때문입니다.


systemd로 서비스 관리하기

Ubuntu 서버에서 Nginx나 PostgreSQL 같은 프로그램을 설치하면 systemd를 통해 서비스로 관리하는 경우가 많습니다.

이때 사용하는 대표적인 명령어가 systemctl입니다.

Nginx 상태를 확인해 보겠습니다.

sudo systemctl status nginx

서비스를 시작하려면 다음과 같이 실행합니다.

sudo systemctl start nginx

중지할 때는 다음과 같습니다.

sudo systemctl stop nginx

재시작도 가능합니다.

sudo systemctl restart nginx

서버가 부팅될 때 자동으로 서비스를 실행하도록 설정하려면 다음 명령어를 사용할 수 있습니다.

sudo systemctl enable nginx

반대로 자동 시작을 비활성화하려면 다음과 같습니다.

sudo systemctl disable nginx

운영 서버를 관리한다면 systemctl은 자연스럽게 자주 사용하게 되는 명령어 중 하나입니다.


문제가 생겼다면 로그부터 확인하자

서비스가 실행되지 않을 때 무작정 재설치부터 하는 것보다 먼저 로그를 확인하는 편이 좋습니다.

systemd가 관리하는 서비스의 로그는 journalctl을 통해 확인할 수 있습니다.

sudo journalctl -u nginx

최근 로그를 계속 확인하려면 -f 옵션을 사용할 수 있습니다.

sudo journalctl -u nginx -f

애플리케이션이 별도의 로그 파일을 사용한다면 /var/log도 확인합니다.

ls /var/log

파일의 마지막 부분을 실시간으로 확인할 때 tail도 유용합니다.

tail -f /var/log/nginx/error.log

서버 장애를 분석할 때는 대략 다음과 같은 흐름으로 접근할 수 있습니다.

서비스 상태 확인
        ↓
systemctl status
        ↓
journalctl 확인
        ↓
애플리케이션 로그 확인
        ↓
프로세스 / 포트 / 권한 확인

처음부터 원인을 예상해서 이것저것 수정하기보다 실제 오류 메시지를 먼저 확보하는 것이 훨씬 효율적입니다.


포트가 열려 있는지 확인하기

웹 서버를 실행했는데 접속할 수 없다면 애플리케이션이 실제로 해당 포트에서 실행 중인지 확인해야 합니다.

Ubuntu에서는 ss를 사용할 수 있습니다.

ss -lntp

예를 들어 80번 포트를 확인하려면 다음과 같이 사용할 수 있습니다.

sudo ss -lntp | grep :80

HTTP 요청 자체를 테스트할 때는 curl도 유용합니다.

curl http://localhost

외부에서는 접속되지 않는데 localhost에서는 정상적으로 응답한다면 애플리케이션 자체보다 다음과 같은 네트워크 설정을 확인해야 할 가능성이 높습니다.

  • Firewall
  • Cloud Security Group
  • Reverse Proxy
  • Port forwarding
  • 애플리케이션의 bind address

즉, 프로세스가 실행되고 있다는 것과 외부에서 해당 서비스에 접근할 수 있다는 것은 별개의 문제입니다.


디스크와 메모리 확인하기

서버 장애에서 의외로 자주 만나는 문제가 디스크 공간 부족입니다.

디스크 사용량은 다음 명령어로 확인합니다.

df -h

특정 디렉터리가 얼마나 많은 공간을 사용하는지 확인하려면 du를 사용할 수 있습니다.

du -sh /var/log/*

메모리는 다음과 같이 확인할 수 있습니다.

free -h

CPU와 프로세스 상태는 앞에서 살펴본 top으로 확인할 수 있습니다.

top

서버가 갑자기 느려졌다면 애플리케이션 코드만 보기 전에 CPU, memory, disk 같은 시스템 리소스도 함께 확인하는 것이 좋습니다.


Ubuntu 서버에서 문제가 발생했을 때 확인하는 순서

지금까지의 내용을 실제 상황에 적용해 보겠습니다.

예를 들어 배포 이후 API 서버에 접속할 수 없다고 가정하겠습니다.

1. 서비스 상태 확인

먼저 애플리케이션 서비스가 실행되고 있는지 확인합니다.

sudo systemctl status my-api

2. 로그 확인

서비스가 실패했다면 로그를 확인합니다.

sudo journalctl -u my-api -n 100

3. 포트 확인

프로세스가 정상적으로 실행 중이라면 실제 포트를 확인합니다.

sudo ss -lntp

4. 서버 내부에서 요청

서버 내부에서 직접 애플리케이션으로 요청을 보내봅니다.

curl http://localhost:8080

5. 시스템 리소스 확인

필요하다면 디스크와 메모리, CPU 상태도 확인합니다.

df -h
free -h
top

이런 기본적인 확인만으로도 문제의 범위를 상당히 줄일 수 있습니다.

핵심은 명령어를 많이 외우는 것이 아니라 다음과 같은 순서로 문제를 좁혀가는 습관입니다.

Service
   ↓
Log
   ↓
Process
   ↓
Network
   ↓
System Resource

자주 사용하는 명령어 한 번에 정리하기

마지막으로 지금까지 살펴본 명령어를 간단하게 정리해 보겠습니다.

목적 명령어
Ubuntu 버전 확인 cat /etc/os-release
Kernel 정보 확인 uname -a
패키지 목록 업데이트 sudo apt update
패키지 업그레이드 sudo apt upgrade
패키지 설치 sudo apt install <package>
파일 목록 및 권한 확인 ls -l
권한 변경 chmod
소유자 변경 chown
프로세스 확인 ps aux
시스템 상태 확인 top
서비스 상태 확인 systemctl status
서비스 로그 확인 journalctl
Listening port 확인 ss -lntp
HTTP 요청 테스트 curl
디스크 사용량 확인 df -h
메모리 사용량 확인 free -h

마무리

Ubuntu를 처음 사용할 때는 Linux 명령어를 얼마나 많이 알고 있는지가 중요해 보입니다.

하지만 실제 개발과 서버 운영에서는 모든 명령어를 외우고 있을 필요가 없습니다.

대신 다음 정도는 이해해 두는 것이 좋습니다.

/etc        → 설정
/var/log    → 로그

apt         → 패키지 관리
chmod       → 권한 변경
ps / top    → 프로세스 확인
systemctl   → 서비스 관리
journalctl  → 서비스 로그
ss          → 포트 확인
df / free   → 시스템 리소스 확인

Ubuntu에 익숙해진다는 것은 결국 명령어를 외우는 것보다 문제가 생겼을 때 어디를 확인해야 하는지 아는 것에 가깝습니다.

처음에는 apt, systemctl, journalctl 정도부터 익혀도 충분합니다.

실제 서버를 운영하면서 필요한 명령어를 하나씩 추가하다 보면 어느 순간 Ubuntu가 단순한 "Linux 서버"가 아니라, 문제가 발생했을 때 어느 부분부터 살펴봐야 하는지 구조가 보이기 시작할 것입니다.

Tags

태그

UbuntuLinuxDevOpsServerAPTsystemdCLI