Linux Upskill 8. 한국어 locale, chroot, busybox와 심볼릭 링크

jiffydev·2021년 4월 10일
0

linux upskill

목록 보기
8/8

본 포스트는 박재호님의 유튜브 강의를 보고 개인적으로 정리한 내용입니다.

1. 한국어 locale 사용

우선 locale(이하 로케일)이 무엇인지부터 설명해야 할 것 같다.
국가별로 언어나 날짜, 단위, 통화 등 많은 부분에서 다른점이 있는데, 시스템 상에서 자신이 속한 나라의 문화에 맞는 표기법을 쓰고 싶을 것이다. 그래서 이런 부분을 선택할 수 있도록 하는 것이 로케일로, EC2에서 ubuntu를 설치하면 기본적으로 영어로 되어 있다.
이를 한국어 로케일을 설정할 수 있는데, 여기서 주의할 점은 한국어 로케일로 설정한다고 해서 모든 애플리케이션에 한국어가 적용되는 것은 아니다.

1-1. 명령어 실습

1-1-1. locale

현재 사용 가능한 로케일을 출력하려면 다음과 같이 입력한다.

ubuntu@ip-172-26-9-205:~$ locale -a


여기서 C는 POSIX 로케일의 alias이므로 둘은 같다고 할 수 있다.
C란 C언어에서 가장 최소 기능의 로케일에 대해서 지정한 규약을 딴 것이고 그것을 POSIX에서도 이어받아 같은 방식으로 정의를 하고 있다.
C같은 경우 일반적인 ascii 문자코드를 지원하는데, C.UTF-8의 경우 C를 따르되 문자코드를 utf-8로 하라는 뜻이 된다.
또다른 로케일인 en_US.utf8은 미국에 특화된 로케일이면서 utf8을 지원한다고 해석할 수 있다.

그러면 현재 설정된 로케일을 다음과 같이 확인하자.

ubuntu@ip-172-26-9-205:~$ locale

로케일을 변경하기 위해서는 dpkg를 통해 선택해야 한다.

ubuntu@ip-172-26-9-205:~$ sudo dpkg-reconfigure locales

이 명령을 실행하면 선택화면이 다음과 같이 뜨게 되고, 여기서 한국어 로케일에 해당하는 ko_KR .UTF-8 UTF-8을 선택하면 된다.(스페이스로 선택) EUC-KR도 있지만 표현하지 못하는 부분이 있어 어려움이 발생할 수 있기 때문에 utf-8을 선택하기를 권장한다.


여기서 디폴트 언어를 선택하면 된다.
이제 적용이 되었는지 다시 locale 명령으로 확인해보자.


적용되지 않은 것을 볼 수 있다. 적용하기 위해서는 터미널은 종료하여 다시 로그인해야 적용된다.

다시 영어로 되돌려보도록 할텐데 이번에는 dpkg 대신 다른 명령어를 사용해보자.

ubuntu@ip-172-26-9-205:~$ sudo update-locale LANG=C.UTF-8 LANGUAGE

명령을 실행하고 터미널을 종료하여 다시 로그인하면 원래대로 돌아온 것을 볼 수 있다.

2. chroot & busybox

chroot
지금이야 웹 서버에 접근해서 소프트웨어를 다운받거나 소스코드도 github에 올리고 내리는게 자연스럽지만, 이런 시스템이 없던 과거에는 anonimou ftp라고 해서 익명의 사용자에게 파일을 업로드, 다운로드 할 수 있는 권한을 주는 웹사이트가 운영되었다.
그런데 이 과정에서 함부로 ftp서버의 모든 파일 시스템을 다 열게 되면 보안이 취약해지는 것은 뻔하기 때문에, 파일시스템을 격리해야 할 필요성이 대두되었다. 이를 위해 나온 것이 chroot인데, 본래의 사용 취지와 더불어 현재는 다양한 방식으로 사용되게 되었다.

busybox
일반적으로 chroot를 사용하기 위해서는 bash 및 bin과 하위 파일을 복사하고, 관련 라이브러리도 복사해야 한다. 하지만 이런 번거로움을 줄이기 위해 busybox를 사용하면, 상기한 과정 없이도 chroot에 루트 파일시스템을 마운트할 수 있다.

2-1. 명령어 실습

2-1-1. busybox 빌드

