ubuntu 부팅 과정과 자동 실행
※ 18.04 버전부턴 rc.local 을 사용하지 않는다고 한다. 해당 문서는 16.04 에서 진행되었다.
부팅시 구동 순서
BIOS
메인보드에 있는 BIOS 라고 불리는 펌웨어가 부팅시 필요한 처음 동작들을 처리한다.
이 BIOS는 POST(Power On Self Test)라고 불리는 동작을 통해 부팅에 필요한 하드웨어들이 잘 연결되어 있는지, 하드웨어들이 잘 동작하는지 등을 확인한다. 그리고 부트 가능한 장치들을 사전에 설정된 부팅 우선 순위(Periperial Booting Priority)에 따라 차례대로 각각의 장치의 MBR(Master Boot Record) 혹은 부트섹터라고 불리는 첫 번째 섹터의 마지막 2바이트를 확인해서 부트섹터의 시그니쳐가 맞는지 확인한 후 시그니쳐(0x55AA) 가 맞을 경우 해당 장치로 부팅을 시도한다. 그리고 MBR의 첫 번째 바이트로 점프해서 기계어 Instruction을 실행한다.
최근에는 BIOS 대신 UEFI가 여기에 위치하는 경우도 있다.
MBR
설정된 장치의 첫 번째 섹터를 MBR(Master Boot Record)이라고 하며 여기에 나머지 부팅 절차들을 발기 위한 명령어들이 있다.
하드웨어에서 한 섹터는 512바이트 이며, 컴퓨터들은 하위호환성을 유지하면서 발전했기 때문에 저장장치의 용량이 커져도 이는 동일하다.
이 MBR 에 있는 코드에는 리눅스 부트로더인 GRUB(혹은 레가시 시스템에서는 LILO)이 들어있다.
GRUB
Grand Unified Bootloader 의 약자이며 MBR 에 GRUB의 기계어 Instuction 들이 있다.
하나의 저장장치에 여러개의 OS가 설치되어 있을 수 있으므로, GRUB은 어떤 OS로 부팅할 것인지 사용자가 설정할 수 있도록 UI를 제공한다.
사용자가 원하는 OS를 선택하면 부트로더는 저장장치의 다른 섹터에 있는 커널 코드들을 메모리에 로드한 뒤 커널코드로 점프하여 커널의 기계어 Instruction들을 실행하도록 한다.
커널
리눅스 운영체제의 핵심. GRUB 설정 파일에 정의된 경로에 루트 파일 시스템을 마운트 하고 /sbin/init 프로그램을 실행한다.
init 프로세스는 해당 OS에서 실행된 첫 번째 프로세스로 pid가 1이다.
우분투 최신 버전의 경우init 프로세스 대신 systemd 라는 시스템 데몬 프로세스가 그 자리를 대신하기도 한다.
init
해당 시스템에 저장된 런 레벨에 맞게 동작한다.
런레벨은 보통 0~6까지의 숫자로 이루어져 있으며 시스템을 어떤 방식으로 부팅하는지를 결정한다.
systemd 로 제어되는 시스템의 경우 더 많은 종류의 런레벨을 갖고 있으며, 리눅스 메뉴얼 페이지에서 man systemd.special 명령어로 확인가능하다.
0 - 시스템종료
1 - 싱글유저모드
계정이 하나만 존재하며 시스템 복원모드라고도 불린다. 기본적으로 관리자 권한의 쉘을 얻게된다.
파일 시스템을 점검하거나 관리자 암호 변경시 사용한다. S모드와의 차이점은 이 모드는 멀티 유저 모드에서 싱글 유저 모드로 스위치 된 경우 이 모드이다.
점검을 위해 싱글 유저 모드로 들어간 경우라고 인식된다.
S - 싱글유저모드
1번 모드와 동일하나 부팅시 부터 싱글유저 모드인 경우
2 - 멀티유저모드 NFS비활성
여러개의 계정을 사용할 수 있으며 NFS(Network File System) 사용이 불가능하다. 3번 모드와 같지만 네트워크 사용이 불가능하다.
3 - 풀 멀티유저모드
CLI 를 가지며 멀티유저를 지원한다.
4 - 사용안함
기본적으로 사용하지 않는 모드이며 사용자가 정의하여 원하는 모드로 사용가능하다.
5 - X11
3번 모드와 같이 멀티유저를 지원하는 일반모드 이지만 GUI를 지원한다.
6 - 재시작
시스템을 재시작한다.
런레벨 프로그램
init 프로세스가 런레벨을 결정하면 각각의 런레벨에 맞는 서비스들을 실행해야 한다.
이때 각각 런 레벨별 실행해야 하는 서비스들의 디렉토리 경로는 다음과 같다.
rc 는 Run Command 의 약자
레벨S - /etc/rcS.d
레벨0 - /etc/rc0.d
레벨1 - /etc/rc1.d
레벨2 - /etc/rc2.d
레벨3 - /etc/rc3.d
레벨4 - /etc/rc4.d
레벨5 - /etc/rc5.d
레벨6 - /etc/rc6.d
/etc/rc0.d 디렉토리의 파일중
K로 시작하는 파일은 해당 서비스를 종료하기 위한 스크립트로 심볼릭 링크 원본의 스크립트를 stop 인자와 함께 실행
S로 시작하는 파일은 해당 서비스를 구동하기 위한 스크립트로 심볼릭 링크 원본의 스크립트를 start 인자와 함께 실행
뒤의 숫자는 순서를 맞추기 위함이다.
이런식으로 rc?.d 디렉토리들을 확인해 보면 런레벨 2~5와 S레벨의 경우 마지막에 /etc/init.d/rc.local 이라는 스크립트를 실행시킨다.
/etc/init.d/rc.local 스크립트를 살펴보면 /etc/rc.local 파일이 있을 경우 실행시킨다고 되어있다.
※ 18.04 버전에서는 /etc/init.d/rc.local , /etc/rc.local 파일이 존재하지 않는다.
/etc/rc/local 스크립트 실행
ubuntu 16.04 의 경우 런레벨 2~5, S의 경우 /etc/rc.local 을 최종적으로 실행시킨다. 없을경우 실행시키지 않는다.
런레벨 0은 시스템 종료, 6은 재부팅이므로 관계 없으며, 런레벨1의 경우 시스템 복구모드 으기 때문에 복구를 위해서 해당 스크립트를 실행시키지 않는것으로 보인다.
부팅 스크립트 등록
리눅스 부팅 과정을 알아보면 알 수 있듯이 부팅때마다 실행되어야 할 스크립트는 /etc/rc.local 에 입력하면 된다.
주의할 점은 PATH 같은 환경변수가 일반 쉘과 같은 환경으로 설정되지 않을 수 있기 때문에 환경변수를 설정하고 명령어를 실행하거나 절대경로로 실행하는 것을 추천한다.
또한 스크립트 실행 도중 에러가 발생했을 때, 표준 출력과 표준 에러를 직접 터미널로 확인하기 어려우므로 파일로 Redirection 하되 표준에러도 같이 Redirection 하도록 하는 것을 추천한다.
참고
- http://eine.tistory.com/41
- https://www.thegeekstuff.com/2011/02/linux-boot-process/
- http://kateee.tistory.com/51
- http://nuitstory.tistory.com/500
- https://wiki.debian.org/BootProcess
- http://cherub.sungkyul.edu/~web/jinboard/files/63_boot.pdf
- https://ko.wikipedia.org/wiki/%EC%8B%9C%EB%8F%99_%EC%9E%90%EC%B2%B4_%EC%8B%9C%ED%97%98
- http://forensic-proof.com/archives/435