알아두면 좋은 리눅스 디렉토리 구조 및 운영체제 관련 개념

8 minute read

어떤 언어를 사용해 개발을 하든 프로그램은 결국 운영체제 위에 파일들로 만들어져 작동하게 된다. 운영체제는 기본적으로 약속된 디렉토리 구조를 사용해 파일들을 관리하고 우리가 사용하는 프로그램들을 돌아가게 한다. 서버 관리자가 아니더라도 요새는 도커 사용이나 웹 서버를 구성하며 이런 디렉토리 구조를 몰라 많은 시간을 허비하게 되는 경우가 많다. 가장 많이 사용되는 리눅스를 통해 운영체제의 디렉토리 구조를 알아보자.

FHS ( Filesystem Hierarchy Standard ) - 주요 디렉토리

/assets/images//linux-directory.png

리눅스에서 모든 것은 파일로 표현된다. 디렉토리도 파일의 한 종류로서 여러개의 하위 파일이나 디렉토리의 주소들을 담고 있다. 리눅스에서는 Filesystem Hierarchy Standard(FHS)라는 디렉토리 구조를 활용해 파일들을 관리하고 이 위치에 따라 파일들을 참조하여 시스템을 동작시킨다.

먼저 개별 디렉토리들에 대해 간단히 알아보자. 이 글은 CentOS8을 기준으로 작성되었다.

CentOS8 root 디렉토리