busybox는 바이너리 파일 하나로만 구성되어 있기 때문에 의존성 문제도 없고, 따로 설치한다기보다 그냥 소스코드를 가져와 빌드하면 된다.

ubuntu@ip-172-26-9-205:~$ mkdir chroot_example
ubuntu@ip-172-26-9-205:~/chroot_example$ wget https://busybox.net/downloads/busybox-1.32.0.tar.bz2

보다시피 bz2 형식으로 압축되어 있기 때문에 tar에서 압축 푸는 명령 j를 추가해 압축을 풀어주자.

ubuntu@ip-172-26-9-205:~/chroot_example$ tar xvpfj busybox-1.32.0.tar.bz2

압축을 풀면 디렉토리가 생성되고 그 안에 이제 어떻게 설치하면 될지 설명이 있을 것이다.(INSTALL파일)

여기서 우리는 make menuconfigmake만을 실행할 것이다. install은 이번 시간의 목표와는 관계가 없기 때문인데 그 이유에 대해서는 아래에서 설명하겠다.

ubuntu@ip-172-26-9-205:~/chroot_example/busybox-1.32.0$ make menuconfig


make menuconfig를 실행하면 위와 같은 에러가 뜰 것이다. 메시지에도 써있듯, curses.h라는 파일이 없기 때문으로 ncurses를 아래와 같이 설치하면 된다. 만약 컴파일러가 없다는 에러가 뜬다면(이 시리즈를 처음부터 따라왔다면 중간에 컴파일러를 설치하기 때문에 이 에러가 발생할 일은 거의 없겟지만) build-essential을 설치하면 해결된다.

다시 돌아와서 ncurses를 설치하고 make menuconfig도 다시 실행하자.

ubuntu@ip-172-26-9-205:~/chroot_example/busybox-1.32.0$ sudo apt-get install libncurses5-dev libncursesw5-dev
ubuntu@ip-172-26-9-205:~/chroot_example/busybox-1.32.0$ make menuconfig

명령을 실행하면 바로 위와 같은 화면이 반겨줄 것이다.
필요한 설정을 진행하기 전에 busybox의 사용 목적을 설명하자면, 사실 busybox는 필요한 명령들을 줄이고 줄여서 최소한의 용량을 바이너리 파일에 때려박은 것이다. 이는 임베디드 쪽은 저장 용량이 작기 때문에, 동작을 쉽게하기 위해서 이와 같이 최소한의 용량만으로도 돌아가도록 만든 것이 busybox이다.

이번 시간에는 applet에 대한 설정은 건드리지 않고, 단지 static link만 설정할 것이다. 이를 통해 라이브러리 없이 이 파일 하나로 의존성을 신경쓰지 않게 하기 위해서이다.
작업을 위해서는 우선 상단의 Settings에 들어가 밑으로 내리다 보면 아래와 같이 Build static binary가 보일 것이다.

이를 스페이스바로 선택 후 exit하면 된다. 다시 exit을 누르면 다음과 같이 설정을 저장하겠냐는 메시지가 뜨므로 yes를 선택하면 설정은 끝이다.

이제 make 명령을 실행해 보자.

ubuntu@ip-172-26-9-205:~/chroot_example/busybox-1.32.0$ make

컴파일이 완료되었으면 실제로 busybox가 어디에 설치되었는지 찾아보자.

ubuntu@ip-172-26-9-205:~/chroot_example/busybox-1.32.0$ find . -name busybox

전에 설정에서 static 라이브러리만 사용하도록(동적 라이브러리 없음) 설정했는데 이 부분도 적용되었는지 확인할 수 있다.
ldd 명령을 사용하면 되는데, 어떤 파일의 공유된(동적) 라이브러리를 보여준다.

ubuntu@ip-172-26-9-205:~/chroot_example/busybox-1.32.0$ ldd busybox


우리가 설치한 busybox는 동적으로 링크된 파일이 하나도 없음을 알 수 있다.

이제 루트 파일시스템을 생성할텐데, 디렉토리를 하나 올라와 ~/chroot_example에서 root디렉토리를 생성하고 그 안에 bin 디렉토리를 만든다.
그리고 busybox를 현재 디렉토리인 bin 디렉토리에 복사한다.

ubuntu@ip-172-26-9-205:~/chroot_example/busybox-1.32.0$ cd ..
ubuntu@ip-172-26-9-205:~/chroot_example$ mkdir root
ubuntu@ip-172-26-9-205:~/chroot_example$ cd root/
ubuntu@ip-172-26-9-205:~/chroot_example/root$ mkdir bin
ubuntu@ip-172-26-9-205:~/chroot_example/root$ cd bin
ubuntu@ip-172-26-9-205:~/chroot_example/root/bin$ cp ../../busybox-1.32.0/busybox .


그러면 busybox를 실행시킬 수 있는데, ./busybox로 실행시켜 보면 명령어만 우르르 쏟아져 나오는 것을 볼 수 있다. 이 명령들은 busybox 다음에 인자로 주어서 실행시킬 수 있다.
예를 들어 busybox ls, busybox pwd를 실행시키면 busybox 안에 있는 ls, pwd 명령이 실행되는 것이다.

그런데 매번 busybox를 사용해야 하는 것은 불편한 일이다. 여기서 등장하는 것이 이전에 설명했던 심볼릭 링크인데, busybox와 각 명령에 심볼릭 링크를 걸어 줌으로써 바로 실행할 수 있게 된다.

ubuntu@ip-172-26-9-205:~/chroot_example/root/bin$ ln -s busybox ls
ubuntu@ip-172-26-9-205:~/chroot_example/root/bin$ ln -s busybox pwd
ubuntu@ip-172-26-9-205:~/chroot_example/root/bin$ ln -s busybox cd
ubuntu@ip-172-26-9-205:~/chroot_example/root/bin$ ln -s busybox sh

위와 같이 몇 개의 명령어에 심볼릭 링크를 설정하면 busybox 없이 현재 디렉토리에서 명령만 입력해도 실행되는 것을 볼 수 있다.

(여기서 실행된 셸은 busybox의 셸이지 기본 bash shell이 아님에 주의.)

이제 마지막 단계로 chroot로 생성된 루트 파일시스템을 마운트해 보자.

ubuntu@ip-172-26-9-205:~/chroot_example/root/bin$ cd ../..
ubuntu@ip-172-26-9-205:~/chroot_example$ sudo chroot ./root /bin/sh

chroot 명령을 해석해보면, 현재 디렉토리 안의 ./root 라는 디렉토리를 마운트시켜 셸의 최상위(root) 디렉토리로 인식하도록 설정하였고, 그 아래 /bin/sh를 자동으로 실행시켜서 권한을 얻는 것이다.

명령을 실행해 보면 위와 같이 셸이 실행되어 잘 마운트된 것을 볼 수 있다.
이번 포스트에서의 작업은 매우 단순화시켜서 간단한 작업이지만, 결국 docker도 이와 유사한 원리로 동작하게 된다.

3. busybox의 심볼릭 링크

위의 busybox와 관련된 심볼릭 링크에 대해서, 필자도 그렇지만 이게 어떻게 심볼릭 링크를 걸었다고 해서 busybox 자신의 명령인 것처럼 ls나 pwd가 동작하는지 이해가 되지 않았다. 이 부분에 대해 어떤 원리로 동작하는지 알아보고자 한다.

이는 엔트리포인트에서 넘어오는 인자를 처리하는 방법과 연관이 있는데, 우선 argv에 대해 생각해 보아야 한다. argv는 bash shell에서 커맨드라인에 명령을 내리게 되면 명령을 프로그램으로 넘기게 되는데, 가장 처음으로 넘어오는 것이 우리가 입력한 명령이다.

예를 들어 ls -al sometfile.txt라는 명령을 입력하면 argv 0번에 ls, 1번에 -al 2번에 somefile.txt가 배열 형태로 들어가게 된다.

여기서 심볼릭 링크의 정의에 대해 생각해보면, 특정 파일이 다른 무언가를 가리키도록 만는 것인데 심볼릭 링크를 실행하면 실제 파일 이름이 넘어오는 것이 아니라 심볼릭 링크 자체의 이름이 넘어오게 되는데, 바로 이 점을 이용한 것이다.

심볼릭 링크를 설정할 때 ln -s busybox ls와 같이 설정하는데, 이는 busybox에 ls 라는 심볼릭 링크를 건 것이다. 그리고 ls 명령을 내리게 되면 실제로는 busybox(파일이름)가 실행되는데, argv[0]에는 ls(심볼릭 링크 이름)가 넘어가서 ls명령이 실행되는 것이다.

profile
잘 & 열심히 살고싶은 개발자

0개의 댓글