.
|-- bin -> usr/bin
|-- boot
|-- dev
|-- etc
|-- home
|-- lib -> usr/lib
|-- lib64 -> usr/lib64
|-- lost+found
|-- media
|-- mnt
|-- opt
|-- proc
|-- root
|-- run
|-- sbin -> usr/sbin
|-- srv
|-- sys
|-- tmp
|-- usr
`-- var

tree 명령어를 통해 CentOS8의 root 디렉토리를 살펴보면 20개의 하위 디렉토리를 확인할 수 있다. 연관된 디렉토리끼리 묶어서 살펴보자.

bin, sbin

bin은 user command binaries, sbin은 system command binaries를 뜻한다. 둘 다 바이너리 파일로 컴파일된 실행 파일들을 포함하고 있다. 대체적으로 sbin은 system이 사용하거나 system을 컨트롤하기 위한 파일들을 포함하고 bin은 커맨드 라인 인터페이스에서 우리가 자주 사용하는 명령어 실행 파일들을 포함한다.

bin 디렉토리 일부

...
-r-xr-xr-x 1 root root      50 Apr 27  2020  cat
-rwxr-xr-x 1 root root    3283 Jul 20  2020  catchsegv
-rwxr-xr-x 1 root root   43912 May 11  2019  catman
-rwxr-xr-x 1 root root      26 Jul 21  2020  cd
-rwxr-xr-x 1 root root   17488 May 11  2019  chacl
-rwsr-xr-x 1 root root   79648 Aug 12  2020  chage
-r-xr-xr-x 1 root root      52 Apr 27  2020  chcon
-r-xr-xr-x 1 root root      52 Apr 27  2020  chgrp
...

bin 디렉토리에 가서 ls -al 커맨드를 쳐보면 위와 같은 결과를 볼 수 있다. 우리가 흔히 사용하는 cat, cd 등의 커맨드는 결국 bin 디렉토리에 포함된 해당 이름으로 된 바이너리 파일을 실행한 결과이다. ls 도 이 디렉토리 내에 포함되어 있다. 참고로 sbin 디렉토리는 sysctl, reboot 등과 같이 시스템을 다루는 파일들을 가지고 있다.

bin, sbin 연관 디렉토리

리눅스 이전 유닉스 운영체제를 만들 때 용량 문제로 꼭 필요한 파일과 그렇지 않은 파일을 분리해 관리하기 위해 bin과 sbin 디렉토리를 여러 곳에 분산시켜 만들었다. 현대 유닉스 기반 OS에서도 이런 사상이 남아서 bin과 sbin에 관련된 연관 디렉토리들이 파일 시스템에 남아있다.

연관된 디렉토리의 종류는 usr/bin, usr/sbin, usr/local/bin, usr/local/sbin이다. 전체적으로 차이점을 정리해보면 아래와 같다.

  • bin: cd, ls 등의 사용자 커맨드 파일이 위치한 디렉토리 (필수적인 파일만 관리)
  • sbin: systemctl 등의 시스템 커맨드 파일이 위치한 디렉토리 (필수적인 파일만 관리)
  • usr/bin: 필요에 의해 설치된 사용자 커맨드 파일이 위치한 디렉토리 (yum 등 패키지 관리자가 관리)
  • usr/sbin: 필요에 의해 설치된 시스템 커맨드 파일이 위치한 디렉토리 (yum 등 패키지 관리자가 관리)
  • usr/local/bin: 기타 사용자 커맨드 파일이 위치한 디렉토리 (사용자 또는 설치 파일이 해당 디렉토리에 파일 설치)
  • usr/local/sbin: 기타 시스템 커맨드 파일이 위치한 디렉토리 (사용자 또는 설치 파일이 해당 디렉토리에 파일 설치)

리눅스 기반 운영체제마다 bin, sbin 연관 디렉토리를 다루는 방법이 조금씩 다르다.

CentOS에서는 디렉토리 구조를 단순화하기 위해 심볼릭 링크로 bin과 sbin을 usr/bin과 usr/sbin과 동일하게 만들어버렸다 (bin -> usr/bin, sbin -> usr/sbin). bin과 sbin 디렉토리는 각각 usr/bin, usr/sbin 디렉토리와 연결되어 파일을 공유하는데 만약 usr/bin 디렉토리의 파일을 삭제하거나 변경하면 이와 연결된 bin 디렉토리의 파일도 똑같이 삭제되거나 변경된다.

리눅스는 아니지만 비슷한 유닉스 기반의 운영체제인 MacOS는 예전 방식대로 bin, sbin 디렉토리를 모두 분리해서 사용한다. CentOS의 yum과 달리 맥의 패키지 관리자인 brew로 설치되는 파일은 Cellar 디렉토리라는 별도의 디렉토리에 저장되며 usr/local/bin에 심볼릭 링크 형태로 관리된다.

운영체제마다 몇가지 차이점이 있으나 기본적으로 시스템의 특정 기능을 실행시키는 파일들을 bin과 sbin에 나누어 관리하고 관리방법에 따라 파일 시스템 내에 복수로 존재한다고만 알아두면 될 듯 싶다.

PATH와 bin, sbin

기본 PATH 목록

[root@l9c11z10a888 bin]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

bin과 sbin은 PATH와 밀접한 연관이 있다. bin과 sbin은 실행파일들의 집합이고 PATH는 운영체제 어디에서든 해당위치에 접근할 수 있게 만드는 환경변수다. 위에서 설명된 6개 디렉토리는 모두 기본 PATH 환경변수에 지정되어 있어 운영체제는 디렉토리에 있는 실행파일들을 어느 위치에서든 실행할 수 있다. 사용자 관점에서는 6개 디렉토리들 중 어느 하나에 실행파일이 있으면 cd, ls 처럼 파일이름으로 해당 커맨드 실행이 가능하다고 생각하면 된다.

brew나 yum 같은 패키지 관리자로 설치한 파일들은 6개 디렉토리 중 하나에 직접적인 파일이나 심볼릭 링크로 존재하게 되어 커맨드 라인에서 바로 사용이 가능하다. 하지만 별도의 인스톨러로 설치하거나 압축파일을 직접 풀어 설치하면 실행이 안 될 때가 있는데, 설치된 파일이 bin, sbin 디렉토리에 존재하지 않기 때문이다. 이런 경우 brew처럼 심볼릭 링크로 실행 파일을 bin 디렉토리에 연결시키거나 bin, sbin 외에 별도의 실행파일을 위한 PATH를 추가함으로써 해결할 수 있다.

lib, lib64

lib와 lib64는 시스템 부팅이나 bin과 sbin 디렉토리에 있는 바이너리 파일들 실행에 필요한 공유 라이브러리 디렉토리이다. 가상환경을 사용하지 않는 파이썬의 경우 usr/local/lib/python3.6/site-packages 같은 디렉토리에 라이브러리 파일이 설치되고 이를 활용해 파이썬 커맨드가 돌아가게 된다.

bin, sbin과 마찬가지로 root 디렉토리, usr 디렉토리, usr/local 디렉토리에 필수 파일 여부와 설치 방법에 따라 분리되어 관리된다.

etc

etc 디렉토리는 설정파일을 관리한다.

etc 디렉토리 ls -al 실행 결과

...
-rw-r--r-- 1 root wheel  1.0K Nov  9  2019 asl.conf
...
drwxr-xr-x 3 root root   4096 Dec  4 17:37 nginx
...
-rw-r--r-- 1 root root    953 May  6 03:54 passwd
-rw-r--r-- 1 root root    916 May  6 03:32 passwd-
drwxr-xr-x 3 root root   4096 Dec  4 17:37 pkcs11
drwxr-xr-x 1 root root   4096 Dec  4 17:37 pki
drwxr-xr-x 5 root root   4096 Dec  4 17:37 pm
drwxr-xr-x 2 root root   4096 May 11  2019 popt.d
drwxr-xr-x 2 root root   4096 May  5 14:19 prelink.conf.d
-rw-r--r-- 1 root root    233 Sep 10  2018 printcap
...

etc 디렉토리 내부를 보면 여러가지 디렉토리와 파일들을 볼 수 있다. .d 를 붙여서 디렉토리인 것을 구별하기도 하고 그렇지 않기도 한다. 설정파일은 .conf 라는 이름의 형식으로 많이 관리되어 있다.

예를 들어 passwd는 사용자에 관련된 내용을 담고 있다. 우리가 커맨드를 통해 사용자를 추가하거나 삭제하면 해당 파일이 변경되며 운영체제에서 사용자를 관리하게 된다.

만약 nginx와 같은 웹서버를 다루게 되면 /etc/nginx 디렉토리에서 nginx.conf 같은 파일들을 수정해야 한다. 인터넷의 글들을 따라하며 파일을 수정하고 웹서버가 작동해도 왜 작동하는지 전혀 이해가 안 되기도 한다. 리눅스에서 etc 디렉토리에서 설정 파일들을 관리한다는 사실을 알고 있다면 대략적으로라도 그런 수정 작업이 무엇을 의미하는지 조금은 알고 할 수 있게 될 것이다.

var

variable data를 뜻한다. 시스템 로그나 웹 로그 파일들을 포함한다. nginx 등의 웹서버를 다룰 때나 aws elastic beanstalk 등을 활용해 배포를 하게 될 때 var 디렉토리 밑에 로그들이 쌓인다. 로그를 확인하고 싶을 때 var 디렉토리를 참조해야 된다는 정도로 알아두면 좋을 것 같다.

usr

universal system resources의 약자라고 하기도 하고 그냥 user의 약자라고 하기도 한다. 리눅스의 여러 사용자들이 공유하는 파일들을 관리한다. 위에 bin, sbin, lib, lib64 디렉토리 설명에서 볼 수 있듯이 사용자를 위한 파일들을 저장하고 관리한다. usr 디렉토리 안에 존재하는 파일들은 모든 사용자들이 참조해 사용할 수 있다.

opt

optional을 뜻한다. 사용자가 외부 프로그램을 설치하면 opt 디렉토리 내에 깔리기도 한다. MacOS의 경우 anaconda의 기본 설치 경로가 opt이다.

home, root

home 디렉토리는 개별 사용자의 디렉토리를 관리하는 디렉토리이다. 만약 jin이라는 이름의 사용자를 만들었다면 /home/jin 디렉토리로 jin을 위한 디렉토리가 생성된다. 해당 디렉토리에 대한 접근 권한은 기본적으로 jin으로 한정되어 관리된다. chownchmod 를 활용해 추후 접근이나 파일의 실행 권한에 대한 변경이 가능하다.

root 디렉토리는 root 계정을 위한 디렉토리로 home 말고 별도의 디렉토리로 관리된다.

FHS ( Filesystem Hierarchy Standard ) - 기타 디렉토리

데이터 분석을 위한 리눅스 디렉토리 구조는 위에서 설명된 주요 디렉토리에 내용만 알아도 충분하다고 생각한다. 나머지 디렉토리에 대해서는 간략히 정리해보겠다. 사용해보지 않은 디렉토리가 많아 위키피디아와 MIT 교육 자료에서 내용을 참조했다.

media, mnt

media와 mnt 모두 파일 시스템이 마운팅되는 디렉토리이다. 다만, media는 os가 관리해주는 디렉토리이고 mnt는 직접 커맨드라인을 통해 마운트할 때 사용되는 디렉토리이다.

boot

부팅에 필요한 파일들을 포함하고 있는 디렉토리이다.

dev

마우스 등 디바이스와 관련된 파일이 존재하는 디렉토리이다.

sys

디바이스를 관리하기 위한 가상 파일 시스템 디렉토리이다.

proc

현재 실행 중인 프로세스에 대한 정보를 관리하는 디렉토리이다.

run

Run-time variable data를 관리한다. 부팅한 후의 시스템 정보를 관리하는 디렉토리이다.

srv

FTP, WWW 또는 CVS와 같은 특정 서비스의 데이터 파일 위치를 포함한 디렉토리이다.

tmp

임시로 파일을 저장하기 위한 디렉토리이다. 재부팅 시에 삭제되며, 정기적으로 10일 정도 간격으로 삭제된다.

lost+found

파일 시스템의 복구에 사용되는 데이터 조각들을 포함하고 있다. 재부팅이나 파일 시스템 체크 커맨드 등을 이용할 때 참조된다.

리눅스 운영체제 관련 개념

마지막으로 디렉토리 구조와 더불어 리눅스 이해에 도움이 될만한 몇 가지 간단한 운영체제 관련 개념에 대해 알아보자.

사용자

리눅스에는 사용자라는 개념이 있다. 일반 데스크톱이나 노트북에서 우리가 로그인해서 시스템에 들어가는 것처럼 리눅스도 사용자 이름과 비밀번호를 통해 시스템에 들어간다. 개인용 PC에서는 따로 사용자 관리를 할 일이 잘 없지만 서버용으로 사용되는 시스템은 중요 부분을 아무나 건드리면 안되기 때문에 사용자별로 권한을 조정해서 보안 등의 관리를 수행한다.

실제 시스템 개발을 할 때는 모든 권한을 가진 root 계정이 아닌 권한이 제한된 사용자 계정을 받아 작업한다. 그런 상황에서 파일 수정이나 엑세스에 문제가 있다면 추가로 권한 요청이 필요할 수 있겠다 정도를 생각할 수 있으면 좋을 것 같다.

파일과 권한

파일은 소유자와 소유 그룹이 존재하며 이를 바탕으로 리눅스에서는 파일에 대한 권한을 관리한다. 소유자의 권한, 소유 그룹의 권한, 다른 그룹의 권한의 형태로 각각에 대한 읽기, 쓰기, 실행에 관한 permission을 지정한다.

권한은 대부분 소유자 개별보다는 소유 그룹의 단위로 관리되며, 사용자 계정에 특정 권한을 가진 그룹을 할당함으로써 파일을 접근하거나 수정할 수 있도록 한다.

chmod, chown 등의 커맨드로 파일의 권한을 변경할 수 있다. 커맨드 사용 예시는 자주 사용하는 리눅스 커맨드 - 사용법 및 예시 에서 확인해볼 수 있다

env

CentOS8 기본 환경 변수 목록

[jin@l9c11z10a888 proc]$ env
LANG=en_US.UTF-8
HOSTNAME=a9a71a10a856
OLDPWD=/
USER=jin
PWD=/proc
HOME=/home/jin
SHELL=/bin/bash
TERM=xterm
SHLVL=2
LOGNAME=jin
PATH=/home/jin/.local/bin:/home/jin/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/usr/bin/env

리눅스에서는 환경 변수가 존재한다. 쉽게 생각하면 파이썬 코드에서 볼 수 있는 변수나 마찬가지이다. 운영체제의 경우에도 일반 코드와 마찬가지로 시스템을 특정 방향으로 구동시키거나 설치된 파일들을 실행하려면 참조할 변수 값이 필요하다. 환경변수도 이런 경우 필요할 때 갖다 쓰는 변수들이다.

처음 프로그래밍을 할 때 PATH라는 환경 변수 설정에서 머리가 아팠었는데, 이것도 결국 ‘운영체제가 어디에서나 참조할 수 있는 실행 파일 경로의 목록’ 이라는 변수라고 생각하면 어려운 개념이 아니었다. 환경변수에는 PATH 외에도 시스템 작동과 관련된 다양한 변수들이 존재한다.

.bashrc 초기화 파일 설정 내용

# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]
then
    PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH

# Uncomment the following line if you don't like systemctl's auto-paging featur$
# export SYSTEMD_PAGER=

# User specific aliases and functions

# Editor
export EDITOR=nano

# PYENV
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

#
...

쉘은 리눅스에서 명령어를 실행할 때 사용하는 인터페이스이다. 우리가 사용하는 까만 화면의 커맨드 라인의 텍스트들은 쉘을 통해 해석되어 커널에 보내진다.

쉘은 다양한 프로그래밍 기능을 가지고 가지고 있다. 변수나 함수를 정의하고 사용할 수 있으며, 초기화 파일을 통해 쉘이 시작하기 전에 이런 요소들을 설정할 수 있다. 위 코드는 bash 쉘의 .bashrc 초기화 파일의 내용 일부이다. 특정 라이브러리 사용이나 언어 사용 시 .bashrc 파일을 수정하라고 하는데 이 파일에 exporteval 명령어를 써 놓으면 쉘이 실행되기 전에 해당 명령어가 실행되어 바로 변수나 설정된 상태를 사용할 수 있다.

쉘에는 다양한 종류가 있는데, 기본적으로 아무 설정을 하지 않으면 bash 쉘이 실행된다.

마치며

분석 모듈이 돌아가는 시스템을 만들려다보니 은근히 리눅스를 건드릴 일이 있었는데 제대로 알아볼 시간은 많이 없었다. 리눅스 관련 내용들은 제대로 이해하지 못하고 급하게 블로그 글들의 코드를 따라쓰며 작업 했었는데 이번 기회에 조금은 정리가 된 기분이다. 리눅스 관련 내용은 유튜브에도 잘 설명된 동영상이 많다. 참조 링크에 있는 동영상들도 참조하면 이해에 도움이 될 것이다.

References

Leave a comment