서 버
서버 관련하여 유익한 정보나 강좌를 게시할수 있는 공간입니다.
글 수 493
http://ccc.mzin.net/lecture/linux/bootdisk.txt
========================================================
*** bootdisk
경호가 경험한 메시지
initrd - 초기화 램디스크
initrd.img
부트 디스크와 부팅 과정
부트 디스크의 종류
*** make bootdisk
경호 bootdisk 제작 스크립트
bootdisk 제작 - 디스켓에 LILO 와 커널을 함께 담기
bootdisk 제작 - LILO 없이 커널만 담기
램디스크 워드의 설정
*** rootdisk
경호 rootdisk 제작 스크립트
루트 fs의 크기를 줄이는 방법
모듈
PAM 과 NSS 에 대한 대책
NSS (Name Service Switch)
*** make rootdisk - 압축된 루트 fs의 제작
fs 만들기
램디스크를 사용하는 방법 (DEVICE = /dev/ram0)
루프백 디바이스를 이용
fs의 구성 - 화일 복사
/dev
/etc
/lib
/bin 과 /sbin
마지막 세부사항
*** other
rootdisk - 램디스크 사용하지 않음
유틸리티 디스크 만들기
boot disk 만드는 여러 방법
dd 이용해서 만들기
rawrite 이용해서 만들기
Tomsrtbt 부트 디스크 만들기
mkbootdisk 스크립트 이용해서 만들기
boot cd 제작
*** etc
복구 패키지들
리눅스 부트 프로세스
애로사항과 문제해결
전문가들이 사용하는 방법
자주 받는 질문들
*** 사용된 명령어 및 참조화일
loadlin, rawrite, mkbootdisk, tomsrtbt, mkisofs
mke2fs, mount, -o loop, -m 0, -i 1024, losetup
lilo, lilo.conf, dd, rdev, mknod
objcopy, --strip-all, --strip-debug
ldconfig, libc, ld-linux, ramdisk, /lib/security, /lib/modules, pam
nss, nsswitch.conf, passwd: files, shadow: files, group: files, services: files
boot.img, menu.lst, stage1, stage2, config.h, makefile, -lnss_dns, -lnss_file
##############################
##############################
bootdisk
다음과 같은 경우에 리눅스 부트 디스켓을 요긴하게 사용할 수 있다.
- 새로운 커널을 테스트할 때.
- 디스크에 문제가 발생했을때 복구용으로 (부트섹터를 날렸거나 디스크 헤드가 망가진 경우 등등.)
- 망가진 시스템을 고칠 경우 플로피 디스켓으로 부팅해 시스템을 수리 해야만 할 경우도 있다.
- /libc.so 등과 같은 핵심적인 시스템 파일을 업그레이드할 때.
*** 부트 디스크는 다음 방법을 통해 얻을 수 있다.
- 슬랙웨어 등의 배포본에 있는 부트 디스크를 이용한다. 적어도 부팅은 확실하게 할수있다.
- 복구전용으로 디자인된 복구 패키지를 이용한다.
- 각각의 디스크가 어떻게 동작하는지를 이해한 후 직접 부트 디스크를 제작한다.
가장 적당한 것이 배포본의 복구 디스켓용 fs을 이용 하는 것이다.
이 것들은 플로피를 대상으로 했기 때문에 어느 정도 용량에 대한 고려가 되어 있다.
그러나 레드헷의 복구 디스켓은 ext2 fs을 사용하고 라이브러리와 프로그램이 elf 포맷으로 되어 있어서
용량이 무척 크다. 슬랙웨어의 디스켓용 프로그램 들은 아직도 a.out 포맷으로 되어 있고
라이브러리도 최소한의 기능 만을 넣고 있기 때문에 크기가 비교적 작다.
새 프로그램을 a.out으로 컴파일하면 되겠지만 모든 배포본이 elf 시스템으로 되어 있어서 쉽지 않다.
추가하려는 프로그램이 한 두개라면 라이브러리를 실행 프로그램에 합치는 정적 컴파일을 하면 되겠지만
용량을 무시하지 못하게 된다. 20k 정도를 정적 컴파일 하게 되면 900K 이상이 된다.
*** 부팅하기
cdrom:/dosutils> autoboot.bat
loadlin 이라는 프로그램이 vmlinuz라는 커널이미지를 가지고 부팅한다
cdrom:/dosutils> loadlin [CDROM]\autoboot\vmlinux root=/dev/hdb1 ro
### 경호가 경험한 message ###
kernel panic: VFS: Unable to mount root fs on 02:00
rdev -r 명령으로 실행하지 않았을때 bootdisk 완료후 rootdisk 삽입하자 마자 나타남
루트 fs의 파티션이 틀렸다던지 루트 fs을 커널이 지원하지 않는다던지
또는 SCSI 어댑터를 모듈로 설정하여 SCSI 모듈이 로드되지 않을 경우 많이 볼수있다
VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER
rdev -r 명령실행후 bootdisk 완료후 rootdisk 삽입하자 마자 나타남 (이후 정상 진행)
RAMDISK: Compressed image found at block 0
bootdisk 구동후 rootdisk 정상 구동시 맨트
cannot excute "/etc/rc.d/rc"
no more processes left in this runlevel
부팅후 userid 입력하면 passwd 프롬프트가 뜨지 않아서 Ctrl+Alt+Del 눌렀을때 나타나는 멘트
fd0u1722 로 rootdisk 구성 했을시 나타나는 멘트
- invalid compressed format (err=1)<5> VFS: insert root floppy and press ENTER
- kernel panic: Attempted to kill init
floppy0: probe failed...
플로피 디스크 블럭 탐색 못하는것 같은데.. 까묵었다..
dd 로 vmlinuz 만 복사 했을시
invalid compressed format (err=2)
-- system halted
#####
##### initrd - 초기화 램디스크 ###
램디스크 코드의 동작원리에 대한 탁월한 설명은 리눅스 커널에 따라오는 문서에서 찾을수 있다.
/usr/src/linux/Documentation/ramdisk.txt 를 보라.
*** 어떤 부트 디스크 들은 initrd(initial ramdisk)라 불리우는 기능을 이용한다.
이 기능은 커널 2.0.x 대에서 처음 도입 되었으며 커널을 두 단계로 부트시킨다.
일단, 커널이 처음 부트된 후 초기화 램디스크 이미지를 부트 디스크에서 읽어온다.
초기화 램디스크 이미지는 루트 fs이 로드 되기전 먼저 실행 되어야 할 프로그램을 담은 루트 fs다.
이 프로그램은 시스템 환경을 조사해서 사용자로 하여금 다양한 부트옵션을 선택할 수 있게 한다.
가령 진짜 루트디스크를 어느 디바이스에서 로드 할지를 선택할 수도 있다.
이것은 주로 커널에 내장 되어 있지 않은 추가적인 모듈들을 로드한다.
이 초기화 프로그램이 끝나면 커널은 진짜 루트 이미지를 로드해서 정상적으로 부팅을 속개하게 된다.
initrd 에 관한 더 많은 내용은 아래를 참고
/usr/src/linux/Documentation/initrd.txt
ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/initrd-example.tgz
*** initrd라는 이미지는 초기화 램 디스크인데 램디스크와 차이가 있다.
램 디스크는 부팅한 후에 루트 fs으로 지정되어 재부팅 할 때까지 변하지 않지만
초기화 램디스크는 커널이 부른후 그안에서 임의의 작업을 하고 언마운트 시킬 수 있다.
이 것을 언마운트 시키고 대신에 일반 램 디스크를 적재하게 된다.
이런 특성 때문에 초기화 램디스크는 특정 하드웨어에 필요한 모듈을 가지고 있다가
사용자의 요구에 따라 적재하고 사라지는 등 램디스크의 용량 문제로 유지하고 있기 힘든
프로그램이나 부팅하면서 한 번만 사용되는 프로그램 들을 넣어서 사용할 때 주로 쓴다.
또다른 차이는 램 디스크는 커널이 적재 하면서 /etc/init(/sbin/init)를 실행하게 되지만
초기화 램 디스크는 /linuxrc 파일을 실행 한다. linuxrc는 어떤 프로그램도 될 수가 있다.
(/usr/src/linux/Documentation/initrd.txt 참고)
#####
##### 부트 디스크와 부팅 과정 ###
부트 디스크란 기본적으로 플로피 디스켓에 쏙 들어가는 미니어처 즉, 축소판 리눅스 시스템이다.
부트 디스크는 완전한 풀 사이즈의 리눅스 시스템의 기능 중 많은 부분을 그대로 수행할 수 있어야만 한다.
부트 디스크 제작에 앞서 당신은 리눅스의 부팅 과정의 기본 원리를 이해해야만 한다.
### 부트 시퀀스 ###
일반적인 데스크탑 PC의 부팅은 다음과 같은 순서를 가진다.
BIOS(Basic Input/Output System)
처음 PC에 전원을 넣으면 BIOS는 자체적인 테스트 POST(Power On Self Test)를 수행하여
어떤 장치가 있으며 그것들이 제대로 동작하는지를 체크하고 초기화한다.
그리고 부팅 하기위해 플로피 디스크나 CD-ROM 또는 하드디스크의 부트 섹터를 읽는 작업을 한다.
부트 로더
보통 MBR(Master Boot Record) 이나 플로피 디스크일 경우 디스크의 첫번째 섹터 에서 동작한다.
리눅스에서는 LILO나 GRUB을 사용하고, 부트 로더가 존재하지 않는다면 커널이미지가
첫번째 섹터부터 쓰여지게 하면 부트 로더 없이 부팅할 수 있다.
커널
BIOS나 부트 로더에 의해 로딩된 커널은 주변장치와 하드웨어를 초기화하고 루트 fs을 찾는uf
이 다음과정이 init 프로세서를 fork 하는것이다.
init
커널 소스의 init/main.c를 보면 알수 있듯이 /sbin/init, /etc/init, /bin/init, /bin/sh 순으로 실행한다.
만약 부팅시 커널 옵션에 'init='을 정의해 놓았다면 그것이 실행된다.
이후 /etc/inittab 파일을 읽어서 지정된 레벨로 실행한다.
getty
일반적으론 /etc/inittab에 정의된대로 getty가 /bin/login을 실행 한다.
login
login이 수행되면 모니터에서 'login: '을 볼 수 있으며 인증방식을 통해 인증을 거쳐
shell을 실행하게되면 비로서 shell 프롬프트가 뜨고 키보드를 통한 입력이 가능하다.
### 부팅 과정 ###
모든 PC 시스템들은 롬(BIOS) 내의 코드를 실행시키는 것으로 부팅을 시작한다. 이 코드는
부트 드라이브의 섹터 0, 실린더 0 부분을 읽고, 바이오스는 읽어들인 이 섹터의 내용을 실행한다.
대부분의 부트 가능한 디스크들은 섹터 0, 실린더 0 영역에 다음 내용 중 하나를 담고 있다.
- LILO 등과 같은 부트로더(boot loader)의 코드
- 리눅스 등과 같은 운영체제 커널의 시작 부분.
만일 리눅스 커널이 디스켓에 직접 복사된 경우 (raw copy)라면 디스크의 첫번째 섹터는
리눅스 커널 그 자체의 첫번째 섹터가 된다. 이 첫번째 섹터는 부트 디바이스로부터 커널의
나머지 부분을 계속 읽어 들임으로써 부트 프로세스를 진행한다.
일단 커널이 완전히 로드되면, 이제 기본적인 디바이스들을 초기화 시킨다. 그 다음, 특정 디바이스에서
루트 fs을 찾아 / 에 마운트 하려고 시도한다. 이때 커널은 어디에서 루트 fs을 찾아야
하는지를 미리 지정받아 알고있어야 한다. 만일 커널이 그 위치에서 로드 가능한 이미지를 찾지 못한다면
시스템은 멈춰버리게 된다. 디스켓에서 부팅하는 경우 루트 fs을 램디스크로 로드하기도 한다.
일단 루트 fs이 로드되어 마운트되면 다음과 같은 메시지를 볼 수 있다.
VFS : Mounted root (ext2 filesystem) readonly.
이 시점에 이르면 시스템은 루트 fs에 있는 init 프로그램을 찾아서 실행시킨다
init 는 설정파일인 /etc/inittab 에서 sysinit 라인을 찾아 그에 해당하는 이름의 스크립트를 실행하고
이 스크립트는 쉘 명령어로 아래와 같은 기본적인 시스템 서비스를 제공한다.
- 모든 디스크에 fsck 를 실행한다.
- 필요한 커널 모듈을 로드한다.
- 스왑핑(swapping)을 시작한다.
- 네트웍을 초기화시킨다.
- fstab 에 적힌 디스크들을 마운트한다.
이 스크립트는 대개 다른 여러가지 스크립트들을 동작시킨다. 즉, 초기화 과정을 모듈화시킨 것이다
일반적인 SysVinit 구조에서는 /etc/rc.d/ 디렉토리 밑에 복잡한 구조의 하위디렉토리가 있고 각각의
하위디렉토리에는 수많은 시스템 서비스들을 어떻게 온오프 시키는지를 정해놓은 파일들이 있다.
하지만 부트 디스크에서 사용하는 sysinit 스크립트는 보통 매우 간단하다.
sysinit 스크립트의 실행이 끝나면 다시 init 프로세스로 조종권이 돌아오고, 이번에는 default runlevel
단계로 들어간다. default runlevel 은 inittab 파일내에 initdefault 키워드로 지정되어 있다.
runlevel 라인은 주로 콘솔이나 tty 를 통한 통신을 책임지는 getty 같은 프로그램을 지정한다.
우리에게 익숙한 login: 프롬프트 따위를 출력해 주는 것이 바로 getty 프로그램이다.
getty 프로그램은 로그인 인증을 처리하는 login 프로그램을 구동시킨 후 user 세션을 마련한다.
### 부트 디스크의 종류 ###
- boot
부트 가능한 커널을 포함한 디스크. 이 디스크는 커널을 부트시키는 용도로 사용되며, 이렇게
로드된 커널은 또다른 디스크에 위치하고 있는 루트 fs을 로드할 수 있다. 보통, 부트 디스크상의
커널은 루트 fs이 어디에 위치하고 있는지를 미리 지정받아 알고 있어야한다.
대부분의 경우 부트 디스크는 다른 디스켓상의 루트 fs을 로드하게 되지만, 때로는 하드디스크에 있는
루트 fs을 로드하도록 설정할 수도있다. 이런 기법은 주로 새로운 커널을 테스트 해볼때 사용된다
(make zdisk 명령은 커널 소스코드로부터 자동으로 부트 디스크를 만든다).
- root
리눅스 시스템 운용에 필수적인 파일들을 가진 fs을 루트 fs이라 하며 이 루트 fs을
담은 디스크가 root 디스크다. 루트 디스크가 반드시 커널이나 부트로더를 가지고 있을 필요는 없다.
커널이 부트된 상태라면 루트 디스크는 다른 어떤 디스크도 필요없이 독자적으로 시스템을 운용할 수있다.
보통, 루트 디스크는 자동적으로 램디스크로 복사된다. 램디스크를 사용하면 루트 fs에 대한
액세스가 훨씬 빠르며, 또한 디스크 드라이브를 비워 유틸리티 디스크를 넣을 수 있다.
- boot/root
커널과 루트 fs을 한장에 모두 가지고 있는 디스크. 바꾸어 말하면, 하드디스크 없이도 이 디스크는
리눅스 시스템을 부트하고 운용하는데 필요한 모든 것을 다 가지고 있는 것이다.
- utility
그 밖의 여러가지 데이터를 담은 디스켓으로서 fs을 가지고 있지만 루트 fs으로서 마운트되는 것은
아니다. 루트 디스크 한장에 다 담기 힘들 경우 여분의 유틸리티들을 이 디스크에 담는다.
일반적으로 부트 디스크를 제작 한다고 말할 때는 boot(kernel) 와 root(files) 부분을 만드는 것을 뜻한다.
두 부분을 하나에 담을 수도 있고 (a single boot/root disk) 두 장의 디스크로 분리하여 담을수도 있다
(boot + root disks). 아마도 boot 디스켓과 root 디스켓을 따로 만들고 그래도 모자라는 경우
한두 장의 utility 디스켓을 더 만드는 것이 복구 디스켓을 제작하는 가장 유연한 방법일 것이다.
##############################
##############################
make bootdisk
# fdformat -n /dev/fd0
*** 경호 bootdisk 제작 스크립트
#!/bin/bash
kernel_block=`expr $(ls -lL /boot/vmlinuz | | awk '{print $5}') / 1024`
otherfiles_block=150
sourcedir="./bootdisk/*"
bootdisk="/mnt/t2/" # temp boot fs location to mount
echo;echo;echo "---------------------0 준비단계"
umount $bootdisk
sync;sync
echo;echo;echo "---------------------1 bootdisk ext2 fs 제작"
mke2fs -i 8192 -m 0 /dev/fd0 $kernel_block
sync;sync
echo;echo;echo "---------------------2 마운트 하기"
mount /dev/fd0 $bootdisk
sync;sync
echo;echo;echo "---------------------3 bootdisk 의 쓸모없는 화일 지우기"
rm -rf ${bootdisk}lost+found
sync;sync
echo;echo;echo "---------------------4 bootdisk 에 화일 복사하기"
cp -dpR ${sourcedir} ${bootdisk}
sync;sync
echo;echo;echo "---------------------5 lilo 실행"
lilo -v -C bdlilo.conf -r $bootdisk
sync;sync
umount $bootdisk
sync;sync
echo;echo;echo;echo "=============================================="
echo "=== 완료 되었습니다. ==="
echo "=============================================="
### 커널 설정 ###
대부분의 경우 현재 시스템의 커널을 그대로 부트 디스켓으로 복사해서 부트해도 되지만
때에 따라서는 별도의 커널을 만들어야 할 때도 있다. 한 장의 boot/root 디스켓을 만들려 한다면
커널은 디스켓 상에서 가장 큰 파일이 되기 때문에 가능한한 그 크기를 줄일 필요가 있다.
*** 시스템 커널에 있는 백업 장비에 대한 I/O 지원은 boot/root 디스켓의 커널에도 포함 시켜야 한다
예로 백업받은 파일들이 모두 테이프에 담겨있고 테이프 드라이브를 액세스하기 위해서는
ftape 를 써야만 하는 시스템이 있다고 하자, 만약 Ftape를 포함하고 있는 루트 드라이브에
문제가 발생했다면 이제는 백업테이프를 써서 복구할 방법이 없다.
결국, 리눅스를 새로 설치후, ftape 를 다시 인스톨 해야 백업 테이프를 읽어올 수 있다
- boot/root 시스템을 기동하는 것과 무관한 다른 디스크 드라이브에 대한 지원도 빼버려라.
네트워킹이 그 좋은 예다. 기타 불필요한 디바이스들도 버리는 것이 좋다.
- 압축된 ext2 fs을 부트하기 위해서 램디스크와 ext2 에 대한 지원은 커널안에 포함시켜야 한다.
- 최소한의 기능만을 포함한 커널을 만들었다면 이제 다시 무엇을 추가할수 있을지 확인해 보아라.
boot 디스켓의 주된 용도는 손상된 fs을 복구하는 것일 테니 커널 차원의 지원이 필요하다.
#####
##### bootdisk 제작 - LILO 와 커널을 함께 담기 ###
부트로더의 일종인 LILO 를 사용할지 여부를 결정해야 한다.
LILO 를 쓰면 하드웨어를 초기화 시키는 파리메터를 부팅시에 알려줄수 있다는 점이다
LILO 의 단점은 부트 디스크가 보다 복잡해 지고 용량을 조금 더 차지 한다는 점이다.
LILO 를 위한 작은 설정파일을 만든다. (btlilo.conf)
prompt
delay = 150
timeout = 50
default = bootdisk
boot = /dev/fd0
map = /boot/map
install = /boot/boot.b
backup = /dev/null
lba32
compact
read-write
image = /boot/vmlinuz
label = bootdisk
root = /dev/fd0
read-only
image = /boot/vmlinuz
label = harddisk
root = /dev/hda5
initrd = /boot/initrd-redhat.img
read-only
이제 커널 fs이라 불리우는 작은 fs을 만들어야 한다. 이것은 루트 fs과 는 별개의 것이다.
먼저, fs의 크기를 얼마로 해야할지 알아내야 하고, 만들어낸 커널의 블록 단위 크기가
얼마 인지 확인후 (vmlinuz-2.4.20-8 의 크기 / 1024) 70 을 더한다.
70 블록은 inode 와 그 밖의 몇 가지 파일들에 필요한 대략적인 크기다.
첫번째 디스크는 커널 전용으로만 사용되기 때문에 두장의 디스켓으로 하면 넉넉히 잡아도 좋다.
계산한 숫자를 KERNEL_BLOCKS 라고 부르기로 하자.
# ls -l /boot/vmlinuz-2.4.20-8
-rw-r--r-- 1 root root 1122186 3월 14 2003 /boot/vmlinuz-2.4.20-8
# expr 1122186 / 1024
1095
# mke2fs -i 8192 -m 0 /dev/fd0 KERNEL_BLOCKS
-i 8192 8192 바이트 당 하나의 inode 를 할당
-m 0 mke2fs 가 root 용 공간을 할당하지 못하게한다
# mount /dev/fd0 /mnt
# rm -rf /mnt/lost+found
# mkdir /mnt/{boot,dev}
# cp -dpR /dev/{null,fd0} /mnt/dev
디바이스 /dev/null 과 /dev/fd0 를 만든다.
# cp /boot/{map,boot.b} /mnt/boot/
LILO 는 그 부트로더인 boot.b 의 복사본을 필요로 한다
# cp /boot/vmlinuz-2.0.0 /mnt/boot/vmlinuz
# cp bdlilo.conf /mnt
마지막으로 앞 절에서 만든 LILO 설정 파일을 커널과 함께 플로피로 복사해 넣는다.
# lilo -v -C bdlilo.conf -r /mnt
-r 부트로더를 다른 루트에 설치할 때 사용된다.
#####
##### bootdisk 제작 - LILO 없이 커널만 담기 ###
# dd if=/boot/vmlinuz of=/dev/fd0 bs=1k
668+1 records in
668+1 records out
LILO 를 사용하지 않겠다면 dd 명령을 써서 커널을 부트 디스크에 담아야 한다.
위의 예에서 dd 는 668 개의 완전한 레코드와 1개의 부분 레코드를 써넣었다.
따라서 커널은 디스켓 앞부분의 669 블록들을 점유하게 된다.
이 숫자를 KERNEL_BLOCKS 라고 부르겠으니 기억해 두어라.
# rdev /dev/fd0 /dev/fd0
# rdev -R /dev/fd0 0
루트 디바이스를 디스켓 자체로 설정한 후 루트가 read/write 로 로드 되도록 설정한다.
# dd if=/dev/fd0 of=work-img.gz bs=1k seek=670
두번째 램 디스크 이미지는 work-img.gz이며 위명령을 사용해서 플로피에서 직접 읽어 올 수 있다.
리눅스 플로피 fs은 한 플로피에 2개의 fs을 가지고 있다.
커널 이미지를 담고 있는 부트 fs과 작업을 위한 프로그램을 가진 램 디스크 이미지이다.
플로피의 앞부분 669K 바이트가 ext2 fs으로 만들어져 있으며
커널 이미지와 lilo를 사용한 부팅 옵션을 위한 파일들 그리고 부팅할 때 나오는 메세지가 담겨 있다.
#####
##### 램디스크 워드의 설정 ###
커널 이미지의 최초 512 (램디스크 워드) 바이트 안에 커널 설정이 있다. rdev 명령을 써서
확인 및 설정이 가능하고, 이것은 다른 옵션들과 더불어서 루트 fs을 어디서 찾을 것인지 설정한다.
LILO를 사용 하겠다면 마운트될 커널의 경로 (/mnt/vmlinuz)를 rdev 파라메터로 써야 한다.
LILO를 쓰지 않고 커널을 dd 명령으로 복사했다면 플로피 디바이스의 이름을 써준다 (/dev/fd0)
# rdev -r KERNEL_OR_FLOPPY_DRIVE VALUE
### 그내용은 다음과 같이 해석한다. ###
bit 0-10 램디스크가 시작하는 오프셋. 1024 byte 블록 내의 오프셋
bit 11-13 사용하지 않는다
bit 14 램디스크로 로딩될지를 나타내는 플래그
bit 15 루트 fs을 로딩하기 전에 한번 멈출지를 결정하는 플래그
만약 15번 비트가 설정되어 있으면 부팅시에 새로운 디스켓을 집어 넣으라는 메시지를 받게 된다
이 기능은 두 개의 디스크로 부팅할 경우 필요하다.
한 개의 boot/root 디스켓을 만들 것인지 두개의 "boot+root" 디스켓을 만들 것인지에 따라
다음 두 가지 경우가 생길 수 있다.
*** 한개의 디스켓을 만든다면 압축 루트fs은 커널 바로 뒤에 연이어 위치하게 되므로 그 오프셋은
첫번째 빈블럭 (KERNEL_BLOCKS 값과 동일) 이된다. 비트 14는 1로, 비트 15는 0으로 설정하라
(당신이 한장짜리 디스크를 만드는데 루트 fs이 253 블록(십진수)에서 시작 한다고 치면
램디스크 워드의 값은 253(십진수) 에다 비트 14 는 1, 비트 15 는 0 으로 세팅한 값을 주어야한다)
이 램디스크 워드 값을 구하려면 모두 십진수로 변환해 더하면 된다.
253 + (2^14) = 253 + 16384 = 16637
# rdev -r /mnt/floopy/boot/vmlinuz 16637
*** 두개의 디스켓 세트를 만든다면 루트 fs은 두 번째 디스켓의 0 번 블록부터 시작할 것이고
따라서 그 오프셋은 0 이다. 비트 14는 1로, 비트 15도 1로 설정하라.
따라서 램디스크 워드의 십진수 값은 2^14 + 2^15 = 49152 가 된다.
램디스크 워드에 해당하는 값을 주의깊게 계산한 다음, 그 값대로 rdev -r 명령으로 설정한다.
십진수를 사용해야 함에 주의하라.
# rdev -r /mnt/floopy/boot/vmlinuz 49152
LILO를 사용한다면 이제 디스켓을 언마운트 시키십시오.
##############################
##############################
rootdisk
*** 경호 lib 디렉토리 카피 스크립트
작동하지 않는다. cp -dpR /lib/${libfiles} $rootdisk 문구 에서 ${libfiles} 를
쉘이 정규식으로 확장한후 cp 명령의 인수로 넘겨야 하는데.
셀이 확장을 하지 않고 "{....}" 문자열로 cp 로 넘어가기에
"{모든화일}" 라는 화일명 1개가 인수로 넘어간 것과 같다. 그래서 안되징..
#!/bin/bash
libfiles="ld-2.3.2.so,ld-linux.so.2,\
libc-2.3.2.so,libc.so.6,\
libcom_err.so.2.0,libcom_err.so.2\
libcrypt-2.3.2.so,libcrypt.so.1,\
libdl-2.3.2.so,libdl.so.2,\
libe2p.so.2.3,libe2p.so.2,\
libext2fs.so.2.4,libext2fs.so.2,\
libpam.so.0.75,libpam.so.0,\
libpam_misc.so.0.75,libpam_misc.so.0,\
libpcre.so.0.0.1,libpcre.so.0,\
libproc.so.2.0.11,\
libresolv-2.3.2.so,libresolv.so.2,\
libtermcap.so.2.0.8,libtermcap.so.2,\
libuuid.so.1.2,libuuid.so.1" # source lib files
rootdisk="/mnt/tmp2/lib" # root disk lib directory
cp -dpR /lib/${libfiles} $rootdisk
*** 경호 rootdisk 제작 스크립트
#!/bin/bash
workdir="/root/"
rootfile="rootfile.ccc" # temp roof device file name
rootsize="4500" # temp roof device file size (4200=3.8M)
rootdisk="/mnt/t2/" # temp root fs location to mount
# root file directory to copy
rootsrcdir="./rootdisk/*"
echo;echo;echo "---------------------0 준비단계"
umount $rootdisk; rm -f ${workdir}${rootfile} ${workdir}rootfs.gz
sync;sync
echo;echo;echo "---------------------1 루프 디바이스 화일 생성"
dd if=/dev/zero of=${workdir}${rootfile} bs=1k count=$rootsize
sync;sync
echo;echo;echo "---------------------2 루프 디바이스 화일 시스템 생성"
mke2fs -m 0 -i 1024 ${workdir}${rootfile}
sync;sync
echo;echo;echo "---------------------3 루프 디바이스 화일 마운트"
mount -o loop -t ext2 ${workdir}${rootfile} $rootdisk
sync;sync
echo;echo;echo "---------------------4 루프 디바이스 화일로 루트 디스크 화일 복사"
cp -dpR $rootsrcdir $rootdisk
sync;sync
echo;echo;echo "---------------------5 루프 디바이스 화일 압축"
dd if=${workdir}${rootfile} bs=1k | gzip -v9 > ${workdir}rootfs.gz # 루트 fs 생성
sync;sync
echo;echo;echo "---------------------6 플로피 디스크 생성"
dd if=${workdir}rootfs.gz of=/dev/fd0u1722 bs=1k # 루트 fs을 두번째 디스켓에 담을때
sync;sync
umount $rootdisk
rm -rf ${workdir}${rootfile} ${workdir}rootfs.gz
sync;sync
echo;echo;echo;echo "=============================================="
echo "=== 완료 되었습니다. ==="
echo "=============================================="
#####
##### 루트 fs의 크기를 줄이는 방법 ###
때로는 루트 fs이 너무 커서 압축을 해도 디스켓 한 장에 다 들어가지 않을 수도 있다.
다음은 fs의 크기를 줄이는 몇가지 방법이다.
- 디스크의 밀도를 높인다
기본적으로 플로피 디스켓은 1440 K 로 포맷됩니다, 하지만 더 높은 밀도의 포맷도 가능하다.
fdformat 는 디스크를 1600, 1680, 1722, 1743, 1760, 1840, 1920 크기로 포맷할 수 있다
대부분의 1440 K 드라이브들은 1722 K 의 포맷을 지원한다
(man fdformat, /usr/src/linux/Documentation/devices.txt 참조)
- 쉘을 바꾼다
bash, tcsh 은 크기도 크고 많은 라이브러리들을 필요로 한다. ash, lsh, kiss, smash 같은
경량급 쉘들은 훨씬작고 라이브러리를 별로(전혀) 필요로 하지 않으므로 대안이 될수있다.
이러한 대용 쉘들은 대부분 다음 홈페이지에서 찾을 수 있다.
http://metalab.unc.edu/pub/Linux/system/shells/
어떤쉘을 사용하던 부트 디스크에 포함시킨 rc 파일들 내의 명령어를 실행시킬 수 있어야 한다.
- 스트립 라이브러리와 바이너리들을 사용한다
라이브러리들과 바이너리들은 보통 스트립되지 않은(즉, 디버깅 심볼을 포함하는) 상태로 존재한다.
이런 파일에 대해 "file" 명령을 실행하면 "not stripped" 라는 결과가 출력된다.
# objcopy --strip-all FROM TO
바이너리들을 루트 fs으로 복사할 때는 위과 같은 습관을 들이는 것이 좋다.
# objcopy --strip-debug FROM TO
라이브러리를 복사할 때
- 중요하지 않은 파일들은 유틸리티 디스크로 옮긴다
부트나 로그인 시에 반드시 필요한 것이 아니라면 유틸리티 디스크로 옮겨놓는다.
모듈들을 유틸리티 디스크로 옮겨놓는 것도 고려해 볼만하다.
#####
##### 모듈 ###
모듈화된 커널을 사용한다면 부팅 후 부트 디스크로 부터 어떤 모듈을 로드 해야할지를 고려해야만 한다.
만약 백업 테이프들이 플로피 테이프상에 있다면 ftape 와 zftape 모듈을 포함시켜야 하고 SCSI 장비를
가지고 있다면 SCSI 관련 모듈을 포함시켜야 하며 만일 응급상황에서 네트웍에 액세스해야 한다면
PPP 나 SLIP 관련 모듈을 포함시켜야 한다.
- 모듈들은 /lib/modules 에 두면 된다.
- insmod, rmmod, lsmod 프로그램을 포함 시켜야 한다.
- modprobe, depmod, swapout 도 포함시켜야 한다. (모듈을 자동으로 로드하고 싶다면)
- kerneld 를 사용한다면 kerneld 를 /etc/conf.modules 의 설정에 맞추어 포함시켜야 한다.
#####
##### PAM 과 NSS 에 대한 대책 ###
PAM (Pluggable Authentication Modules)
당신 시스템에는 ldd 로 확인할 수 없는 동적으로 로드되는 라이브러리가 필요할 수도 있다.
만일 시스템이 PAM을 쓰고 있다면 부트 디스크 상에 PAM 을 위한 몇가지 준비를 해야한다.
그러지 않으면 로그인이 불가능할 것이다.
PAM 이란 사용자를 인증하고 사용자들의 서비스에 대한 액세스를 컨트롤하는 모듈화된 방법이다.
시스템이 PAM 을 쓰고있는지 확인해보려면 /etc/pam.conf 이나 pam.d 디렉토리가 있는지 체크.
그런 것이 있다면 최소한의 pam 지원은 하고 있는 것이다
(login 실행파일에 대해 ldd 를 해보자. libpam.so 가 출력되면 PAM 이 필요하다는 뜻).
운좋게도, 부트 디스크에 있어서 보안은 보통 관심밖의 사항이다.
물리적 액세스를 할 수 있는 사람은 그만한 권한이 있는 사람일 것이다. 따라서,
다음과 같은 간단한 /etc/pam.conf 파일을 만들어두면 PAM 기능을 무력화시킬 수 있다.
OTHER auth optional /lib/security/pam_permit.so
OTHER account optional /lib/security/pam_permit.so
OTHER password optional /lib/security/pam_permit.so
OTHER session optional /lib/security/pam_permit.so
- /lib/security/pam_permit.so 를 루트 fs으로 복사하라.
이렇게 하면 머신의 파일이나 서비스에 누구든지 제한없이 액세스할 수 있다
어떤 이유로 부트 디스크상의 보안에도 신경을 써야 한다면
하드디스크의 PAM 설정의 일부 혹은 전부를 당신의 루트 fs으로 복사 해야한다.
(PAM 에 관한 문서를 주의깊게 읽은후 /lib/security 에서 필요한 라이브러리들을 루트 fs로 복사)
또한 /lib/libpam.so 를 부트 디스크에 포함 시켜야만 한다.
(앞의 /bin/login 에 ldd 를 실행시켰을때 의존성을 눈치챘을 것이다.)
# cp /lib/libpam.so /mnt/lib/
# cp /etc/pam.d/{login,passwd} /mnt/etc/pam.d/
필요한 설정 화일을 카피한다.
#####
##### NSS (Name Service Switch) ###
glibc(일명 libc6)를 사용하고 있다면 name service 에 대한 준비를 해야한다. 그렇지 않으면
로그인이 불가능할 것이다. /etc/nsswich.conf 는 여러가지 서비스에 대한 db 열람을 컨트롤한다.
네트웍상의 서비스(DNS, NIS lookup)에 액세스 할 필요가 없다면 간단한 nsswitch.conf 파일만 준비하면 된다.
이것은 모든 서비스가 오로지 로컬 파일에서 제공되는 것으로 설정한 것이다.
passwd: files
shadow: files
group: files
hosts: files
services: files
또한 /lib/libnss_files.so.1 을 포함 시켜야한다.
이것은 파일 열람(file lookup)을 처리할 때 동적으로 로드되는 라이브러리다
부트 디스크에서 네트웍에 액세스할 작정이라면 보다 정교한
nsswitch.conf 파일을 만들 필요가 있다. (nsswitch 맨 페이지를 참고)
당신이 설정한 service 들에 대해 각각에 해당하는 /lib/libnss_service.so.1 파일들을
포함시켜야만 한다는 점을 명심하라.
##############################
##############################
make rootdisk - 압축된 루트 fs의 제작
루트 fs을 만들때는 시스템 구동에 필수적인 파일들을 고르는 작업이 필요하다.
잘 쓰이지는 않지만 압축안된 fs을 디스켓상에 만들어 루트로 마운트시키는 방법도 있다
루트 fs은 풀 사이즈의 완전한 리눅스 시스템을 지원하기 위한 모든 것을 갖추어야 한다.
이를 위해서는 리눅스 시스템에 꼭 필요한 최소요건 만큼은 루트디스크에 반드시 구비되야 한다.
- 기본적인 fs 구조
- 최소한도의 디렉토리들 : /dev, /proc, /bin, /etc, /lib, /usr, /tmp
- 기본적인 유틸리티들 : sh, ls cp mv 등
- 꼭 필요한 config 파일들: rc, inittab, fstab 등
- 디바이스들 : /dev/hd*, /dev/tty*, /dev/fd0 등
- 유틸리티 프로그램에 필요한 기본적인 함수들을 제공하는 런타임 라이브러리.
루트 디스켓으로 다음과 같은 작업을 할수 있어야만 한다
- 다른 드라이브에 있는 fs을 체크하는 작업.
- cpio, tar, gzip, ftape 등의 archive 및 압축 유틸리티를 써서 백업으로부터
원래의 루트드라이브의 전부 혹은 일부를 복구하는 작업
#####
##### fs 만들기 ###
압축된 루트 fs을 만들기 위해서는 압축하기전 필요한 모든 파일들을 담을 수 있는 충분한 크기의
빈 공간이 필요하다. (약 4 메가바이트)
압축 fs은 fs이 압축된 상태로 있다가 부트시에 램디스크로 압축이 풀리면서 복사되는 것을 말한다.
압축 fs을 쓰면 표준 1440K 디스켓에 훨씬 많은 파일(약 6메가)들을 넣을 수 있다.
fs이 디스켓의 용량보다 훨씬 크기 때문에 디스켓 위에 이를 직접 작성하는 것은 불가능하다.
일단 다른 곳에서 fs을 완전히 만들어 압축한 다음, 그 압축된 것을 디스켓에 복사하는 방법을 써야한다.
==========================================================================================
>>> 압축된 fs을 부트하기 위해서는 램디스크와 ext2 지원을 반드시 커널에 내장시 켜야한다 <<<
==========================================================================================
만약 쓰지 않는 수메가바이트의 하드디스크 파티션이 있어 이를 이용할 수 있다면 아주 좋은 방법이다.
### 램디스크를 사용하는 방법 (DEVICE = /dev/ram0) ###
/dev/ram0, /dev/ram, /dev/ramdisk 등의 디바이스를 가지고 있는지 확인하고, 만일 없다면
====================================================================
>>> mknod 명령 (major number 1, minor 0)으로 /dev/ram0를 만든다. <<<
====================================================================
메모리 일부를 가상의 디스크 드라이브로 설정하고, 램디스크는 필요한 크기의 fs을 담을수 있어야 한다.
만일 LILO 를 쓰고 있다면 /etc/lilo.conf 에 "RAMDISK_SIZE = nnn" 라인이 있는지 확인하라
이것은 할당가능한 램디스크 크기의 최대치를 설정한다. 디폴트는 4096K 인데 이 정도면 충분하다
### 루프백 디바이스를 이용 ###
루프 디바이스(/dev/loop0, /dev/loop1)가 없다면
===============================================
>>> mknod /dev/loop0 b 7 0 명령으로 만든다. <<<
===============================================
루프백 디바이스는 파일 하나를 마치 디바이스처럼 취급할 수있다.
즉, 파일 한개를 마치 하드디스크의 파티션처럼 인식시키는 것이다. 루프백 디바이스를 이용해서
하드 디스크 상에 3 메가바이트 가량의 파일을 만든후 이 위에 fs을 만들 수 있다. (man losetup)
ftp://ftp.win.tue.nl:/pub/linux/util/mount/ 에서 util-linux 패키지를 받아 설치하자
# dd if=/dev/zero of=[RAM_DEVICE or loopback_filename] bs=1k count=3000
하드디스크 상에 충분한 크기의 임시 파일을 만든다.
루프백 디바이스를 사용하면 DEVICE 자리에 파일이름을 써야 한다.
디바이스의 내용을 모두 0 으로 채운다. 이 과정이 중요한 이유는 디바이스 상의 fs은
나중에 압축되게 되므로 사용되지않은 모든 영역은 0 으로 채워야 최대한으로 압축할수 있다.
# mount -o loop -t ext2 [RAM_DEVICE or loopback_filename] /mnt
-o loop 옵션을 주어 mount 프로그램에게 루프백 디바이스를 마운트함을 알려야 한다.
위는 루프백 디바이스를 통해 filename 를 마운트포인트 /mnt 에 마운트 시킨다.
앞으로 우리가 만들 모든 디렉토리들은 /mnt 아래에 있는 것으로 가정하자
# mke2fs -m 0 -i 1024 [RAM_DEVICE or loopback_filename]
fs을 만든다. mke2fs 명령은 자동으로 사용가능 용량을 인지하고 fs을 설정한다.
-m 0 root 용 공간을 할당하지 못하게한다 (사용가능한 디스크 용량을 더많이 확보)
-i 1024 1024 정도로 설정하면 inode 가 부족해지는 일은 없다.
커널이 자동으로 램디스크로 복사할수 있는 루트 디스크 fs은 minix 와 ext2 두가지 뿐이다
ext2 를 쓰면 -i 옵션을 주어 디폴트값 보다 더많은 inode 를 설정할 수 있고,
mke2fs 는 디폴트로 1.44 M 디스켓에 360 개의 inode를 생성한다.
또는
# head -c 1000000 < /dev/zero > file ::: 지정된 크기로 파일을 설정
# losetup /dev/loop0 file ::: 루프백 디바이스로 설정
# mke2fs /dev/loop0 ::: fs 만들기
# mount -o loop /dev/loop0 /mnt
#####
##### fs의 구성 - 화일 복사 ###
다음은 일반적인 루트 fs에 들어있어야할 최소한의 디렉토리다.
/proc proc fs에 필요한 디렉토리
/dev I/O 에 필요한 디바이스들이 위치.
/lib 런타임 공유라이브러리들이 위치.
/etc 시스템 설정파일들이 위치.
/sbin 시스템에 없어서는 안될 필수 바이너리들이 위치.
/bin 시스템의 일부로 간주되는 기본적인 바이너리들이 위치.
/mnt 다른 디스크들을 관리하기 위한 마운트포인트
/usr 그밖의 여러 유틸리티와 응용프로그램들이 위치.
여기에 제시된 디렉토리 구조는 루트디스켓에 해당되는 것만 적은 것이다.
실제의 리눅스 시스템은 보다 복잡하고 세련된 디렉토리 구조에 관한 규약을 가지고 있다.
이를 표준 계층 fs (FHS, Filesystem Hierarchy Standard)라 부르는데
각 파일들을 어느 디렉토리에 두어야 하는가에 대한 규약이다
/proc 디렉토리는 단순히 proc fs이 위치하게 되는 장소이고,
/mnt 와 /usr 는 boot/root 시스템 가동후 사용되는 마운트 포인트다.
따라서 이 3 가지는 mkdir 명령으로 디렉토리만 만들어 주면 된다.
#####
##### /dev ###
디바이스(장치) 노드가 위치한다.
- 디렉토리에는 시스템이 사용하는 모든 디바이스들 각각에 대응하는 특수파일들이 위치한다
- 디렉토리 자체는 보통의 디렉토리와 같으므로 mkdir 명령어로 그냥 만들어 주면된다.
- 여기의 파일은 메이저와 마이너 넘버로 각 장치를 구분하며 mknod 명령으로 노드를 만들 수 있다.
- Devfs(디바이스 fs)는 /proc과 같은 가상 fs이기 때문에
디렉토리내 특별히 여러 노드를 만들지 않아도 된다.
보다 간단한 방법은 시스템의 /dev 디렉토리의 내용들을 복사한후 필요 없는 것들을 지운다.
이때 유념해야 할것은 특수 디바이스 파일들을 복사해 올때는 -R 옵션을 써서 복사해야 한다
이렇게 해야 디렉토리가 복사될 때 파일들의 내용들은 복사되지 않게된다.
# cp -a /dev /mnt
# cp -dpR /dev /mnt
디스켓이 /mnt 에 마운트 되었다고 가정한 것이다.
-dp 심볼릭 링크가 복사될때 타겟파일들이 복사되는 것이 아니라 링크로서 복사되도록 해주며
원래의 파일 속성이 그대로 유지된 채 복사되도록 한다. (파일 소유권을 그대로 유지)
어려운 방법으로 해보고 싶다면 ls -l 로 원하는 디바이스의 메이저와 마이너 디바이스 넘버를
출력해서 확인한 후 mknod 명령을 써서 직접 만들어 주는 방법도 있다.
디바이스들을 복사했으면, 원하는 특수 디바이스들이 복구디스켓에 제대로 들어갔는지 확인한다
각각의 특수 디바이스 파일은 하나씩의 inode 를 필요로 하기 때문에, 경우에 따라서는
inode 가 부족 할 수 있다. 따라서 필요없는 디바이스 파일들은 디스켓에서 제거하자.
SCSI 를 가지고 있지 않다면 sd로 시작하는 모든 디바이스 파일들은 삭제해도 무방하고,
시리얼 포트를 사용할 일이 없다면 cua 로 시작하는 파일들은 지워도 된다
/dev 디렉토리에 다음 화일들은 반드시 있어야 한다
console, kmem, mem, null, ram, tty1
#####
##### /etc ###
/etc 디렉토리에는 설정파일들이 위치한다.
대부분의 시스템에 있어 설정파일들은 다음 세가지 정도로 분류할 수 있다.
1. 어떤 경우든 반드시 필요한 파일 rc, fstab, passwd 등
2. 꼭 그런 것은 아니나 대체로 필요하다고 생각되는 파일들
3. 그외의 파일들
# ls -ltru /etc
마지막으로 액세스된 시간순으로 파일들을 출력하여 필수적인 파일인지 아닌지 확인해보자
최근 액세스된 적이 없는 파일들은 루트디스켓에서 제외시켜도 된다.
필자의 루트디스켓에는 약 15 개 정도의 설정파일이 있고, 용도에 따라 세가로 나누어 보겠다.
1. 시스템을 설정하는데 꼭 필요한 설정파일들
rc.d/* 시스템 기동 및 런레벨 변환 스크립트
fstab 마운트되는 fs의 리스트
inittab init 프로세스에 대한 파라메터들이 담겨있다.
2. 시스템 정돈에 필요한 설정파일들
passwd 사용자, 홈 디렉토리 등등의 리스트. passwd 는 적어도 root 를 포함하고 있어야 한다.
group 사용자 그룹
shadow 사용자들의 패스워드. 없을 수도 있다.
termcap 터미널의 능력에 대한 db
주로 사용하는 터미널인 linux-console 엔트리만 남기고 나머지는 삭제하라.
보안이 중요한 경우 사용자 패스워드가 시스템을 떠나 존재하지 않도록
passwd 와 shadow 는 디스켓으로 복사해오지 않는 것이 좋다.
이렇게 해두면 디스켓으로 부팅시 원치않는 사용자의 로그인을 막을수 있다.
다른 사용자들도 로그인할수 있게 하려면 그사용자의 홈 디렉토리와 쉘을 만들어 주어야 한다.
3. 그 밖의 설정파일들
필자는 이 중에서 두 가지 파일만큼은 반드시 설정해주는데 그 내용은 무척이나 간단하다.
- rc 에는 다음과 비슷한 내용이 반드시 들어있어야 한다. 디렉토리가 맞는지 확인하라.
#!/bin/sh
echo Root device system read/write mount
/sbin/mount -w -n -o remount /
echo fstab mount
/bin/mount -av
echo Set Hostname to acsecret
/bin/hostname acsecret
/bin/login
- fstab 에는 최소한 다음 내용은 들어있어야 한다.
/dev/ram0 / ext2 defaults
/dev/fd0 / ext2 defaults
/proc /proc proc defaults
현재 사용하고 있는 fstab 의 엔트리를 복사해도 된다.
하드디스크 피티션을 자동으로 마운트하게 해서는 안된다. (noauto 키워드를 쓰라)
하드디스크가 손상되었거나 죽어버려서 부트 디스크를 사용해야할 경우도 있기 때문이다.
- inittab 의 sysinit 라인은 rc 나 기본적인 부트 스크립트를 구동시킬수 있도록 수정하라
시리얼 포트쪽으로 사용자가 접속하는 것을 막으려면 getty 설정 엔트리중 라인 끝부분에 ttys 나
ttyS 디바이스가 적힌 엔트리들은 주석처리 해야한다. 단, 콘솔로 로그인할 tty 포트들은 남겨두자.
id:2:initdefault:
si::sysinit:/etc/rc
1:2345:respawn:/sbin/getty 9600 tty1
2:23:respawn:/sbin/getty 9600 tty2
세심하게 체크해야할 것은 inittab 에서 언급된 화일들이 정말로 제자리에 있는지의 여부다.
만일 init 가 해당 파일을 찾지 못하면 멈춰버리게 되며 에러 메시지조차 뜨지 않을수도 있다.
어떤 프로그램들은 다른 위치에 있는 것이 허용되지 않고 정해진 디렉토리에 위치해야 한다.
이는 프로그램들이 이 프로그램이 이곳에 위치할 것이라고 간주하여 코딩되었기 때문이다.
예를들어 필자의 시스템은, /etc/shutdown 은 reboot 의 위치를 /etc/reboot 라고 간주하여
코딩되었다. 만일 필자가 reboot 파일을 /bin/reboot 에 둔 후 shutdown 명령을 내린다면,
/etc 디렉토리에서 reboot 파일을 찾을 수 없으므로 shutdown 명령은 실패할 것이다
가장 확실한 방법은 inittab 에서부터 시작해서 필요한 것들을 하나하나 확인해 나가는 방법 뿐이다.
대부분의 시스템들은 각각의 런레벨에 해당하는 쉘 스크립트들을 /etc/rc.d/ 밑에 두고 있다.
가장 단순하게 하려면 rc 스크립트 하나면 되지만, 본래 시스템으로부터 inittab와 /etc/rc.d 를
통째로 복사한 후 디스켓에 필요없는 스크립트들을 지워나가는 방법이 보다 편리할 것이다.
- 기타
/etc/nsswitch.conf
/etc/mtab
/etc/profile
~/.bashrc
#####
##### /lib ###
시스템에 있어서 가장 중요한 glibc(C 라이브러리)를 포함하여 모든 라이브러리 파일이 위치하는 곳이다.
어떠한 리눅스 명령어도 glibc가 없다면 실행될 수 없다.(static으로 컴파일된것 제외.)
/lib 에는 필요한 공유 라이브러리들과 로더들을 두어야 한다.
필요한 라이브러리들이 /lib 디렉토리에서 발견되지 않는다면 시스템은 부트에 실패하게 된다.
커널이 필요한 라이브러리를 로드하지 못하면 대부분의 경우 에러메시지조차 없이 그냥 멈추어 버린다.
일부 라이브러리들은 상당히 커서 당신의 루트 fs에 쉽사리 들어가지 않을 수 있음에 주의.
이런 라이브러리들을 루트 fs으로 옮기려면 스트립(strip) 시킬 필요가 있다.
(사용법은 루트fs의 크기를 줄이기 절을 참조)
# ls -l /lib/libc.so*
-rwxr-xr-x 1 root root 4016683 Apr 16 18:48 libc-2.1.1.so*
lrwxrwxrwx 1 root root 13 Apr 10 12:25 libc.so.6 -> libc-2.1.1.so*
거의 모든 프로그램들이 적어도 libc 라이브러리인 libc.so.N 만큼은 반드시 필요로 한다.
여기서 N은 현재의 버전넘버를 뜻한다. (당신의 /lib 디렉토리를 확인)
보통, libc.so.N 은 완전한 버전넘버를 가진 파일이름에 심볼릭 링크되어 있다.
# ldd /sbin/mke2fs
libext2fs.so.2 => /lib/libext2fs.so.2 (0x40014000)
libcom_err.so.2 => /lib/libcom_err.so.2 (0x40026000)
libuuid.so.1 => /lib/libuuid.so.1 (0x40028000)
libc.so.6 => /lib/libc.so.6 (0x4002c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
포함시키려고 하는 바이너리들이 어떤 라이브러리들을 필요로 하고 있는지
의존성을 검사해 보려면 ldd 명령어를 사용하라. (ldd는 libc-2.1.1.so 가 필요하다)
오른편의 각 파일들이 필요함을 알 수 있다. 출력된 라이브러리들은 심볼릭 링크일수 있다.
최근 버전의 ldd 는 정확히 어떤 로더가 필요한지를 가르쳐 주지만 옛날 버전은 그렇지 않다.
/lib 에는 라이브러리용의 로더를 포함시켜야 한다.
/lib/ld.so (a.out 라이브러리용)이나 /lib/ld-linux.so (ELF 라이브러리용)일 것이다.
# file /lib/libc.so.4.7.2 /lib/libc.so.5.4.33 /lib/libc-2.1.1.so
/lib/libc.so.4.7.2: Linux/i386 demand-paged executable (QMAGIC), stripped
/lib/libc.so.5.4.33: ELF 32-bit LSB shared object, Intel 80386, version 1, stripped
/lib/libc-2.1.1.so: ELF 32-bit LSB shared object, Intel 80386, version 1, not stripped
어떤 로더가 필요한지 자신이 없다면 라이브러리에 대해 file 명령을 실행하자.
QMAGIC 은 4.7.2 가 a.out 라이브러리용이고,
ELF 는 5.4.33 과 2.1.1 이 ELF 라이브 러리용임을 나타내고 있다.
만들고자 하는 루트 fs에 필요한 로더들을 골라 복사하라.
라이브러리와 로더들이 과연 바이너리에 맞는 것인지 주의깊게 체크 해야한다.
# cp /etc/ld.so.conf rootsampledir/etc
# cd rootsampledir
# chroot ./ /sbin/ldconfig ::: or # chroot /mnt /sbin/ldconfig
# ldconfig
ld.so.cache 를 리메이크 한다.
마지막으로, 필요한 모든 라이브러리들을 설치했다면 ldconfig 를 실행시켜서 루트 fs 상의
/etc/ld.so.cache 를 리메이크 해주어라. 캐쉬는 로더에게 어디서 라이브러리를 찾을지를 지시한다.
ldconfig 는 언제나 루트 fs에 대해서만 캐쉬를 리메이크 하므로 반드시 chroot 명령이 필요하다.
그외
objcopy --strip-debug /lib/libc-2.2.so $MNT/lib/libc-2.2.so
objcopy --strip-debug /lib/libutil-2.2.so $MNT/lib/libutil-2.2.so
objcopy --strip-debug /lib/ld-2.2.so $MNT/lib/ld-2.2.so
objcopy --strip-debug /lib/libtermcap.so.2.0.8 $MNT/lib/libtermcap.so.2.0.8
objcopy --strip-debug /lib/libcrypt-2.2.so $MNT/lib/libcrypt-2.2.so
objcopy --strip-debug /lib/libdl-2.2.so $MNT/lib/libdl-2.2.so
objcopy --strip-debug /lib/libnss_files-2.2.so $MNT/lib/libnss_files-2.2.so
objcopy --strip-debug /lib/libpam.so.0.72 $MNT/lib/libpam.so.0.72
objcopy --strip-debug /lib/libpam_misc.so.0.72 $MNT/lib/libpam_misc.so.0.72
objcopy --strip-debug /lib/security/pam_permit.so $MNT/lib/security/pam_permit.so
#####
##### /bin 과 /sbin ###
/bin 은 기본적인 작업에 필요한 ls, mv, cat, dd 등의 유틸리티들을 두기에 편리한 곳이다.
cpio, tar, gzip 등과 같은 백업에 필요한 유틸리티들은 포함시키지 않았다.
유틸리티들은 boot/root 디스켓의 용량을 아끼기 위해 따로 유틸리티 디스크에 넣어두자.
일단 boot/root 디스켓이 부팅이 되어 램디스크로 로딩되고나면,
유틸리티 디스켓으로 바꿔넣은 후 마운트 할수있다. (보통 /usr 에 마운트한다)
백업을 할 때에는 백업본 외에도 백업을 만드는데 사용된 백업 유틸리티들 역시 동일 버전으로 복사하라
다음 프로그램들이 포함되었는지 확인
init, getty 류의 프로그램, login, mount, rc 스크립트를 실행시킬 수 있는 쉘 프로그램
쉘을 sh 에 링크시켰는지도 확인
#####
##### 마지막 세부사항 ###
# mkdir -p /mnt/var/{log,run}
# touch /mnt/var/run/utmp
login 같은 시스템 프로그램들은 /var/run/utmp 와 /var/log/ 가 없는 경우 문제를 일으킬 수 있다.
# umount /mnt
만들어진 fs을 포장하기
# dd if=DEVICE bs=1k | gzip -v9 > rootfs.gz
일단 루트 fs을 다 만들었다면 언마운트시키고 파일로 카피한 다음 압축시켜야 합니다.
이 과정이 끝나면 rootfs.gz 라는 파일을 얻게 될텐데 바로 이것이 당신의 압축 루트 fs다.
그 크기를 확인해서 과연 한 장의 플로피 디스켓에 다 들어가는지를 체크해야만 한다
만일 다 들어가지 않는다면 되돌아가서 몇 가지 파일들을 지워야 한다.
루트 fs을 첫번째 디스켓에 담을때 (boot+root)
# dd if=rootfs.gz of=/dev/fd0 bs=1k seek=KERNEL_BLOCKS
루트 fs을 두번째 디스켓에 담을때
# dd if=rootfs.gz of=/dev/fd0 bs=1k
##############################
##############################
other
#####
##### rootdisk - 램디스크 사용하지 않음 ###
루트 fs의 제작 편에서는 시스템 부팅과 동시에 램디스크로 로드되는 압축 루트fs을 만드는 법을 설명했다.
이 방법이 많은 장점이 있어 주로 사용되지만 메모리가 부족한 일부 시스템은 설치된 램이 램디스크를
만들만한 용량도 못되는 수가 있으므로 이때는 디스켓 상에서 직접 마운트되는 루트fs을 만들어야만 한다.
이러한 fs은 다른 디바이스가 아닌 디스켓 위에 그대로 만들고 압축도 필요없기 때문에 압축 루트 fs을
만드는 것보다 쉽다. 위에서 우리가 배운 절차와는 조금 다르므로 그 개요를 적어보겠다.
이 방법을 택하면 사용할 수 있는 공간이 훨씬 적어진다는 사실을 잊지말라.
1. 루트파일들에 할당할 수 있는 공간이 얼마나 되는지 계산한다. 만일 한장짜리 boot/root 디스크를
만든다면 커널의 블록과 루트 fs의 블록을 더한 값을 디스켓 한 장의 용량에 맞추어야 한다.
2. mke2fs 를 써서 디스켓 위에 적절한 크기의 루트 fs을 만든다.
3. 앞에서 배운 대로 fs을 구성한다.
4. 다 되었으면 fs을 언마운트 시키고 디스크 파일로 만든다. 단, 압축시키지 말라.
5. 앞에서 배운대로 커널을 플로피 디스켓에 담는다. 램디스크 워드를 계산할 때는 비트 14 를 0으로 설정한다.
이는 루트 fs이 램디스크로 로드되지 않도록 하는 것이다. 앞에서 배운 대로 rdev 를 실행한다.
6. 만일 두장의 디스크 세트를 만든다면 직접 두번째 디스크 상에 루트 fs을 만들면 된다.
또한 한장짜리 boot/root 디스크를 만들면서 LILO를 사용하겠다면 한장의 디스켓에 커널, LILO 파일,
루트파일 셋이 모두 들어있는 단일한 fs을 만든 후, 마지막에 LILO 만 실행시키면 된다.
#####
##### 유틸리티 디스크 만들기 ###
유틸리티 디스켓을 만드는 것은 포맷된 디스크에 fs을 만들고 파일들을 카피하면 된다.
부트디스켓에서 이 유틸리티 디스켓를 이용하려면 부트된 후 유틸리티 디스켓을 마운트하면 된다.
이 문서의 앞부분에서 유틸리티 디스켓를 /usr 디렉토리에 마운트할 수 있다고 했다. 이 경우
바이너리들은 유틸리티 디스켓 상에 존재하면서 /bin 디렉토리 아래에 위치하게 되는 것이다.
따라서 /usr/bin 을 PATH 에 포함시켜두면 이를 액세스 할 수 있다.
실행화일에 필요한 각종 라이브러리들은 유틸리티 디스켓의 /lib 디렉토리에 두면된다.
유틸리티 디스크 제작시 명심해야할 중요한 사항
1. 시스템 부트후 마운트될수 있기 때문에 핵심적인 시스템 바이너리나 라이브러리들은 디스크에 담지마라.
2. 플로피 디스켓과 플로피 테이프 드라이브를 동시에 엑세스할 수없다. 즉, 플로피 테이프 드라이브를
가지고 있다해도 유틸리티 디스켓이 마운트 되어있는 동안에는 이 테이프 드라이브를 액세스 할수없다
3. 유틸리티 디스켓에 있는 파일을 엑세스하는 속도는 상당히 느리다.
부록 유틸리티 디스크 견본은 유틸리티 디스크에 들어가는 파일들의 예를 보여준다.
도움되는 아이디어를 발견할 수 있을 것이다
디스크를 다루는 프로그램들(format, fdisk)과 fs용 프로그램들(tt/mke2fs, fsck, debugfs, isofs.o/),
간단한 텍스트 에디터 (elvis,jove), 압축및 아카이브 유틸리티(gzip, tar, cpio, afio),
테이프 유틸리티(mt,tob,taper), 통신 유틸리티(ppp.o, slip.o, minicom),
디바이스용 유틸리티(setserial, mknod) 등이 들어있다.
##############################
##############################
boot disk 만드는 여러 방법
#####
##### 라이브러리없이 static으로 구성 - grub 와 패포판 이미지 이용 ###
디렉토리구조는 데스크탑 리눅스의 축소판으로 구성하며 기본 리눅스 명령어는 busybox를 사용한다.
그리고 /dev 밑의 여러가지 노드는 커널의 Devfs로 간단히 해결하도록 하겠으며
부트 로더 GRUB도 포함하여 구성하도록 하겠다.
### boot image make ###
boot.img 다운받기
ftp://ftp.mizi.com/pub/mizios/2.0/i586/1st/images/boot.img
boot.img, bootnet.img, pcmcia.img 파일은 부트 이미지 파일인데 여기서는 특별히
한글화에 관련된 작업을 하지 않는다.
*** 루프백(loopback)으로 마운트 하기
여기서 우리가 필요한 파일 menu.lst, stage1, stage2를 제외하고 모두 삭제하도록 한다.
# mount -o loop boot.img /mnt/boot_image
# ls -l
루프백으로 마운트한후 파일 리스트를 보면 다음과 같다.
-rw-r--r-- 1 root root 710804 12월 17 17:46 initrd.img
-rw-r--r-- 1 root root 406 8월 29 2001 menu.lst
-rw-r--r-- 1 root root 974 8월 29 2001 menu.lst.all
-rw-r--r-- 1 root root 14505 8월 3 2001 mizios.msg.gz
-rw-r--r-- 1 root root 512 8월 3 2001 stage1
-rw-r--r-- 1 root root 132736 8월 3 2001 stage2
-rw-r--r-- 1 root root 570980 11월 1 2001 vmlinuz
initrd.img 압축된 ext2 fs 이미지 파일인데 압축을 풀고 루프백으로 마운트하여 내용을 수정한다.
# gzip -dc initrd.img > /tmp/initrd.ext2
# mount /tmp/inird.ext2 /mnt/iso3 -o loop
menu.lst GRUB 부트 로더의 config 파일로 커널이미지의 위치, root 디바이스의 위치 및
커널 파라메터 값을 셋팅할 수 있다. (LILO로 치자면 lilo.conf 에 해당한다.)
stage1 GRUB에 있어 필수적인 파일이며 부트 섹터나 MBR에 꼭 들어가야 하는 파일이다.
PC의 부트 섹터가 512Byte 인것처럼 stage1 역시 512Byte의 사이즈를 가진다.
stage2 GRUB 이미지 파일. (http://www.gnu.org/software/grub/ 참고)
*** 커널 이미지 만들기
[*] /dev file system support (EXPRIMENTAL)
<M> Loopback device support
menu.lst 수정하기
# vi menu.lst
timeout 10
color
default
title floppy-boot
root (fd0)
append = "devfs=mount" # 부팅시 devfs 사용을 위해
kernel /vmlinuz root=/dev/fd0 vga=0x307
# umount /tmp/boot_image
# dd if=boot.img of=/dev/fd0
부트 로더 GRUB으로 부팅 가능한 플로피 디스크 이미지를 만들때 stage1, stage2를 그냥
플로피 디스크에 카피한다고 하여 부팅 가능한 디스크가 되는것은 아니다.
부트 섹터 즉 최초 512Byte에 stage1 이 들어가야하고 그 뒤쪽 영역에 stage2가 들어가야지만
부팅 가능한 이미지가 된다.
이렇게 하여 첫번째 플로피 디스크의 구성은 끝이 났다. 이 디스켓으로 부팅한다면 부트 로더가 뜨고
카피한 커널 이미지가 로딩되어 부팅되기는 하겠으나 루트 fs이 없으므로 에러가 날것이다.
### root image make ###
Busybox
busybox를 카피한후 Config.h에서 정의해준 여러 명령어를 busybox에 심벌릭 링크 해준다.
(이렇게 링크된 명령어는 마치 busybox의 인자값처럼 동작하게 된다.)
busybox는 busybox란 바이너리 파일 하나로 구성되어 있지만 리눅스의 여러가지 utility를
포함하고 있으며 또한 사이즈가 아주 적어 루트 fs을 구성할때 많이 사용한다.
우선 루트 fs의 뿌리가 되는 busybox를 만들어 보자. (http://busybox.lineo.com을 참고)
# wget http://www.busybox.net/downloads/busybox-0.60.3.tar.gz
# vi Config.h
/* vi: set sw=4 ts=4: */
//#define BB_AR
#define BB_ASH
#define BB_BASENAME
#define BB_CAT
...
Config.h는 busybox가 포함할 여러 utility를 설정해주는 설정 파일로 각 명령어가
#define 되어있는데 필요한 명령어의 주석을 제거해주면 그 명령어를 사용할 수 있다.
자신만의 busybox를 만들어도 상관없지만
shell인 BB_ASH 관련 설정과 init인 BB_INIT와 mount등 필수적인 기본 명령어는 꼭 포함하자
# vi Makefile
PROG := busybox
VERSION := 0.60.3
BUILDTIME := $(shell TZ=UTC date -u "+%Y.%m.%d-%H:%M%z")
# If you want a static binary, turn this on.
#DOSTATIC = # 주석처리
DOSTATIC = true # 이 부분을 수정
컴파일은 간단하게 make라는 명령으로 끝나지만 우리는 라이브러리를 사용하지 않으므로
static으로 컴파일해야한다.
그러기 위해 Makefile을 'DOSTATIC = true'로 수정한후 make 명령으로 컴파일 하자.
-lnss_dns이나 -lnss_files 관련 에러로 컴파일이 되지 않는다면 다음 두 부분을 수정하고 컴파일 하라.
#LIBRARIES = -lc -lresolv -lnss_dns -lnss_files # 주석처리
LIBRARIES = -lc -lresolv # 이 부분을 수정
# dd if=/dev/zero of=root.img bs=1024 count=1440
플로피 디스크 1장 사이즈로 root.img란 제로 파일을 만든다.
# mke2fs -F root.img
root.img를 강제로 ext2 fs으로 만들자. 그렇지 않으면 fs이 없으므로 마운트 할 수가 없다.
# mount -o loop root.img /tmp/root_image
boot.img과 같은 방법으로 /tmp/root_image란 디렉토리를 만들고 루프백으로 마운트 한다.
아래와 같은 디렉토리를 만든다.
이 중에서 /dev, /proc, /tmp는 어떤 파일도 포함하지 않는 단지 이름뿐인 디렉토리이다.
bin/ dev/ etc/ proc/ sbin/ tmp/
/bin의 세부적인 파일은 다음과 같다.
'['를 test에 링크걸고 test을 busybox에 링크건 까닭은
shell 스크립트등에서 "if [ -e" 같은 구문을 사용하기 위해서이다.
# ls /bin
[ -> test*
basename -> busybox*
cat -> busybox*
chgrp -> busybox*
chmod -> busybox*
chown -> busybox*
clear -> busybox*
...
cp cut date dd df dmesg du echo env expr
false free grep gunzip gzip head hostname init
ln ls mkdir mknod more mount mv ping ps pwd
rm rmdir sed sh sleep sync tail telnet test true
umount uname uptime usleep vi
# ls /sbin
lrwxrwxrwx 1 root root 12 6월 15 18:30 halt -> /bin/busybox
lrwxrwxrwx 1 root root 12 6월 15 18:30 init -> /bin/busybox
lrwxrwxrwx 1 root root 12 6월 15 18:30 reboot -> /bin/busybox
# ls /etc
-rw-r--r-- 1 root root 137 6월 11 20:00 fstab
drwxr-xr-x 2 root root 1024 6월 15 17:13 init.d/
-rw-r--r-- 1 root root 0 5월 2 2001 mtab
# vi fstab
none /proc proc defaults 0 0
none /dev/pts devpts mode=0622 0 0
tmpfs /dev/shm tmpfs defaults 0 0
/dev/floppy/0 / ext2 defaults 1 1
# touch /etc/mtab
# vi /etc/init.d/rcS
#!/bin/sh
/bin/mount -a
#exec /etc/rc.local
busybox의 init 은 /etc/init/rcS를 디폴트 sysinit 스크립트로 사용한다.
# chmod 755 rcS
busybox의 init에서 이 rcS을 실행하기 때문에 꼭 실행권한이 있어야 한다.
# ./busybox
Usage: busybox [function] [arguments]...
Currently defined functions:
[, ash, basename, busybox, cat, chgrp, chmod, chown, clear, cp, date, df, dmesg,
du, echo, env, expr, false, free, grep, gunzip, gzip, halt, head, hostname, init, kill,
...
busybox를 그냥 실행해보면 Config.h에서 지정한 명령어를 확인 할 수 있다.
# ./busybox ls
busybox의 특정 명령어는 위와 같이도 실행 할 수도 있다.
# umount /tmp/root_image
#####
##### dd 유틸리티 이용해서 만들기 ###
dd 명령을 사용해서 부팅 디스켓을 만들때는 lilo 가 포함된 부팅 디스크와는 달리 리눅스가 설치되어있는
루트 파티션에 대한 정보가 올바른 형태로 저장되어 있어야 한다
rdev [장치화일명] 을 입력하면 현재 설정되어 있는 루트 파티션을 확인해 볼수 있는데 현재의 루트파티션이
lilo 가 설치되어있는 mbr 영역을 의미하는 /dev/hda1 이고 실제 리눅스 커널이 설치되어 있는 파티션이
/dev/hdb1이라면 rdev /dev/fd0 /dev/hdb1 을 실행해 루트파티션에대한 정보를 변경시켜야 한다
# dd if=/boot/vmlinuz-2.0.36-1kr of=/dev/fd0
단순히 커널 이미지만 디스켓으로 복사되기 때문에 lilo가 포함되지 않으며
컴퓨터로 부팅함과 동시에 lilo를 건너뛰고 바로 리눅스로 부팅 된다
# dd if=/cdrom/disks/rescue.img of=/dev/fd0 bs=72k
구조용 플로피 디스크를 생성. boot.img 를 이용한 부트 디스크로 부팅한후 rescue.img 로
복구용 디스크를 만든후 먼저 부팅 디스크로 부팅하고 boot: 프롬프트에서 rescue 를 입력한다
이어서 두번째 disk를 넣으라는 메시지가 나오면 삽입한다
# dd if=/mnt/cdrom/images/boot.img of=/dev/fd0 bs=72k
부팅용 디스크 작성
# dd if=/mnt/cdrom/images/supp.img of=/dev/fd0 bs=72k
설치용 디스크 작성
#####
##### rawrite 이용해서 만들기 ###
도스에서(리눅스 CD에 포함된) 디스크 생성방법
usage :
rawrate -f '이미지위치' -d '저장할 드라이브'
-f <path> 저장할 이미지의 위치
-d<drive> 저장할 드라이브 위치 A 또는 B 드라이브
-n 사용자가 디스크를 드라이브에 삽입을 기다리지 않고 실행
-h help
C:\> rawrite -f "L:\images\boot.img" -d "a:"
여러가지 이미지중 boot.img라는 부팅용 이미지 파일을 디스크로 옮긴다
C:\> rawrite
-f,-d 옵션을 이용해서 옮겨도 되고,
옵션없이 명령어를 입력한다음 순차적으로 요구하는것을 입력해도된다
Enter source file name: ..\images\supp.img ::: 설치용 디스크 작성
Enter destionation drive: a: ::: a 드라이브 선택
Please insert a formatted diskette into drive a: and press
-Enter-:
같은 방법으로 루트 디스크를 만든다
#####
##### Tomsrtbt 부트 디스크 만들기 ###
http://www.toms.net/~toehser/rb/
tomsrtbt 는 커널 2.0 기반의 한장짜리 boot/root 디스크다.
IDE, SCSI, 테이프, 네트웍 어댑터, PCMCIA 기타 여러가지를 지원한다.
디스크 복구 및 수리에 관련된 약 100 개 이상의 유틸리티와 툴이 포함되어 있다.
이미지를 풀어 재구축 할수있는 스크립트가 포함되어 있으므로 필요하면 새로운 것을 첨가할 수 있다.
John Comyns 씨가 제작한 rescue02 는 커널 1.3.84 기반의 복구 디스크이다. IDE, 아답텍 1542, NCR53C7,
8xx 를 지원한다. ELF 바이너리를 사용하지만 충분한 명령어들을 가지고 있으므로 어떤 시스템에도
사용할 수 있다. 부팅 후에는 그밖의 SCSI 카드들에 대한 모듈도 로드할수 있다. 이 디스크는 3 메가의
램디스크를 사용하므로 4 mb 의 램을 가진 시스템에서는 쓸수 없다.
Sergei Viznyuk 씨가 제작한 resque_disk-2.0.22 는 본격적인 boot/root 디스크로서 커널 2.0.22 를
기반으로 한다. IDE, 다양한 SCSI 컨트롤러들, ELF/A.OUT 에 대한 지원을 커널에 내장하고 있다. 또한
많은 모듈들과 하드디스크의 수리와 복구에 유용한 많은 유틸리티들을 가지고 있다.
커널 2.0.23 에 기반한 cramdisk 이미지들은 4 MB 나 8 MB 머신에서 사용가능하다. math emulation,
네트워킹(PPP 와 다이얼링 스크립트, NE2000, 3C509), 병렬포트 ZIP 드라이브 등에 대한 지원을 포함하고
이 디스켓 이미지들은 4 MB 이상의 램을 가진 386 에서 사용가능하다.
MSDOS 지원이 포함 되어 있으므로 도스파티션으로 다운받을 수 있다.
http://metalab.unc.edu/pub/Linux/system/recovery/images
#####
##### mkbootdisk 스크립트 ###
usage : mkbootdisk --device /dev/fd0 --verbose [커널버전]
- mkbootdisk는 부트 이미지를 만들어주는 스크립트이다 이것은 쉘스크립트 화일인데 명령 실행시
의존성 에러가 생기면 해당 패키지를 설치해야 한다
- /lib/modules 디렉토리에 [커널번호] 에 해당하는 커널 모듈 디렉토리가 있어야 이미지가 만들어진다
# cd /boot
# ln /boot/bzImage-2.4.4 /boot/vmlinuz-2.4.4
bzImage(예, bzImage-2.4.4)로서 커널을 컴파일 한다면, vmlinuz-2.4.4에 대한 하드 링크(hard link)를
생성하여야만 한다 (vmlinuz 명칭에서 z를 주의하라. vmlinux가 아니다)
이것을 제대로 하지 못하면, mkbootdisk 명령은 실패할 것이다
# ls -d /lib/modules/2.0.*
/lib/modules/2.0.36-1kr
# mkbootdisk --device /dev/fd0 2.0.36-1kr
실제 모듈 버젼이 2.0.36 이라해도 /lib/modules 에있는 정확한 이름인 2.l.36-kr 을 사용해야한다
#####
##### boot cd 제작 ###
점검사항
mkbootdisk ::: 부트 이미지를 만들어주는 스크립트
mkisofs
루트 권한으로
# mkbootdisk --device ./linux-bootcd.img 2.4.2-xx
linux-bootcd.img 는 부트 이미지를 저장할 화일 이름이다.
플로피에 직접 쓰는 경우 화일 이름 대신 디바이스 화일 이름을 사용한다.
# mkdir temp
# cd temp
# cp some_path/linux-bootcd.img ./
만들어질 시디의 최상위 디렉토리와 같은 의미가 되는 임시 디렉토리를 만들고 linux-bootcd.img 화일을
복사해 넣어둔다. 그 외에 자기가 복사해두고 싶은 파일들을 잔뜩 복사한다
# mkisofs -r -b linux-bootcd.img -c boot.catalog -o bootcd.iso .
iso 이미지 화일을 만든다 반드시 temp 디렉토리에서 위처럼 한다
-b 부트 이미지의 이름
-c 부트 카달로그 파일 이름 (규약상 필요한 것이고 무조건 이렇게 해야 부팅 시디가 만들어진다
boot.catalog 라는 파일을 손으로 만들 필요는 없다)
-o 만들어질 iso 이미지 파일 이름
-r 화일 퍼미션, 소유권등을 적절히 바꾸라는 옵션.
마지막에 "."을 빠뜨리면 안되고, 파일패스는 만들어질 시디롬의 루트 디렉토리를 기준으로 써야한다
만들어진 이미지를 각자 좋아하는 프로그램으로 시디를 굽는다
##############################
##############################
etc
*** 복구 패키지들
배포본 부트 디스크 외에도 다음의 복구 디스크 이미지들을 쓸 수도 있다.
metalab.unc.edu 에 복구디스크를 만드는 패키지가 있다. 이 패키지들을 쓸 경우, 포함 시키고자 하는
파일들을 지정해 주기만 하면 소프트웨어가 어느정도 자동적으로 부트 디스크를 만든다.
(http://metalab.unc.edu/pub/Linux/system/ 참고) recovery/!INDEX.html 파일의 날짜를 체크하라.
패키지들 중 몇몇은 지난 수년간 갱신되지 않았기 때문에 램디스크로 로딩되는 압축 루트 fs 제작을
지원하지 않는다. (현재까지 Yard 패키지만이 지원한다.)
*** 리눅스 부트 프로세스
리눅스 부트 프로세스에 관한 보다 자세한 사항은 다음을 참고
- "리눅스 시스템 관리자 가이드" 에 부팅에 관한 절이 있다. (http://linuxdoc.org/LDP/sag/c1596.html)
- LILO "Technical overview" http://metalab.unc.edu/pub/Linux/system/boot/lilo/lilo-t-21.ps.gz
에는 부트 프로세스에서부터 커널이 시작되는 단계까지에 관한 기술적인 사항 및 저수준 에서의
동작에 관한 중요한 설명이 있다.
소스코드야 말로 궁극적인 안내서다. 아래의 파일들은 부트프로세스와 관련된 몇가지 커널 파일이다.
리눅스 커널 소스 코드를 가지고 있면 /usr/src/linux 아래에 있을 것이다.
다른 방법으로는, Shigio Yamaguchi (shigio@tamacom.com) 씨가 다음 홈페이지에서 아주 훌륭한
하이퍼텍스트 커널 브라우저를 제공하고 있다. http://www.tamacom.com/tour/linux/index.html
다음은 관련 파일들이다.
arch/i386/boot/bootsect.S,setup.S
부트섹터에 해당되는 어셈블리 코드가 있다.
arch/i386/boot/compressed/misc.c
커널의 압축을 해제하는 코드가 있다.
arch/i386/kernel/
커널을 초기화시키는 코드가 이 디렉토리에 들어있다. setup.c 에 램디스크 워드가 있다.
drivers/block/rd.c
램디스크 드라이버가 있다. rd_load 와 rd_load_image 프로시저가 디바이스에서
램디스크로 데이터 블록들을 로드한다. identify_ramdisk_image 프로시저는 어떤 종류의
fs이 발견되었는지, 또 그것이 압축된 상태인지 아닌지를 판별한다.
#####
##### 애로사항과 문제해결 ###
부트 디스크를 만들 때 단번에 성공하는 일을 거의 없다. 루트디스크를 만드는 일반적인 접근방법은
현재 시스템 으로부터 필요한 요소들을 끌어모아 조립한 디스켓 기반의 시스템을 가지고 시행착오를 거쳐
콘솔 상에 어떤 메시지가 나타나는 단계에까지 진입하는 것이다.
이 단계까지오면 출력된 메시지를 보고 무엇이 문제인지를 파악해 나갈 수 있으므로 시스템이 원활히
동작할 때까지 각각의 개별적 문제들을 해결해 나가기만 하면 된다.
시스템이 아무런 메시지 없이 그냥 멈추어 버린 경우라면 그 원인을 찾는 것은 어려운 일이다.
시스템이 부트되어 어떤 메시지를 보낼수 있는 단계까지 왔다는 말은 몇 가지 구성요소들은 동작하고 있으며
거기까지는 제대로 설정이 되었다는 말이된다.
만일 시스템이 아무런 메시지를 남기지 않고 멈추어 버렸다면 아래의 순서대로 원인을 조사하자
### 다음과 같은 메시지가 나온 경우 ###
Kernel panic: VFS: Unable to mount root fs on XX:YY
이는 흔히 발생하는 문제이며 이유는 몇가지 밖에 없다.
디바이스 XX:YY 가 디바이스 코드의 리스트에 있는지 체크하자. 그것이 올바른 루트 디바이스인가?
아니라면 원인은 틀림없이 rdev -R 을 실행하지 않았거나 잘못된 이미지에 대해 rdev 명령을 내린 것이다.
디바이스 코드가 올바르다면 커널내에 컴파일 되어있는 디바이스 드라이버들을 주의깊게 체크하라
- 루트 fs의 /lib/libc.so 의 링크가 하드디스크의 /lib 디렉토리에 있는 링크와 같은지 확인.
- 루트디스크에 정말로 당신이 생각했던 디렉토리들이 포함되어 있는지 확인.
루트디스켓 fs의 /dev 디렉토리의 심볼릭 링크가 당신 시스템의 그것과 동일한지 확인.
- /dev/tty1, /dev/null, /dev/zero, /dev/mem, /dev/ram, /dev/kmem 이 포함되었는지 확인.
특히 /dev/console 링크는 대부분의 경우 반드시 있어야 한다.
- 커널 설정을 확인. 로그인 단계에 다다를 때까지 필요한 자원에 대한 지원은 커널에 내장 되어야 한다.
따라서 램디스크와 ext2 에 대한 지원은 반드시 커널에 내장되어야 한다.
커널 루트 디바이스와 램디스크 설정이 올바른지 확인.
일단 위의 일반적인 사항들을 확인했다면 이제 보다 구체적인 파일들을 확인한다.
1. init 가 /sbin/init 혹은 /bin/init 로 제대로 포함되어 실행가능한 상태인지 확인.
2. ldd init 해서 init 의 라이브러리들을 체크. 보통 이것은 libc.so 가 되지만 다시 확인.
필요한 라이브러리와 로더들을 포함시켰는지 확인.
3. 각 라이브러리들에 대해 그에 해당하는 알맞은 로더를 가지고 있는지를 확인.
a.out 에는 ld.so 가 있어야 하고 ELF 에는 ld-linux.so 가 있어야 한다.
4.- 부트 디스크 fs에 있는 /etc/inittab 파일을 열어 getty를 호출하는 부분을 체크.
(혹은 agetty, mgetty, getty_ps 등의 이른바 getty 류 프로그램)
이 부분을 하드 디스크의 inittab 과 비교하면서 되풀이 하여 확인.
- 당신이 사용하는 프로그램의 맨 페이지를 펼쳐놓고 과연 제대로 설정되었는지 확인
- /etc/inittab 가 시스템 초기화 엔트리를 가지고 있는지 확인
이 파일에는 시스템 초기화 스크립트들을 수행시키는 명령어가 반드시 포함되어 있어야 한다.
- inittab 는 리눅스 시스템에서 가장 교묘한 부분이다. 그 이유는 init 의 문법과 내용은 사용되는
init 프로그램에 따라 서로 다르고, 또 각 시스템의 특성에 의존적이기 때문이다.
init 에 관한 문제를 다루는 유일한 방법은 init 와 inittab 에 대한 맨 페이지를 숙지한 후,
시스템이 부트될때 일어나는 과정들이 플로피 디스크 상에서도 똑같이 일어나도록 하는 것이다.
5. init 에 했던 것처럼 getty 에 대해서도 ldd 를 실행시켜서 getty 가 무엇을 필요로 하는지 확인하고
필요한 라이브러리와 로더들이 루트 fs에 들어있는지 확인.
6. rc 스크립트를 실행시키는 쉘 프로그램 (bash, ash 등)을 포함시켰는지 확인
7. 만일 복구디스켓에 /etc/ld.so.cache 파일을 포함시켰다면 그것을 리메이크한다.
### init 가 시작되기는 하는데 다음과 같은 메시지를 내는 경우 ###
Id xxx respawning too fast: disabled for 5 minutes
이것은 init 가 발생시킨 메시지로서 주로 getty 나 login 이 시작하자마자 죽어버렸음을 알리는 것이다.
getty와 login 이 의존하는 실행파일들과 라이브러리들을 확인하라.
/etc/inittab 내의 호출형식이 정확한지 확인.
만일 getty 로부터 이상한 메시지를 받았다면 /etc/inittab 내의 호출형식이 어딘가 틀렸을 것이다.
getty 프로그램들의 옵션은 다양하다. 버전별로 호출형식이 상이한 경우도 있다.
만일 로그인 프롬프트가 떴고 제대로 사용자 이름을 넣었는데도 시스템 프롬프트가 즉각 또다른 로그인
네임을 요구한다면, 아마도 PAM 이나 NSS 에 관련된 것이다. (PAM 과 NSS에 대한 대책절을 참고)
shadow password 를 사용하면서 /etc/shadow 를 부트 디스크로 복사해 넣지 않았기 때문일 수도있다.
### 복구 디스켓에 있는 df 등의 일부 실행파일을 실행했을때 다음과 비슷한 메시지를 받는 경우 ###
df: not found
- 그 바이너리가 위치한 디렉토리가 PATH 에 잡혀있는지 확인
- 그 프로그램이 필요로 하는 라이브러리와 로더를 포함시켰는지.
#####
##### 전문가들이 사용하는 방법 ###
슬랙웨어, 레드햇, 데비안 등의 주요한 배포본들에 사용되는 부트 디스크도 한번쯤 생각해 볼수 있다.
이런 것들은 이 문서에서 설명한 것보다 복잡하게 구성되어 있다.
전문적인 배포본의 부트 디스크들 역시 대체로 여기에서 설명한 원리에 기초하고 있지만,
그 외에도 그런 부트 디스크들은 다음의 기능들을 구비하기 위해 보다 다양한 기교를 사용한다.
첫째, 폭넓은 종류의 하드웨어를 지원해야 한다. 따라서 사용자의 입력을 받을수 있어야 하고
다양한 디바이스 드라이버들을 로드할수 있어야 한다.
둘째, 여러가지 많은 설치 옵션을 입력받아 각각을 자동적으로 처리할 수 있어야 한다.
셋째, 배포본의 부트 디스크들은 대개의 경우 설치기능과 응급조치의 기능을 함께 가지고 있다.
슬랙웨어(v.3.1)는 "디스켓에 LILO 와 커널을 함께 담기 부분" 에서 설명한 부트방식을 그대로 사용한다.
슬랙웨어의 부트 디스크는 LILO 의 메시지 파라메터를 이용하여 부트업 메시지
("Welcome tothe Slackware Linux bootkernel disk!")를 화면에 출력한다.
이 메시지는 사용자로 하여금 필요한 경우 부트 파라메터 라인을 입력토록 지시한다.
부팅 후 루트 fs은 두번째 디스크에서 로드된다.
이제 사용자는 초기화과정을 처리하는 셋업 스크립트를 가동시키게 됩니다.
모듈화된 커널을 쓰는 대신 슬랙웨어는 각각의 커널을 다양하게 준비해 두고
그 중에서 사용자가 자신의 하드웨어 사양에 맞는 것 하나를 골라쓰는 방법을 택하고 있다.
레드햇(v.4.0) 역시 LILO 부트를 이용한다.
레드햇은 압축된 루트디스크를 첫번째 디스크에 가지고 있으며 이것은 레드햇 특유의 init 프로그램을 기동시킨다.
이 프로그램은 드라이버를 물어본 후 필요한 경우 보충 디스크에서 추가적인 파일들을 로드하게 된다.
데비안(V.1.3) 은 설치디스크들 중에서 가장 복잡한 방법을 쓰고 있다.
이것은 SYSLINUX 로더를 써서 다양한 로드 옵션을 제공한 다음,
initrd 이미지를 사용해서 설치 과정동안 사용자를 안내한다.
데비안은 데비안 특유의 init 와 쉘을 사용하는 듯하다.
##############################
##############################
자주 받는 질문들 (FAQ : Frequently Asked Question)
Q. XYZ 드라이버를 포함한 부트 디스크를 만들려면?
가장 쉬운 방법은 가까운 슬랙웨어 미러 사이트에서 슬랙웨어 커널을 받는 것이다.
슬랙웨어 커널들은 가능한 한 많은 디바이스 드라이버들을 포함하는 포괄적인 커널들이므로 만일 SCSI 나
IDE 컨트롤러를 가지고 있다면 해당 드라이버가 슬랙웨어 커널에 있을 가능성이 높다.
a1 디렉토리에 가서 당신의 컨트롤러 타입에 맞는 IDE 나 SCSI 커널을 선택하라. 선택하신 커널에 대한
xxxxkern.cfg 파일을 보면 해당 드라이버가 그 커널에 들어있는지 확인할 수 있다. 원하는 디바이스가
리스트 안에 있다면, 그 커널은 당신 컴퓨터를 부팅시킬 수다. xxxxkern.tgz 파일을 다운받은 후
본 문서의 부트 디스크 제작에 관한 부분에 적힌 방법대로 부트 디스크로 복사하라
그 다음, rdev 명령을 써서 커널의 루트 디바이스를 체크해야 한다.
# rdev zImage
rdev 명령은 커널 내에 지정된 현재의 루트 디바이스가 무엇인지 출력한다.
만일 당신이 원하는 루트디바이스가 아니라면, rdev 명령을 써서 루트 디바이스를 바꿔주어야 한다.
예를 들어 지금 다운받은 커널에는 /dev/sda2 가 루트 디바이스로 지정되어 있는데 정작
자신의 루트 디바이스는 /dev/sda8 이라는 SCSI 파티션이라고 하자.
루트디스켓을 사용하기 위해서는 다음 명령을 써야한다.
# rdev zImage /dev/fd0
Q. 부트디스켓의 커널을 새로운 커널로 갱신하려면 어떻게 해야 하나요?
fs이 없는 부트디스켓의 경우는 dd 명령어를 써서 단순히 부트디스켓에 커널을 복사하면 된다.
boot/root 디스크인 경우 cp 명령어를 사용한다.
Q. 루트디스켓의 파일들을 새로운 파일들로 갱신하려면 어떻게 해야 하나요?
가장 쉬운 방법은 루트디스크의 fs을 당신이 사용했던 DEVICE (fs의 제작에서 나왔다)에 역으로 복사한후,
그 fs을 마운트해서 필요한 부분을 갱신한다. 당신의 루트 fs이 어디서부터 시작했고 얼마만큼의 블록을
차지했는지를 반드시 기억해두어야 한다.
# dd if=/dev/fd0 bs=1k skip=ROOTBEGIN count=BLOCKS | gunzip > DEVICE
# mount -t ext2 DEVICE /mnt
갱신한 다음에는 만들어진 fs을 포장하기 부분에서 한것처럼 작업한 후, 루트 fs을 다시 디스크로 옮긴다.
이때, 새로운 루트 fs의 시작위치를 바꾸지 않았다면
커널을 다시 넣는다거나 램디스크 워드를 재계산해줄 필요는 없다.
Q. 커널과 부트 디스크를 모두 잃어버렸는데 부팅시킬 방법이 있을까요?
준비해놓은 부트 디스크가 없다면, 가장 쉬운 방법은 당신의 디스크 컨트롤러 타입(IDE 혹은 SCSI)에 맞는
슬랙웨어 커널을 구하는 것이다. 위의 "XYZ 드라이버를 포함한 부트 디스크를 만들려면?" 답변에서 설명했다.
그렇게 구한 커널을 써서 컴퓨터를 부트시킨 후 손상된 부분을 고치시기 바랍니다.
구한 커널의 루트 디바이스 세팅이 원하시는 디스크 타입과 파티션으로 설정되어있지 않았을 수 있다.
슬랙웨어에서는 일반적으로 커널의 SCSI 루트 디바이스가 /dev/sda2 로 잡혀있는데 필자의 리눅스의
루트파티션은 /dev/sda8 로 되어있다면, 이 경우 커널내의 루트 디바이스 설정을 수정해야 한다.
심지어는 당신이 가진 것이 달랑 커널 하나와 DOS 나 그 외 다른 운영체제뿐이라고 하더라도 그걸로도
커널내의 루트 디바이스와 램디스크 설정을 바꿀수 있다.
rdev 명령은 커널파일내에 고정되어있는 오프셋의 값을 바꿔줌으로써 커널의 세팅을 바꾸는 것이다.
따라서 현재 어떤 시스템을 갖고 있든지 간에 hex 에디터만 있다면 rdev 와 똑같은 일을 해낼 수 있다.
한 예로 DOS 의 노턴 유틸리티 디스크에디터를 사용할 수도 있다.
에디터를 써서 커널내의 다음 값들을 체크하고 필요하다면 이를 수정하면된다.
HEX DEC DESCRIPTION
0x01F8 504 Low byte of RAMDISK word
0x01F9 505 High byte of RAMDISK word
0x01FC 508 Root minor device number - see below
0X01FD 509 Root major device number - see below
램디스크 워드의 해석은 램디스크 워드의 설정 부분에 나와 있다.
메이저, 마이너 디바이스 넘버들은 루트 fs이 마운트되는 디바이스로 설정되어야 한다.
쓸만한 값들은 다음과 같다.
DEVICE MAJOR MINOR
/dev/fd0 2 0 1st floppy drive
/dev/hda1 3 1 partition 1 on 1st IDE drive
/dev/sda1 8 1 partition 1 on 1st SCSI drive
/dev/sda8 8 8 partition 8 on 1st SCSI drive
일단 이 값들을 설정했다면 이제 노턴 유틸리티 디스크 에디터나 rawrite.exe 같은 프로그램을 써서
파일을 디스켓 상에 써넣어야 한다. 이것은 도스 프로그램으로서 어떤 파일을 fs 내에 쓰는 것이 아니라
부트섹터부터 그대로(raw 하게) 디스크로 써넣어 버리는 프로그램이다.
노턴 유틸리티를 사용하신다면 파일을 물리적인 디스크의 첫부분에 서부터 그대로 써넣어야 한다.
Q. boot/root 디스켓의 복사본을 만들려면?
자성 매체는 시간이 지남에 따라 그 자기적 특성이 저하되기 때문에,
원본을 읽을 수 없게 될 경우에 대비해 복구용 디스켓을 여벌로 가지고 있는 것이 좋다.
디스켓의 복사본을 만드는 가장 손쉬운 방법은 dd 명령으로 원본디스켓의 내용을 하드디스크의
파일로 복사해 온 후, 같은 명령으로 그 파일을 새로운 디스켓에 복사해 넣는 것이다.
dd 명령은 raw device 인터페이스를 사용하기 때문에 디스켓을 마운트해서도 안된다.
원본을 복사하기 위해서는 다음과 같은 명령을 사용한다.
# dd if=DEVICENAME of=FILENAME
DEVICENAME 은 디스켓 드라이브의 디바이스 이름, FILENAME 은 생성되는 파일의 이름이다.
dd 명령에서 count 파라메터를 생략하면 디스크 전체(고밀도 = 2880 블록)를 복사하게 된다.
# dd if=FILENAME of=DEVICENAME
얻어낸 파일을 새로운 디스켓으로 복사하려면 새 디스켓을 넣고 명령을 반대로 내린다.
Q. 매번 부트할 때마다 "ahaxxxx=nn,nn,nn" 식으로 입력하지 않고 부트할 수는 없나요?
디스크 디바이스가 자동으로 감지되지 않는다면 커널에 디바이스 파라메터 문자열을 써 주어야 한다.
aha152x=0x340,11,3,1
LILO 사용시 이 파라메터 문자열을 전달하는 몇 가지 방법이 있다.
- 시스템이 LILO 를 통해 부트될 때마다 명령어 라인에 문자열을 써주는 방법.
- LILO 의 "lock" 키워드를 써서 원하는 명령어 라인을 디폴트로 저장시키는 방법.
이렇게 하면 LILO 는 부트 할 때마다 매번 이 옵션을 사용하게 된다.
- LILO 설정파일내에 append= 구문을 쓰는 방법. (파라메터 문자열은 반드시 인용부호로 감싸야 한다)
zImage aha152x=0x340,11,3,1 root=/dev/sda1 lock
파라메터 문자열을 사용한 명령어 라인 예
디바이스 파라메터 문자열을 넘겨주면서 동시에 커널로 하여금 루트 디바이스를 /dev/sda1 로
설정케 한 후, 명령어 라인 전체를 저장시켜 차후로 부트할 때마다 이를 사용한다.
APPEND = "aha152x=0x340,11,3,1"
APPEND 구문의 예.
파라메터 문자열은 명령어 라인에서는 절대로 인용부호를 써서는 안되며, 반대로 APPEND
구문에서는 반드시 인용부호를 같이 써야한다.
또, 파라메터 문자열대로 제대로 동작하게 하려면 커널은 반드시 그 디스크 타입에 해당하는
드라이버를 가지고 있어야한다. 만일 해당 드라이버를 가지고 있지 않다면 그 파라메터 문자열은
아무런 작용을 못하는 존재가 되므로 이럴때는 필요한 드라이버를 포함하는 커널을 다시 만들어
설치하거나 아니면 그 디스크 타입에 맞는 일반적인 커널을 구해 설치해도 된다.
lilo 의 BOOT 구문을 부주의하게 사용하면 파티션이 손상될 수 있다.
Q. 부트할 때 "A: cannot execute B" 라는 에러가 났습니다. 왜인가요?
어떤 프로그램의 이름이 다른 유틸리티 프로그램의 코드내에서 직점 코딩된 경우가 있다.
자주있는 것은 아니지만 이러한 경우는 실행파일이 분명히 존재하는데도 불구하고 특정 프로그램이
그 파일을 찾지 못하는가를 설명해줍니다. 특정 프로그램이 코드내에서 다른 파일의 이름을 사용하고
있는지 여부를 확인하려면 strings 명령을 쓴후 그 출력을 grep 으로 파이프 받아확인하면 된다.
이런 경우의 몇가지 예를 들어 보겠습니다.
- 어떤 리눅스 버전에서의 shutdown 프로그램은 그 코드내에 /etc/reboot 라는 이름을 사용하고 있다.
따라서 이 경우 reboot 프로그램은 반드시 /etc 디렉토리 밑에 위치해야한다.
- 커널이 init 를 찾지 못해서 문제가 되는 경우도 있다.
이런 문제들을 해결하기 위해서는, 해당 프로그램을 올바른 디렉토리에 두거나 설정파일(inittab)들을
고쳐 올바른 디렉토리를 가리키도록 해야한다. 아무래도 미심쩍다면 하드디스크의 환경과 동일한 환경을
만들어 주라 (하드디스크와 동일한 디렉토리에 두고, inittab, /etc/rc.d 도 하드와 동일한 파일을 사용)
Q. 제 커널은 램디스크를 지원합니다만 램디스크를 0K 로 초기화시켜 버립니다.
이런 일이 발생하면 부팅시에 다음과 같은 커널 메시지가 뜹니다.
Ramdisk driver initialized : 16 ramdisks of 0K size
이는 틀림없이 부트시에 커널 파라메터가 램디스크의 크기를 0 으로 세팅했기 때문이다.
아마도 LILO 설정파일의 파라메터가 ramdisk= 0 으로 설정되어있는 것을 간과했을 것이다.
일부 오래된 배포판에 포함된 LILO 설정의 샘플 파일에 이런 옵션이 들어 있는 수가 있다.
만일 0K 로 설정되어있는 램디스크를 사용하려 한다면 그 결과는 예상할 수 없다.
이는 커널 패닉으로 이어질 수도 있다. (위와 같은 라인이 있다면 삭제하라.)
##############################
##############################
루트 디스크 견본
Root directory:
bin dev etc lib mnt proc root sbin tmp usr var
/dev:
cdrom -> cdu31a cdu31a console cua0 cua1
cua2 cua3 fd0 fd0D1040 fd0D1120 fd0D360
fd0D720 fd0D800 fd0E2880 fd0E3200 fd0E3520
fd0E3840 fd0H1440 fd0H1600 fd0H1680 fd0H1722 fd0H1743
fd0H1760 fd0H1840 fd0H1920 fd0H360 -> fd0D360 fd0H720 -> fd0D720
fd0H820 fd0H830 fd0d360 fd0h1200 fd0h1440 fd0h1476 fd0h1494
fd0h1600 fd0h360 fd0h410 fd0h420 fd0h720 fd0h880
hda hda1 hda2 hda3 hda4 hda5 hda6
hdb hdb1 hdb2 hdb3 hdb4 hdb5 hdb6
kmem mem modem -> ../dev/ttyS1 mouse -> ../dev/psaux
null psaux ram ram0 ram1 ram2 ram3 ram4 ramdisk -> ram0
tty0 tty1 tty2 tty3 tty4 tty5 tty6 tty7 tty8 tty9 ttyS1
zero
/lib:
ld-2.0.7.so ld-linux.so.2 -> ld-2.0.7.so
libc-2.0.7.so libc.so.6 -> libc-2.0.7.so
libcom_err.so.2.0 libcom_err.so.2 -> libcom_err.so.2.0
libcrypt-2.0.7.so libcrypt.so.1 -> libcrypt-2.0.7.so
libdl-2.0.7.so libdl.so.2 -> libdl-2.0.7.so
libext2fs.so.2.4 libext2fs.so.2 -> libext2fs.so.2.4
libnsl-2.0.7.so libnsl.so.1 -> libnsl-2.0.7.so
libnss_files-2.0.7.so libnss_files.so.1 -> libnss_files-2.0.7.so
libpam.so.0.64 libpam.so.0 -> libpam.so.0.64
libpam_misc.so.0.64 libpam_misc.so.0 -> libpam_misc.so.0.64
libproc.so.1.2.6
libpwdb.so.0.54 libpwdb.so.0 -> libpwdb.so.0.54
libtermcap.so.2.0.8 libtermcap.so.2 -> libtermcap.so.2.0.8
libutil-2.0.7.so libutil.so.1 -> libutil-2.0.7.so
libuuid.so.1.1 libuuid.so.1 -> libuuid.so.1.1
modules
security
/lib/modules:
2.0.35
/lib/modules/2.0.35:
block cdrom
/lib/modules/2.0.35/block:
loop.o
/lib/modules/2.0.35/cdrom:
cdu31a.o
/lib/security:
pam_permit.so
/etc:
conf.modules fstab gettydefs group inittab issue ld.so.cache
motd nsswitch.conf pam.d passwd profile rc shells
termcap ttytype utmp -> ../var/run/utmp wtmp -> ../var/log/wtmp
/etc/pam.d:
other
/sbin:
fdisk fsck e2fsck fsck.ext2
mkfs mke2fs mkfs.ext2 mkswap
badblocks
swapoff -> swapon swapon
reboot -> halt shutdown halt init
insmod lsmod rmmod depmod modprobe
getty agetty ifconfig route probe dbflush
kerneld ldconfig
telinit -> init update
/bin:
sh -> ash ash bash false true
cut cat vi more
ls cp pwd rm date ln mv touch mkdir
grep egrep gzip gunzip zcat tar compress
ps dd df hostname login sync
ping rdev mount umount
su stty mknod e2fsck
chmod chown
/usr:
bin lib man sbin share tmp -> ../var/tmp
/usr/bin:
afio chroot cut diff du find free head id passwd tail tr wc whoami
/usr/lib:
libncurses.so.4 -> libncurses.so.4.2
libncurses.so.4.2
/usr/sbin:
fuser mklost+found
/usr/share:
terminfo
/usr/share/terminfo:
l
v
/usr/share/terminfo/l:
linux linux-m linux-nic
/usr/share/terminfo/v:
vt100 vt100-am
/var:
log run tmp
/var/log:
wtmp
/var/run:
utmp
/var/tmp:
/mnt:
cdrom floppy
/root:
.bashrc .cshrc .glintrc .profile .tcshrc
/proc:
/tmp:
#####
##### 유틸리티 디스크 견본 ###
cpio* debugfs* elvis* fdisk* ftape.o ftmt* grep* gzip*
insmod* lsmod* mt -> mt-st* mt-st* rmmod -> insmod*
tar* vi -> elvis*
========================================================
*** bootdisk
경호가 경험한 메시지
initrd - 초기화 램디스크
initrd.img
부트 디스크와 부팅 과정
부트 디스크의 종류
*** make bootdisk
경호 bootdisk 제작 스크립트
bootdisk 제작 - 디스켓에 LILO 와 커널을 함께 담기
bootdisk 제작 - LILO 없이 커널만 담기
램디스크 워드의 설정
*** rootdisk
경호 rootdisk 제작 스크립트
루트 fs의 크기를 줄이는 방법
모듈
PAM 과 NSS 에 대한 대책
NSS (Name Service Switch)
*** make rootdisk - 압축된 루트 fs의 제작
fs 만들기
램디스크를 사용하는 방법 (DEVICE = /dev/ram0)
루프백 디바이스를 이용
fs의 구성 - 화일 복사
/dev
/etc
/lib
/bin 과 /sbin
마지막 세부사항
*** other
rootdisk - 램디스크 사용하지 않음
유틸리티 디스크 만들기
boot disk 만드는 여러 방법
dd 이용해서 만들기
rawrite 이용해서 만들기
Tomsrtbt 부트 디스크 만들기
mkbootdisk 스크립트 이용해서 만들기
boot cd 제작
*** etc
복구 패키지들
리눅스 부트 프로세스
애로사항과 문제해결
전문가들이 사용하는 방법
자주 받는 질문들
*** 사용된 명령어 및 참조화일
loadlin, rawrite, mkbootdisk, tomsrtbt, mkisofs
mke2fs, mount, -o loop, -m 0, -i 1024, losetup
lilo, lilo.conf, dd, rdev, mknod
objcopy, --strip-all, --strip-debug
ldconfig, libc, ld-linux, ramdisk, /lib/security, /lib/modules, pam
nss, nsswitch.conf, passwd: files, shadow: files, group: files, services: files
boot.img, menu.lst, stage1, stage2, config.h, makefile, -lnss_dns, -lnss_file
##############################
##############################
bootdisk
다음과 같은 경우에 리눅스 부트 디스켓을 요긴하게 사용할 수 있다.
- 새로운 커널을 테스트할 때.
- 디스크에 문제가 발생했을때 복구용으로 (부트섹터를 날렸거나 디스크 헤드가 망가진 경우 등등.)
- 망가진 시스템을 고칠 경우 플로피 디스켓으로 부팅해 시스템을 수리 해야만 할 경우도 있다.
- /libc.so 등과 같은 핵심적인 시스템 파일을 업그레이드할 때.
*** 부트 디스크는 다음 방법을 통해 얻을 수 있다.
- 슬랙웨어 등의 배포본에 있는 부트 디스크를 이용한다. 적어도 부팅은 확실하게 할수있다.
- 복구전용으로 디자인된 복구 패키지를 이용한다.
- 각각의 디스크가 어떻게 동작하는지를 이해한 후 직접 부트 디스크를 제작한다.
가장 적당한 것이 배포본의 복구 디스켓용 fs을 이용 하는 것이다.
이 것들은 플로피를 대상으로 했기 때문에 어느 정도 용량에 대한 고려가 되어 있다.
그러나 레드헷의 복구 디스켓은 ext2 fs을 사용하고 라이브러리와 프로그램이 elf 포맷으로 되어 있어서
용량이 무척 크다. 슬랙웨어의 디스켓용 프로그램 들은 아직도 a.out 포맷으로 되어 있고
라이브러리도 최소한의 기능 만을 넣고 있기 때문에 크기가 비교적 작다.
새 프로그램을 a.out으로 컴파일하면 되겠지만 모든 배포본이 elf 시스템으로 되어 있어서 쉽지 않다.
추가하려는 프로그램이 한 두개라면 라이브러리를 실행 프로그램에 합치는 정적 컴파일을 하면 되겠지만
용량을 무시하지 못하게 된다. 20k 정도를 정적 컴파일 하게 되면 900K 이상이 된다.
*** 부팅하기
cdrom:/dosutils> autoboot.bat
loadlin 이라는 프로그램이 vmlinuz라는 커널이미지를 가지고 부팅한다
cdrom:/dosutils> loadlin [CDROM]\autoboot\vmlinux root=/dev/hdb1 ro
### 경호가 경험한 message ###
kernel panic: VFS: Unable to mount root fs on 02:00
rdev -r 명령으로 실행하지 않았을때 bootdisk 완료후 rootdisk 삽입하자 마자 나타남
루트 fs의 파티션이 틀렸다던지 루트 fs을 커널이 지원하지 않는다던지
또는 SCSI 어댑터를 모듈로 설정하여 SCSI 모듈이 로드되지 않을 경우 많이 볼수있다
VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER
rdev -r 명령실행후 bootdisk 완료후 rootdisk 삽입하자 마자 나타남 (이후 정상 진행)
RAMDISK: Compressed image found at block 0
bootdisk 구동후 rootdisk 정상 구동시 맨트
cannot excute "/etc/rc.d/rc"
no more processes left in this runlevel
부팅후 userid 입력하면 passwd 프롬프트가 뜨지 않아서 Ctrl+Alt+Del 눌렀을때 나타나는 멘트
fd0u1722 로 rootdisk 구성 했을시 나타나는 멘트
- invalid compressed format (err=1)<5> VFS: insert root floppy and press ENTER
- kernel panic: Attempted to kill init
floppy0: probe failed...
플로피 디스크 블럭 탐색 못하는것 같은데.. 까묵었다..
dd 로 vmlinuz 만 복사 했을시
invalid compressed format (err=2)
-- system halted
#####
##### initrd - 초기화 램디스크 ###
램디스크 코드의 동작원리에 대한 탁월한 설명은 리눅스 커널에 따라오는 문서에서 찾을수 있다.
/usr/src/linux/Documentation/ramdisk.txt 를 보라.
*** 어떤 부트 디스크 들은 initrd(initial ramdisk)라 불리우는 기능을 이용한다.
이 기능은 커널 2.0.x 대에서 처음 도입 되었으며 커널을 두 단계로 부트시킨다.
일단, 커널이 처음 부트된 후 초기화 램디스크 이미지를 부트 디스크에서 읽어온다.
초기화 램디스크 이미지는 루트 fs이 로드 되기전 먼저 실행 되어야 할 프로그램을 담은 루트 fs다.
이 프로그램은 시스템 환경을 조사해서 사용자로 하여금 다양한 부트옵션을 선택할 수 있게 한다.
가령 진짜 루트디스크를 어느 디바이스에서 로드 할지를 선택할 수도 있다.
이것은 주로 커널에 내장 되어 있지 않은 추가적인 모듈들을 로드한다.
이 초기화 프로그램이 끝나면 커널은 진짜 루트 이미지를 로드해서 정상적으로 부팅을 속개하게 된다.
initrd 에 관한 더 많은 내용은 아래를 참고
/usr/src/linux/Documentation/initrd.txt
ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/initrd-example.tgz
*** initrd라는 이미지는 초기화 램 디스크인데 램디스크와 차이가 있다.
램 디스크는 부팅한 후에 루트 fs으로 지정되어 재부팅 할 때까지 변하지 않지만
초기화 램디스크는 커널이 부른후 그안에서 임의의 작업을 하고 언마운트 시킬 수 있다.
이 것을 언마운트 시키고 대신에 일반 램 디스크를 적재하게 된다.
이런 특성 때문에 초기화 램디스크는 특정 하드웨어에 필요한 모듈을 가지고 있다가
사용자의 요구에 따라 적재하고 사라지는 등 램디스크의 용량 문제로 유지하고 있기 힘든
프로그램이나 부팅하면서 한 번만 사용되는 프로그램 들을 넣어서 사용할 때 주로 쓴다.
또다른 차이는 램 디스크는 커널이 적재 하면서 /etc/init(/sbin/init)를 실행하게 되지만
초기화 램 디스크는 /linuxrc 파일을 실행 한다. linuxrc는 어떤 프로그램도 될 수가 있다.
(/usr/src/linux/Documentation/initrd.txt 참고)
#####
##### 부트 디스크와 부팅 과정 ###
부트 디스크란 기본적으로 플로피 디스켓에 쏙 들어가는 미니어처 즉, 축소판 리눅스 시스템이다.
부트 디스크는 완전한 풀 사이즈의 리눅스 시스템의 기능 중 많은 부분을 그대로 수행할 수 있어야만 한다.
부트 디스크 제작에 앞서 당신은 리눅스의 부팅 과정의 기본 원리를 이해해야만 한다.
### 부트 시퀀스 ###
일반적인 데스크탑 PC의 부팅은 다음과 같은 순서를 가진다.
BIOS(Basic Input/Output System)
처음 PC에 전원을 넣으면 BIOS는 자체적인 테스트 POST(Power On Self Test)를 수행하여
어떤 장치가 있으며 그것들이 제대로 동작하는지를 체크하고 초기화한다.
그리고 부팅 하기위해 플로피 디스크나 CD-ROM 또는 하드디스크의 부트 섹터를 읽는 작업을 한다.
부트 로더
보통 MBR(Master Boot Record) 이나 플로피 디스크일 경우 디스크의 첫번째 섹터 에서 동작한다.
리눅스에서는 LILO나 GRUB을 사용하고, 부트 로더가 존재하지 않는다면 커널이미지가
첫번째 섹터부터 쓰여지게 하면 부트 로더 없이 부팅할 수 있다.
커널
BIOS나 부트 로더에 의해 로딩된 커널은 주변장치와 하드웨어를 초기화하고 루트 fs을 찾는uf
이 다음과정이 init 프로세서를 fork 하는것이다.
init
커널 소스의 init/main.c를 보면 알수 있듯이 /sbin/init, /etc/init, /bin/init, /bin/sh 순으로 실행한다.
만약 부팅시 커널 옵션에 'init='을 정의해 놓았다면 그것이 실행된다.
이후 /etc/inittab 파일을 읽어서 지정된 레벨로 실행한다.
getty
일반적으론 /etc/inittab에 정의된대로 getty가 /bin/login을 실행 한다.
login
login이 수행되면 모니터에서 'login: '을 볼 수 있으며 인증방식을 통해 인증을 거쳐
shell을 실행하게되면 비로서 shell 프롬프트가 뜨고 키보드를 통한 입력이 가능하다.
### 부팅 과정 ###
모든 PC 시스템들은 롬(BIOS) 내의 코드를 실행시키는 것으로 부팅을 시작한다. 이 코드는
부트 드라이브의 섹터 0, 실린더 0 부분을 읽고, 바이오스는 읽어들인 이 섹터의 내용을 실행한다.
대부분의 부트 가능한 디스크들은 섹터 0, 실린더 0 영역에 다음 내용 중 하나를 담고 있다.
- LILO 등과 같은 부트로더(boot loader)의 코드
- 리눅스 등과 같은 운영체제 커널의 시작 부분.
만일 리눅스 커널이 디스켓에 직접 복사된 경우 (raw copy)라면 디스크의 첫번째 섹터는
리눅스 커널 그 자체의 첫번째 섹터가 된다. 이 첫번째 섹터는 부트 디바이스로부터 커널의
나머지 부분을 계속 읽어 들임으로써 부트 프로세스를 진행한다.
일단 커널이 완전히 로드되면, 이제 기본적인 디바이스들을 초기화 시킨다. 그 다음, 특정 디바이스에서
루트 fs을 찾아 / 에 마운트 하려고 시도한다. 이때 커널은 어디에서 루트 fs을 찾아야
하는지를 미리 지정받아 알고있어야 한다. 만일 커널이 그 위치에서 로드 가능한 이미지를 찾지 못한다면
시스템은 멈춰버리게 된다. 디스켓에서 부팅하는 경우 루트 fs을 램디스크로 로드하기도 한다.
일단 루트 fs이 로드되어 마운트되면 다음과 같은 메시지를 볼 수 있다.
VFS : Mounted root (ext2 filesystem) readonly.
이 시점에 이르면 시스템은 루트 fs에 있는 init 프로그램을 찾아서 실행시킨다
init 는 설정파일인 /etc/inittab 에서 sysinit 라인을 찾아 그에 해당하는 이름의 스크립트를 실행하고
이 스크립트는 쉘 명령어로 아래와 같은 기본적인 시스템 서비스를 제공한다.
- 모든 디스크에 fsck 를 실행한다.
- 필요한 커널 모듈을 로드한다.
- 스왑핑(swapping)을 시작한다.
- 네트웍을 초기화시킨다.
- fstab 에 적힌 디스크들을 마운트한다.
이 스크립트는 대개 다른 여러가지 스크립트들을 동작시킨다. 즉, 초기화 과정을 모듈화시킨 것이다
일반적인 SysVinit 구조에서는 /etc/rc.d/ 디렉토리 밑에 복잡한 구조의 하위디렉토리가 있고 각각의
하위디렉토리에는 수많은 시스템 서비스들을 어떻게 온오프 시키는지를 정해놓은 파일들이 있다.
하지만 부트 디스크에서 사용하는 sysinit 스크립트는 보통 매우 간단하다.
sysinit 스크립트의 실행이 끝나면 다시 init 프로세스로 조종권이 돌아오고, 이번에는 default runlevel
단계로 들어간다. default runlevel 은 inittab 파일내에 initdefault 키워드로 지정되어 있다.
runlevel 라인은 주로 콘솔이나 tty 를 통한 통신을 책임지는 getty 같은 프로그램을 지정한다.
우리에게 익숙한 login: 프롬프트 따위를 출력해 주는 것이 바로 getty 프로그램이다.
getty 프로그램은 로그인 인증을 처리하는 login 프로그램을 구동시킨 후 user 세션을 마련한다.
### 부트 디스크의 종류 ###
- boot
부트 가능한 커널을 포함한 디스크. 이 디스크는 커널을 부트시키는 용도로 사용되며, 이렇게
로드된 커널은 또다른 디스크에 위치하고 있는 루트 fs을 로드할 수 있다. 보통, 부트 디스크상의
커널은 루트 fs이 어디에 위치하고 있는지를 미리 지정받아 알고 있어야한다.
대부분의 경우 부트 디스크는 다른 디스켓상의 루트 fs을 로드하게 되지만, 때로는 하드디스크에 있는
루트 fs을 로드하도록 설정할 수도있다. 이런 기법은 주로 새로운 커널을 테스트 해볼때 사용된다
(make zdisk 명령은 커널 소스코드로부터 자동으로 부트 디스크를 만든다).
- root
리눅스 시스템 운용에 필수적인 파일들을 가진 fs을 루트 fs이라 하며 이 루트 fs을
담은 디스크가 root 디스크다. 루트 디스크가 반드시 커널이나 부트로더를 가지고 있을 필요는 없다.
커널이 부트된 상태라면 루트 디스크는 다른 어떤 디스크도 필요없이 독자적으로 시스템을 운용할 수있다.
보통, 루트 디스크는 자동적으로 램디스크로 복사된다. 램디스크를 사용하면 루트 fs에 대한
액세스가 훨씬 빠르며, 또한 디스크 드라이브를 비워 유틸리티 디스크를 넣을 수 있다.
- boot/root
커널과 루트 fs을 한장에 모두 가지고 있는 디스크. 바꾸어 말하면, 하드디스크 없이도 이 디스크는
리눅스 시스템을 부트하고 운용하는데 필요한 모든 것을 다 가지고 있는 것이다.
- utility
그 밖의 여러가지 데이터를 담은 디스켓으로서 fs을 가지고 있지만 루트 fs으로서 마운트되는 것은
아니다. 루트 디스크 한장에 다 담기 힘들 경우 여분의 유틸리티들을 이 디스크에 담는다.
일반적으로 부트 디스크를 제작 한다고 말할 때는 boot(kernel) 와 root(files) 부분을 만드는 것을 뜻한다.
두 부분을 하나에 담을 수도 있고 (a single boot/root disk) 두 장의 디스크로 분리하여 담을수도 있다
(boot + root disks). 아마도 boot 디스켓과 root 디스켓을 따로 만들고 그래도 모자라는 경우
한두 장의 utility 디스켓을 더 만드는 것이 복구 디스켓을 제작하는 가장 유연한 방법일 것이다.
##############################
##############################
make bootdisk
# fdformat -n /dev/fd0
*** 경호 bootdisk 제작 스크립트
#!/bin/bash
kernel_block=`expr $(ls -lL /boot/vmlinuz | | awk '{print $5}') / 1024`
otherfiles_block=150
sourcedir="./bootdisk/*"
bootdisk="/mnt/t2/" # temp boot fs location to mount
echo;echo;echo "---------------------0 준비단계"
umount $bootdisk
sync;sync
echo;echo;echo "---------------------1 bootdisk ext2 fs 제작"
mke2fs -i 8192 -m 0 /dev/fd0 $kernel_block
sync;sync
echo;echo;echo "---------------------2 마운트 하기"
mount /dev/fd0 $bootdisk
sync;sync
echo;echo;echo "---------------------3 bootdisk 의 쓸모없는 화일 지우기"
rm -rf ${bootdisk}lost+found
sync;sync
echo;echo;echo "---------------------4 bootdisk 에 화일 복사하기"
cp -dpR ${sourcedir} ${bootdisk}
sync;sync
echo;echo;echo "---------------------5 lilo 실행"
lilo -v -C bdlilo.conf -r $bootdisk
sync;sync
umount $bootdisk
sync;sync
echo;echo;echo;echo "=============================================="
echo "=== 완료 되었습니다. ==="
echo "=============================================="
### 커널 설정 ###
대부분의 경우 현재 시스템의 커널을 그대로 부트 디스켓으로 복사해서 부트해도 되지만
때에 따라서는 별도의 커널을 만들어야 할 때도 있다. 한 장의 boot/root 디스켓을 만들려 한다면
커널은 디스켓 상에서 가장 큰 파일이 되기 때문에 가능한한 그 크기를 줄일 필요가 있다.
*** 시스템 커널에 있는 백업 장비에 대한 I/O 지원은 boot/root 디스켓의 커널에도 포함 시켜야 한다
예로 백업받은 파일들이 모두 테이프에 담겨있고 테이프 드라이브를 액세스하기 위해서는
ftape 를 써야만 하는 시스템이 있다고 하자, 만약 Ftape를 포함하고 있는 루트 드라이브에
문제가 발생했다면 이제는 백업테이프를 써서 복구할 방법이 없다.
결국, 리눅스를 새로 설치후, ftape 를 다시 인스톨 해야 백업 테이프를 읽어올 수 있다
- boot/root 시스템을 기동하는 것과 무관한 다른 디스크 드라이브에 대한 지원도 빼버려라.
네트워킹이 그 좋은 예다. 기타 불필요한 디바이스들도 버리는 것이 좋다.
- 압축된 ext2 fs을 부트하기 위해서 램디스크와 ext2 에 대한 지원은 커널안에 포함시켜야 한다.
- 최소한의 기능만을 포함한 커널을 만들었다면 이제 다시 무엇을 추가할수 있을지 확인해 보아라.
boot 디스켓의 주된 용도는 손상된 fs을 복구하는 것일 테니 커널 차원의 지원이 필요하다.
#####
##### bootdisk 제작 - LILO 와 커널을 함께 담기 ###
부트로더의 일종인 LILO 를 사용할지 여부를 결정해야 한다.
LILO 를 쓰면 하드웨어를 초기화 시키는 파리메터를 부팅시에 알려줄수 있다는 점이다
LILO 의 단점은 부트 디스크가 보다 복잡해 지고 용량을 조금 더 차지 한다는 점이다.
LILO 를 위한 작은 설정파일을 만든다. (btlilo.conf)
prompt
delay = 150
timeout = 50
default = bootdisk
boot = /dev/fd0
map = /boot/map
install = /boot/boot.b
backup = /dev/null
lba32
compact
read-write
image = /boot/vmlinuz
label = bootdisk
root = /dev/fd0
read-only
image = /boot/vmlinuz
label = harddisk
root = /dev/hda5
initrd = /boot/initrd-redhat.img
read-only
이제 커널 fs이라 불리우는 작은 fs을 만들어야 한다. 이것은 루트 fs과 는 별개의 것이다.
먼저, fs의 크기를 얼마로 해야할지 알아내야 하고, 만들어낸 커널의 블록 단위 크기가
얼마 인지 확인후 (vmlinuz-2.4.20-8 의 크기 / 1024) 70 을 더한다.
70 블록은 inode 와 그 밖의 몇 가지 파일들에 필요한 대략적인 크기다.
첫번째 디스크는 커널 전용으로만 사용되기 때문에 두장의 디스켓으로 하면 넉넉히 잡아도 좋다.
계산한 숫자를 KERNEL_BLOCKS 라고 부르기로 하자.
# ls -l /boot/vmlinuz-2.4.20-8
-rw-r--r-- 1 root root 1122186 3월 14 2003 /boot/vmlinuz-2.4.20-8
# expr 1122186 / 1024
1095
# mke2fs -i 8192 -m 0 /dev/fd0 KERNEL_BLOCKS
-i 8192 8192 바이트 당 하나의 inode 를 할당
-m 0 mke2fs 가 root 용 공간을 할당하지 못하게한다
# mount /dev/fd0 /mnt
# rm -rf /mnt/lost+found
# mkdir /mnt/{boot,dev}
# cp -dpR /dev/{null,fd0} /mnt/dev
디바이스 /dev/null 과 /dev/fd0 를 만든다.
# cp /boot/{map,boot.b} /mnt/boot/
LILO 는 그 부트로더인 boot.b 의 복사본을 필요로 한다
# cp /boot/vmlinuz-2.0.0 /mnt/boot/vmlinuz
# cp bdlilo.conf /mnt
마지막으로 앞 절에서 만든 LILO 설정 파일을 커널과 함께 플로피로 복사해 넣는다.
# lilo -v -C bdlilo.conf -r /mnt
-r 부트로더를 다른 루트에 설치할 때 사용된다.
#####
##### bootdisk 제작 - LILO 없이 커널만 담기 ###
# dd if=/boot/vmlinuz of=/dev/fd0 bs=1k
668+1 records in
668+1 records out
LILO 를 사용하지 않겠다면 dd 명령을 써서 커널을 부트 디스크에 담아야 한다.
위의 예에서 dd 는 668 개의 완전한 레코드와 1개의 부분 레코드를 써넣었다.
따라서 커널은 디스켓 앞부분의 669 블록들을 점유하게 된다.
이 숫자를 KERNEL_BLOCKS 라고 부르겠으니 기억해 두어라.
# rdev /dev/fd0 /dev/fd0
# rdev -R /dev/fd0 0
루트 디바이스를 디스켓 자체로 설정한 후 루트가 read/write 로 로드 되도록 설정한다.
# dd if=/dev/fd0 of=work-img.gz bs=1k seek=670
두번째 램 디스크 이미지는 work-img.gz이며 위명령을 사용해서 플로피에서 직접 읽어 올 수 있다.
리눅스 플로피 fs은 한 플로피에 2개의 fs을 가지고 있다.
커널 이미지를 담고 있는 부트 fs과 작업을 위한 프로그램을 가진 램 디스크 이미지이다.
플로피의 앞부분 669K 바이트가 ext2 fs으로 만들어져 있으며
커널 이미지와 lilo를 사용한 부팅 옵션을 위한 파일들 그리고 부팅할 때 나오는 메세지가 담겨 있다.
#####
##### 램디스크 워드의 설정 ###
커널 이미지의 최초 512 (램디스크 워드) 바이트 안에 커널 설정이 있다. rdev 명령을 써서
확인 및 설정이 가능하고, 이것은 다른 옵션들과 더불어서 루트 fs을 어디서 찾을 것인지 설정한다.
LILO를 사용 하겠다면 마운트될 커널의 경로 (/mnt/vmlinuz)를 rdev 파라메터로 써야 한다.
LILO를 쓰지 않고 커널을 dd 명령으로 복사했다면 플로피 디바이스의 이름을 써준다 (/dev/fd0)
# rdev -r KERNEL_OR_FLOPPY_DRIVE VALUE
### 그내용은 다음과 같이 해석한다. ###
bit 0-10 램디스크가 시작하는 오프셋. 1024 byte 블록 내의 오프셋
bit 11-13 사용하지 않는다
bit 14 램디스크로 로딩될지를 나타내는 플래그
bit 15 루트 fs을 로딩하기 전에 한번 멈출지를 결정하는 플래그
만약 15번 비트가 설정되어 있으면 부팅시에 새로운 디스켓을 집어 넣으라는 메시지를 받게 된다
이 기능은 두 개의 디스크로 부팅할 경우 필요하다.
한 개의 boot/root 디스켓을 만들 것인지 두개의 "boot+root" 디스켓을 만들 것인지에 따라
다음 두 가지 경우가 생길 수 있다.
*** 한개의 디스켓을 만든다면 압축 루트fs은 커널 바로 뒤에 연이어 위치하게 되므로 그 오프셋은
첫번째 빈블럭 (KERNEL_BLOCKS 값과 동일) 이된다. 비트 14는 1로, 비트 15는 0으로 설정하라
(당신이 한장짜리 디스크를 만드는데 루트 fs이 253 블록(십진수)에서 시작 한다고 치면
램디스크 워드의 값은 253(십진수) 에다 비트 14 는 1, 비트 15 는 0 으로 세팅한 값을 주어야한다)
이 램디스크 워드 값을 구하려면 모두 십진수로 변환해 더하면 된다.
253 + (2^14) = 253 + 16384 = 16637
# rdev -r /mnt/floopy/boot/vmlinuz 16637
*** 두개의 디스켓 세트를 만든다면 루트 fs은 두 번째 디스켓의 0 번 블록부터 시작할 것이고
따라서 그 오프셋은 0 이다. 비트 14는 1로, 비트 15도 1로 설정하라.
따라서 램디스크 워드의 십진수 값은 2^14 + 2^15 = 49152 가 된다.
램디스크 워드에 해당하는 값을 주의깊게 계산한 다음, 그 값대로 rdev -r 명령으로 설정한다.
십진수를 사용해야 함에 주의하라.
# rdev -r /mnt/floopy/boot/vmlinuz 49152
LILO를 사용한다면 이제 디스켓을 언마운트 시키십시오.
##############################
##############################
rootdisk
*** 경호 lib 디렉토리 카피 스크립트
작동하지 않는다. cp -dpR /lib/${libfiles} $rootdisk 문구 에서 ${libfiles} 를
쉘이 정규식으로 확장한후 cp 명령의 인수로 넘겨야 하는데.
셀이 확장을 하지 않고 "{....}" 문자열로 cp 로 넘어가기에
"{모든화일}" 라는 화일명 1개가 인수로 넘어간 것과 같다. 그래서 안되징..
#!/bin/bash
libfiles="ld-2.3.2.so,ld-linux.so.2,\
libc-2.3.2.so,libc.so.6,\
libcom_err.so.2.0,libcom_err.so.2\
libcrypt-2.3.2.so,libcrypt.so.1,\
libdl-2.3.2.so,libdl.so.2,\
libe2p.so.2.3,libe2p.so.2,\
libext2fs.so.2.4,libext2fs.so.2,\
libpam.so.0.75,libpam.so.0,\
libpam_misc.so.0.75,libpam_misc.so.0,\
libpcre.so.0.0.1,libpcre.so.0,\
libproc.so.2.0.11,\
libresolv-2.3.2.so,libresolv.so.2,\
libtermcap.so.2.0.8,libtermcap.so.2,\
libuuid.so.1.2,libuuid.so.1" # source lib files
rootdisk="/mnt/tmp2/lib" # root disk lib directory
cp -dpR /lib/${libfiles} $rootdisk
*** 경호 rootdisk 제작 스크립트
#!/bin/bash
workdir="/root/"
rootfile="rootfile.ccc" # temp roof device file name
rootsize="4500" # temp roof device file size (4200=3.8M)
rootdisk="/mnt/t2/" # temp root fs location to mount
# root file directory to copy
rootsrcdir="./rootdisk/*"
echo;echo;echo "---------------------0 준비단계"
umount $rootdisk; rm -f ${workdir}${rootfile} ${workdir}rootfs.gz
sync;sync
echo;echo;echo "---------------------1 루프 디바이스 화일 생성"
dd if=/dev/zero of=${workdir}${rootfile} bs=1k count=$rootsize
sync;sync
echo;echo;echo "---------------------2 루프 디바이스 화일 시스템 생성"
mke2fs -m 0 -i 1024 ${workdir}${rootfile}
sync;sync
echo;echo;echo "---------------------3 루프 디바이스 화일 마운트"
mount -o loop -t ext2 ${workdir}${rootfile} $rootdisk
sync;sync
echo;echo;echo "---------------------4 루프 디바이스 화일로 루트 디스크 화일 복사"
cp -dpR $rootsrcdir $rootdisk
sync;sync
echo;echo;echo "---------------------5 루프 디바이스 화일 압축"
dd if=${workdir}${rootfile} bs=1k | gzip -v9 > ${workdir}rootfs.gz # 루트 fs 생성
sync;sync
echo;echo;echo "---------------------6 플로피 디스크 생성"
dd if=${workdir}rootfs.gz of=/dev/fd0u1722 bs=1k # 루트 fs을 두번째 디스켓에 담을때
sync;sync
umount $rootdisk
rm -rf ${workdir}${rootfile} ${workdir}rootfs.gz
sync;sync
echo;echo;echo;echo "=============================================="
echo "=== 완료 되었습니다. ==="
echo "=============================================="
#####
##### 루트 fs의 크기를 줄이는 방법 ###
때로는 루트 fs이 너무 커서 압축을 해도 디스켓 한 장에 다 들어가지 않을 수도 있다.
다음은 fs의 크기를 줄이는 몇가지 방법이다.
- 디스크의 밀도를 높인다
기본적으로 플로피 디스켓은 1440 K 로 포맷됩니다, 하지만 더 높은 밀도의 포맷도 가능하다.
fdformat 는 디스크를 1600, 1680, 1722, 1743, 1760, 1840, 1920 크기로 포맷할 수 있다
대부분의 1440 K 드라이브들은 1722 K 의 포맷을 지원한다
(man fdformat, /usr/src/linux/Documentation/devices.txt 참조)
- 쉘을 바꾼다
bash, tcsh 은 크기도 크고 많은 라이브러리들을 필요로 한다. ash, lsh, kiss, smash 같은
경량급 쉘들은 훨씬작고 라이브러리를 별로(전혀) 필요로 하지 않으므로 대안이 될수있다.
이러한 대용 쉘들은 대부분 다음 홈페이지에서 찾을 수 있다.
http://metalab.unc.edu/pub/Linux/system/shells/
어떤쉘을 사용하던 부트 디스크에 포함시킨 rc 파일들 내의 명령어를 실행시킬 수 있어야 한다.
- 스트립 라이브러리와 바이너리들을 사용한다
라이브러리들과 바이너리들은 보통 스트립되지 않은(즉, 디버깅 심볼을 포함하는) 상태로 존재한다.
이런 파일에 대해 "file" 명령을 실행하면 "not stripped" 라는 결과가 출력된다.
# objcopy --strip-all FROM TO
바이너리들을 루트 fs으로 복사할 때는 위과 같은 습관을 들이는 것이 좋다.
# objcopy --strip-debug FROM TO
라이브러리를 복사할 때
- 중요하지 않은 파일들은 유틸리티 디스크로 옮긴다
부트나 로그인 시에 반드시 필요한 것이 아니라면 유틸리티 디스크로 옮겨놓는다.
모듈들을 유틸리티 디스크로 옮겨놓는 것도 고려해 볼만하다.
#####
##### 모듈 ###
모듈화된 커널을 사용한다면 부팅 후 부트 디스크로 부터 어떤 모듈을 로드 해야할지를 고려해야만 한다.
만약 백업 테이프들이 플로피 테이프상에 있다면 ftape 와 zftape 모듈을 포함시켜야 하고 SCSI 장비를
가지고 있다면 SCSI 관련 모듈을 포함시켜야 하며 만일 응급상황에서 네트웍에 액세스해야 한다면
PPP 나 SLIP 관련 모듈을 포함시켜야 한다.
- 모듈들은 /lib/modules 에 두면 된다.
- insmod, rmmod, lsmod 프로그램을 포함 시켜야 한다.
- modprobe, depmod, swapout 도 포함시켜야 한다. (모듈을 자동으로 로드하고 싶다면)
- kerneld 를 사용한다면 kerneld 를 /etc/conf.modules 의 설정에 맞추어 포함시켜야 한다.
#####
##### PAM 과 NSS 에 대한 대책 ###
PAM (Pluggable Authentication Modules)
당신 시스템에는 ldd 로 확인할 수 없는 동적으로 로드되는 라이브러리가 필요할 수도 있다.
만일 시스템이 PAM을 쓰고 있다면 부트 디스크 상에 PAM 을 위한 몇가지 준비를 해야한다.
그러지 않으면 로그인이 불가능할 것이다.
PAM 이란 사용자를 인증하고 사용자들의 서비스에 대한 액세스를 컨트롤하는 모듈화된 방법이다.
시스템이 PAM 을 쓰고있는지 확인해보려면 /etc/pam.conf 이나 pam.d 디렉토리가 있는지 체크.
그런 것이 있다면 최소한의 pam 지원은 하고 있는 것이다
(login 실행파일에 대해 ldd 를 해보자. libpam.so 가 출력되면 PAM 이 필요하다는 뜻).
운좋게도, 부트 디스크에 있어서 보안은 보통 관심밖의 사항이다.
물리적 액세스를 할 수 있는 사람은 그만한 권한이 있는 사람일 것이다. 따라서,
다음과 같은 간단한 /etc/pam.conf 파일을 만들어두면 PAM 기능을 무력화시킬 수 있다.
OTHER auth optional /lib/security/pam_permit.so
OTHER account optional /lib/security/pam_permit.so
OTHER password optional /lib/security/pam_permit.so
OTHER session optional /lib/security/pam_permit.so
- /lib/security/pam_permit.so 를 루트 fs으로 복사하라.
이렇게 하면 머신의 파일이나 서비스에 누구든지 제한없이 액세스할 수 있다
어떤 이유로 부트 디스크상의 보안에도 신경을 써야 한다면
하드디스크의 PAM 설정의 일부 혹은 전부를 당신의 루트 fs으로 복사 해야한다.
(PAM 에 관한 문서를 주의깊게 읽은후 /lib/security 에서 필요한 라이브러리들을 루트 fs로 복사)
또한 /lib/libpam.so 를 부트 디스크에 포함 시켜야만 한다.
(앞의 /bin/login 에 ldd 를 실행시켰을때 의존성을 눈치챘을 것이다.)
# cp /lib/libpam.so /mnt/lib/
# cp /etc/pam.d/{login,passwd} /mnt/etc/pam.d/
필요한 설정 화일을 카피한다.
#####
##### NSS (Name Service Switch) ###
glibc(일명 libc6)를 사용하고 있다면 name service 에 대한 준비를 해야한다. 그렇지 않으면
로그인이 불가능할 것이다. /etc/nsswich.conf 는 여러가지 서비스에 대한 db 열람을 컨트롤한다.
네트웍상의 서비스(DNS, NIS lookup)에 액세스 할 필요가 없다면 간단한 nsswitch.conf 파일만 준비하면 된다.
이것은 모든 서비스가 오로지 로컬 파일에서 제공되는 것으로 설정한 것이다.
passwd: files
shadow: files
group: files
hosts: files
services: files
또한 /lib/libnss_files.so.1 을 포함 시켜야한다.
이것은 파일 열람(file lookup)을 처리할 때 동적으로 로드되는 라이브러리다
부트 디스크에서 네트웍에 액세스할 작정이라면 보다 정교한
nsswitch.conf 파일을 만들 필요가 있다. (nsswitch 맨 페이지를 참고)
당신이 설정한 service 들에 대해 각각에 해당하는 /lib/libnss_service.so.1 파일들을
포함시켜야만 한다는 점을 명심하라.
##############################
##############################
make rootdisk - 압축된 루트 fs의 제작
루트 fs을 만들때는 시스템 구동에 필수적인 파일들을 고르는 작업이 필요하다.
잘 쓰이지는 않지만 압축안된 fs을 디스켓상에 만들어 루트로 마운트시키는 방법도 있다
루트 fs은 풀 사이즈의 완전한 리눅스 시스템을 지원하기 위한 모든 것을 갖추어야 한다.
이를 위해서는 리눅스 시스템에 꼭 필요한 최소요건 만큼은 루트디스크에 반드시 구비되야 한다.
- 기본적인 fs 구조
- 최소한도의 디렉토리들 : /dev, /proc, /bin, /etc, /lib, /usr, /tmp
- 기본적인 유틸리티들 : sh, ls cp mv 등
- 꼭 필요한 config 파일들: rc, inittab, fstab 등
- 디바이스들 : /dev/hd*, /dev/tty*, /dev/fd0 등
- 유틸리티 프로그램에 필요한 기본적인 함수들을 제공하는 런타임 라이브러리.
루트 디스켓으로 다음과 같은 작업을 할수 있어야만 한다
- 다른 드라이브에 있는 fs을 체크하는 작업.
- cpio, tar, gzip, ftape 등의 archive 및 압축 유틸리티를 써서 백업으로부터
원래의 루트드라이브의 전부 혹은 일부를 복구하는 작업
#####
##### fs 만들기 ###
압축된 루트 fs을 만들기 위해서는 압축하기전 필요한 모든 파일들을 담을 수 있는 충분한 크기의
빈 공간이 필요하다. (약 4 메가바이트)
압축 fs은 fs이 압축된 상태로 있다가 부트시에 램디스크로 압축이 풀리면서 복사되는 것을 말한다.
압축 fs을 쓰면 표준 1440K 디스켓에 훨씬 많은 파일(약 6메가)들을 넣을 수 있다.
fs이 디스켓의 용량보다 훨씬 크기 때문에 디스켓 위에 이를 직접 작성하는 것은 불가능하다.
일단 다른 곳에서 fs을 완전히 만들어 압축한 다음, 그 압축된 것을 디스켓에 복사하는 방법을 써야한다.
==========================================================================================
>>> 압축된 fs을 부트하기 위해서는 램디스크와 ext2 지원을 반드시 커널에 내장시 켜야한다 <<<
==========================================================================================
만약 쓰지 않는 수메가바이트의 하드디스크 파티션이 있어 이를 이용할 수 있다면 아주 좋은 방법이다.
### 램디스크를 사용하는 방법 (DEVICE = /dev/ram0) ###
/dev/ram0, /dev/ram, /dev/ramdisk 등의 디바이스를 가지고 있는지 확인하고, 만일 없다면
====================================================================
>>> mknod 명령 (major number 1, minor 0)으로 /dev/ram0를 만든다. <<<
====================================================================
메모리 일부를 가상의 디스크 드라이브로 설정하고, 램디스크는 필요한 크기의 fs을 담을수 있어야 한다.
만일 LILO 를 쓰고 있다면 /etc/lilo.conf 에 "RAMDISK_SIZE = nnn" 라인이 있는지 확인하라
이것은 할당가능한 램디스크 크기의 최대치를 설정한다. 디폴트는 4096K 인데 이 정도면 충분하다
### 루프백 디바이스를 이용 ###
루프 디바이스(/dev/loop0, /dev/loop1)가 없다면
===============================================
>>> mknod /dev/loop0 b 7 0 명령으로 만든다. <<<
===============================================
루프백 디바이스는 파일 하나를 마치 디바이스처럼 취급할 수있다.
즉, 파일 한개를 마치 하드디스크의 파티션처럼 인식시키는 것이다. 루프백 디바이스를 이용해서
하드 디스크 상에 3 메가바이트 가량의 파일을 만든후 이 위에 fs을 만들 수 있다. (man losetup)
ftp://ftp.win.tue.nl:/pub/linux/util/mount/ 에서 util-linux 패키지를 받아 설치하자
# dd if=/dev/zero of=[RAM_DEVICE or loopback_filename] bs=1k count=3000
하드디스크 상에 충분한 크기의 임시 파일을 만든다.
루프백 디바이스를 사용하면 DEVICE 자리에 파일이름을 써야 한다.
디바이스의 내용을 모두 0 으로 채운다. 이 과정이 중요한 이유는 디바이스 상의 fs은
나중에 압축되게 되므로 사용되지않은 모든 영역은 0 으로 채워야 최대한으로 압축할수 있다.
# mount -o loop -t ext2 [RAM_DEVICE or loopback_filename] /mnt
-o loop 옵션을 주어 mount 프로그램에게 루프백 디바이스를 마운트함을 알려야 한다.
위는 루프백 디바이스를 통해 filename 를 마운트포인트 /mnt 에 마운트 시킨다.
앞으로 우리가 만들 모든 디렉토리들은 /mnt 아래에 있는 것으로 가정하자
# mke2fs -m 0 -i 1024 [RAM_DEVICE or loopback_filename]
fs을 만든다. mke2fs 명령은 자동으로 사용가능 용량을 인지하고 fs을 설정한다.
-m 0 root 용 공간을 할당하지 못하게한다 (사용가능한 디스크 용량을 더많이 확보)
-i 1024 1024 정도로 설정하면 inode 가 부족해지는 일은 없다.
커널이 자동으로 램디스크로 복사할수 있는 루트 디스크 fs은 minix 와 ext2 두가지 뿐이다
ext2 를 쓰면 -i 옵션을 주어 디폴트값 보다 더많은 inode 를 설정할 수 있고,
mke2fs 는 디폴트로 1.44 M 디스켓에 360 개의 inode를 생성한다.
또는
# head -c 1000000 < /dev/zero > file ::: 지정된 크기로 파일을 설정
# losetup /dev/loop0 file ::: 루프백 디바이스로 설정
# mke2fs /dev/loop0 ::: fs 만들기
# mount -o loop /dev/loop0 /mnt
#####
##### fs의 구성 - 화일 복사 ###
다음은 일반적인 루트 fs에 들어있어야할 최소한의 디렉토리다.
/proc proc fs에 필요한 디렉토리
/dev I/O 에 필요한 디바이스들이 위치.
/lib 런타임 공유라이브러리들이 위치.
/etc 시스템 설정파일들이 위치.
/sbin 시스템에 없어서는 안될 필수 바이너리들이 위치.
/bin 시스템의 일부로 간주되는 기본적인 바이너리들이 위치.
/mnt 다른 디스크들을 관리하기 위한 마운트포인트
/usr 그밖의 여러 유틸리티와 응용프로그램들이 위치.
여기에 제시된 디렉토리 구조는 루트디스켓에 해당되는 것만 적은 것이다.
실제의 리눅스 시스템은 보다 복잡하고 세련된 디렉토리 구조에 관한 규약을 가지고 있다.
이를 표준 계층 fs (FHS, Filesystem Hierarchy Standard)라 부르는데
각 파일들을 어느 디렉토리에 두어야 하는가에 대한 규약이다
/proc 디렉토리는 단순히 proc fs이 위치하게 되는 장소이고,
/mnt 와 /usr 는 boot/root 시스템 가동후 사용되는 마운트 포인트다.
따라서 이 3 가지는 mkdir 명령으로 디렉토리만 만들어 주면 된다.
#####
##### /dev ###
디바이스(장치) 노드가 위치한다.
- 디렉토리에는 시스템이 사용하는 모든 디바이스들 각각에 대응하는 특수파일들이 위치한다
- 디렉토리 자체는 보통의 디렉토리와 같으므로 mkdir 명령어로 그냥 만들어 주면된다.
- 여기의 파일은 메이저와 마이너 넘버로 각 장치를 구분하며 mknod 명령으로 노드를 만들 수 있다.
- Devfs(디바이스 fs)는 /proc과 같은 가상 fs이기 때문에
디렉토리내 특별히 여러 노드를 만들지 않아도 된다.
보다 간단한 방법은 시스템의 /dev 디렉토리의 내용들을 복사한후 필요 없는 것들을 지운다.
이때 유념해야 할것은 특수 디바이스 파일들을 복사해 올때는 -R 옵션을 써서 복사해야 한다
이렇게 해야 디렉토리가 복사될 때 파일들의 내용들은 복사되지 않게된다.
# cp -a /dev /mnt
# cp -dpR /dev /mnt
디스켓이 /mnt 에 마운트 되었다고 가정한 것이다.
-dp 심볼릭 링크가 복사될때 타겟파일들이 복사되는 것이 아니라 링크로서 복사되도록 해주며
원래의 파일 속성이 그대로 유지된 채 복사되도록 한다. (파일 소유권을 그대로 유지)
어려운 방법으로 해보고 싶다면 ls -l 로 원하는 디바이스의 메이저와 마이너 디바이스 넘버를
출력해서 확인한 후 mknod 명령을 써서 직접 만들어 주는 방법도 있다.
디바이스들을 복사했으면, 원하는 특수 디바이스들이 복구디스켓에 제대로 들어갔는지 확인한다
각각의 특수 디바이스 파일은 하나씩의 inode 를 필요로 하기 때문에, 경우에 따라서는
inode 가 부족 할 수 있다. 따라서 필요없는 디바이스 파일들은 디스켓에서 제거하자.
SCSI 를 가지고 있지 않다면 sd로 시작하는 모든 디바이스 파일들은 삭제해도 무방하고,
시리얼 포트를 사용할 일이 없다면 cua 로 시작하는 파일들은 지워도 된다
/dev 디렉토리에 다음 화일들은 반드시 있어야 한다
console, kmem, mem, null, ram, tty1
#####
##### /etc ###
/etc 디렉토리에는 설정파일들이 위치한다.
대부분의 시스템에 있어 설정파일들은 다음 세가지 정도로 분류할 수 있다.
1. 어떤 경우든 반드시 필요한 파일 rc, fstab, passwd 등
2. 꼭 그런 것은 아니나 대체로 필요하다고 생각되는 파일들
3. 그외의 파일들
# ls -ltru /etc
마지막으로 액세스된 시간순으로 파일들을 출력하여 필수적인 파일인지 아닌지 확인해보자
최근 액세스된 적이 없는 파일들은 루트디스켓에서 제외시켜도 된다.
필자의 루트디스켓에는 약 15 개 정도의 설정파일이 있고, 용도에 따라 세가로 나누어 보겠다.
1. 시스템을 설정하는데 꼭 필요한 설정파일들
rc.d/* 시스템 기동 및 런레벨 변환 스크립트
fstab 마운트되는 fs의 리스트
inittab init 프로세스에 대한 파라메터들이 담겨있다.
2. 시스템 정돈에 필요한 설정파일들
passwd 사용자, 홈 디렉토리 등등의 리스트. passwd 는 적어도 root 를 포함하고 있어야 한다.
group 사용자 그룹
shadow 사용자들의 패스워드. 없을 수도 있다.
termcap 터미널의 능력에 대한 db
주로 사용하는 터미널인 linux-console 엔트리만 남기고 나머지는 삭제하라.
보안이 중요한 경우 사용자 패스워드가 시스템을 떠나 존재하지 않도록
passwd 와 shadow 는 디스켓으로 복사해오지 않는 것이 좋다.
이렇게 해두면 디스켓으로 부팅시 원치않는 사용자의 로그인을 막을수 있다.
다른 사용자들도 로그인할수 있게 하려면 그사용자의 홈 디렉토리와 쉘을 만들어 주어야 한다.
3. 그 밖의 설정파일들
필자는 이 중에서 두 가지 파일만큼은 반드시 설정해주는데 그 내용은 무척이나 간단하다.
- rc 에는 다음과 비슷한 내용이 반드시 들어있어야 한다. 디렉토리가 맞는지 확인하라.
#!/bin/sh
echo Root device system read/write mount
/sbin/mount -w -n -o remount /
echo fstab mount
/bin/mount -av
echo Set Hostname to acsecret
/bin/hostname acsecret
/bin/login
- fstab 에는 최소한 다음 내용은 들어있어야 한다.
/dev/ram0 / ext2 defaults
/dev/fd0 / ext2 defaults
/proc /proc proc defaults
현재 사용하고 있는 fstab 의 엔트리를 복사해도 된다.
하드디스크 피티션을 자동으로 마운트하게 해서는 안된다. (noauto 키워드를 쓰라)
하드디스크가 손상되었거나 죽어버려서 부트 디스크를 사용해야할 경우도 있기 때문이다.
- inittab 의 sysinit 라인은 rc 나 기본적인 부트 스크립트를 구동시킬수 있도록 수정하라
시리얼 포트쪽으로 사용자가 접속하는 것을 막으려면 getty 설정 엔트리중 라인 끝부분에 ttys 나
ttyS 디바이스가 적힌 엔트리들은 주석처리 해야한다. 단, 콘솔로 로그인할 tty 포트들은 남겨두자.
id:2:initdefault:
si::sysinit:/etc/rc
1:2345:respawn:/sbin/getty 9600 tty1
2:23:respawn:/sbin/getty 9600 tty2
세심하게 체크해야할 것은 inittab 에서 언급된 화일들이 정말로 제자리에 있는지의 여부다.
만일 init 가 해당 파일을 찾지 못하면 멈춰버리게 되며 에러 메시지조차 뜨지 않을수도 있다.
어떤 프로그램들은 다른 위치에 있는 것이 허용되지 않고 정해진 디렉토리에 위치해야 한다.
이는 프로그램들이 이 프로그램이 이곳에 위치할 것이라고 간주하여 코딩되었기 때문이다.
예를들어 필자의 시스템은, /etc/shutdown 은 reboot 의 위치를 /etc/reboot 라고 간주하여
코딩되었다. 만일 필자가 reboot 파일을 /bin/reboot 에 둔 후 shutdown 명령을 내린다면,
/etc 디렉토리에서 reboot 파일을 찾을 수 없으므로 shutdown 명령은 실패할 것이다
가장 확실한 방법은 inittab 에서부터 시작해서 필요한 것들을 하나하나 확인해 나가는 방법 뿐이다.
대부분의 시스템들은 각각의 런레벨에 해당하는 쉘 스크립트들을 /etc/rc.d/ 밑에 두고 있다.
가장 단순하게 하려면 rc 스크립트 하나면 되지만, 본래 시스템으로부터 inittab와 /etc/rc.d 를
통째로 복사한 후 디스켓에 필요없는 스크립트들을 지워나가는 방법이 보다 편리할 것이다.
- 기타
/etc/nsswitch.conf
/etc/mtab
/etc/profile
~/.bashrc
#####
##### /lib ###
시스템에 있어서 가장 중요한 glibc(C 라이브러리)를 포함하여 모든 라이브러리 파일이 위치하는 곳이다.
어떠한 리눅스 명령어도 glibc가 없다면 실행될 수 없다.(static으로 컴파일된것 제외.)
/lib 에는 필요한 공유 라이브러리들과 로더들을 두어야 한다.
필요한 라이브러리들이 /lib 디렉토리에서 발견되지 않는다면 시스템은 부트에 실패하게 된다.
커널이 필요한 라이브러리를 로드하지 못하면 대부분의 경우 에러메시지조차 없이 그냥 멈추어 버린다.
일부 라이브러리들은 상당히 커서 당신의 루트 fs에 쉽사리 들어가지 않을 수 있음에 주의.
이런 라이브러리들을 루트 fs으로 옮기려면 스트립(strip) 시킬 필요가 있다.
(사용법은 루트fs의 크기를 줄이기 절을 참조)
# ls -l /lib/libc.so*
-rwxr-xr-x 1 root root 4016683 Apr 16 18:48 libc-2.1.1.so*
lrwxrwxrwx 1 root root 13 Apr 10 12:25 libc.so.6 -> libc-2.1.1.so*
거의 모든 프로그램들이 적어도 libc 라이브러리인 libc.so.N 만큼은 반드시 필요로 한다.
여기서 N은 현재의 버전넘버를 뜻한다. (당신의 /lib 디렉토리를 확인)
보통, libc.so.N 은 완전한 버전넘버를 가진 파일이름에 심볼릭 링크되어 있다.
# ldd /sbin/mke2fs
libext2fs.so.2 => /lib/libext2fs.so.2 (0x40014000)
libcom_err.so.2 => /lib/libcom_err.so.2 (0x40026000)
libuuid.so.1 => /lib/libuuid.so.1 (0x40028000)
libc.so.6 => /lib/libc.so.6 (0x4002c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
포함시키려고 하는 바이너리들이 어떤 라이브러리들을 필요로 하고 있는지
의존성을 검사해 보려면 ldd 명령어를 사용하라. (ldd는 libc-2.1.1.so 가 필요하다)
오른편의 각 파일들이 필요함을 알 수 있다. 출력된 라이브러리들은 심볼릭 링크일수 있다.
최근 버전의 ldd 는 정확히 어떤 로더가 필요한지를 가르쳐 주지만 옛날 버전은 그렇지 않다.
/lib 에는 라이브러리용의 로더를 포함시켜야 한다.
/lib/ld.so (a.out 라이브러리용)이나 /lib/ld-linux.so (ELF 라이브러리용)일 것이다.
# file /lib/libc.so.4.7.2 /lib/libc.so.5.4.33 /lib/libc-2.1.1.so
/lib/libc.so.4.7.2: Linux/i386 demand-paged executable (QMAGIC), stripped
/lib/libc.so.5.4.33: ELF 32-bit LSB shared object, Intel 80386, version 1, stripped
/lib/libc-2.1.1.so: ELF 32-bit LSB shared object, Intel 80386, version 1, not stripped
어떤 로더가 필요한지 자신이 없다면 라이브러리에 대해 file 명령을 실행하자.
QMAGIC 은 4.7.2 가 a.out 라이브러리용이고,
ELF 는 5.4.33 과 2.1.1 이 ELF 라이브 러리용임을 나타내고 있다.
만들고자 하는 루트 fs에 필요한 로더들을 골라 복사하라.
라이브러리와 로더들이 과연 바이너리에 맞는 것인지 주의깊게 체크 해야한다.
# cp /etc/ld.so.conf rootsampledir/etc
# cd rootsampledir
# chroot ./ /sbin/ldconfig ::: or # chroot /mnt /sbin/ldconfig
# ldconfig
ld.so.cache 를 리메이크 한다.
마지막으로, 필요한 모든 라이브러리들을 설치했다면 ldconfig 를 실행시켜서 루트 fs 상의
/etc/ld.so.cache 를 리메이크 해주어라. 캐쉬는 로더에게 어디서 라이브러리를 찾을지를 지시한다.
ldconfig 는 언제나 루트 fs에 대해서만 캐쉬를 리메이크 하므로 반드시 chroot 명령이 필요하다.
그외
objcopy --strip-debug /lib/libc-2.2.so $MNT/lib/libc-2.2.so
objcopy --strip-debug /lib/libutil-2.2.so $MNT/lib/libutil-2.2.so
objcopy --strip-debug /lib/ld-2.2.so $MNT/lib/ld-2.2.so
objcopy --strip-debug /lib/libtermcap.so.2.0.8 $MNT/lib/libtermcap.so.2.0.8
objcopy --strip-debug /lib/libcrypt-2.2.so $MNT/lib/libcrypt-2.2.so
objcopy --strip-debug /lib/libdl-2.2.so $MNT/lib/libdl-2.2.so
objcopy --strip-debug /lib/libnss_files-2.2.so $MNT/lib/libnss_files-2.2.so
objcopy --strip-debug /lib/libpam.so.0.72 $MNT/lib/libpam.so.0.72
objcopy --strip-debug /lib/libpam_misc.so.0.72 $MNT/lib/libpam_misc.so.0.72
objcopy --strip-debug /lib/security/pam_permit.so $MNT/lib/security/pam_permit.so
#####
##### /bin 과 /sbin ###
/bin 은 기본적인 작업에 필요한 ls, mv, cat, dd 등의 유틸리티들을 두기에 편리한 곳이다.
cpio, tar, gzip 등과 같은 백업에 필요한 유틸리티들은 포함시키지 않았다.
유틸리티들은 boot/root 디스켓의 용량을 아끼기 위해 따로 유틸리티 디스크에 넣어두자.
일단 boot/root 디스켓이 부팅이 되어 램디스크로 로딩되고나면,
유틸리티 디스켓으로 바꿔넣은 후 마운트 할수있다. (보통 /usr 에 마운트한다)
백업을 할 때에는 백업본 외에도 백업을 만드는데 사용된 백업 유틸리티들 역시 동일 버전으로 복사하라
다음 프로그램들이 포함되었는지 확인
init, getty 류의 프로그램, login, mount, rc 스크립트를 실행시킬 수 있는 쉘 프로그램
쉘을 sh 에 링크시켰는지도 확인
#####
##### 마지막 세부사항 ###
# mkdir -p /mnt/var/{log,run}
# touch /mnt/var/run/utmp
login 같은 시스템 프로그램들은 /var/run/utmp 와 /var/log/ 가 없는 경우 문제를 일으킬 수 있다.
# umount /mnt
만들어진 fs을 포장하기
# dd if=DEVICE bs=1k | gzip -v9 > rootfs.gz
일단 루트 fs을 다 만들었다면 언마운트시키고 파일로 카피한 다음 압축시켜야 합니다.
이 과정이 끝나면 rootfs.gz 라는 파일을 얻게 될텐데 바로 이것이 당신의 압축 루트 fs다.
그 크기를 확인해서 과연 한 장의 플로피 디스켓에 다 들어가는지를 체크해야만 한다
만일 다 들어가지 않는다면 되돌아가서 몇 가지 파일들을 지워야 한다.
루트 fs을 첫번째 디스켓에 담을때 (boot+root)
# dd if=rootfs.gz of=/dev/fd0 bs=1k seek=KERNEL_BLOCKS
루트 fs을 두번째 디스켓에 담을때
# dd if=rootfs.gz of=/dev/fd0 bs=1k
##############################
##############################
other
#####
##### rootdisk - 램디스크 사용하지 않음 ###
루트 fs의 제작 편에서는 시스템 부팅과 동시에 램디스크로 로드되는 압축 루트fs을 만드는 법을 설명했다.
이 방법이 많은 장점이 있어 주로 사용되지만 메모리가 부족한 일부 시스템은 설치된 램이 램디스크를
만들만한 용량도 못되는 수가 있으므로 이때는 디스켓 상에서 직접 마운트되는 루트fs을 만들어야만 한다.
이러한 fs은 다른 디바이스가 아닌 디스켓 위에 그대로 만들고 압축도 필요없기 때문에 압축 루트 fs을
만드는 것보다 쉽다. 위에서 우리가 배운 절차와는 조금 다르므로 그 개요를 적어보겠다.
이 방법을 택하면 사용할 수 있는 공간이 훨씬 적어진다는 사실을 잊지말라.
1. 루트파일들에 할당할 수 있는 공간이 얼마나 되는지 계산한다. 만일 한장짜리 boot/root 디스크를
만든다면 커널의 블록과 루트 fs의 블록을 더한 값을 디스켓 한 장의 용량에 맞추어야 한다.
2. mke2fs 를 써서 디스켓 위에 적절한 크기의 루트 fs을 만든다.
3. 앞에서 배운 대로 fs을 구성한다.
4. 다 되었으면 fs을 언마운트 시키고 디스크 파일로 만든다. 단, 압축시키지 말라.
5. 앞에서 배운대로 커널을 플로피 디스켓에 담는다. 램디스크 워드를 계산할 때는 비트 14 를 0으로 설정한다.
이는 루트 fs이 램디스크로 로드되지 않도록 하는 것이다. 앞에서 배운 대로 rdev 를 실행한다.
6. 만일 두장의 디스크 세트를 만든다면 직접 두번째 디스크 상에 루트 fs을 만들면 된다.
또한 한장짜리 boot/root 디스크를 만들면서 LILO를 사용하겠다면 한장의 디스켓에 커널, LILO 파일,
루트파일 셋이 모두 들어있는 단일한 fs을 만든 후, 마지막에 LILO 만 실행시키면 된다.
#####
##### 유틸리티 디스크 만들기 ###
유틸리티 디스켓을 만드는 것은 포맷된 디스크에 fs을 만들고 파일들을 카피하면 된다.
부트디스켓에서 이 유틸리티 디스켓를 이용하려면 부트된 후 유틸리티 디스켓을 마운트하면 된다.
이 문서의 앞부분에서 유틸리티 디스켓를 /usr 디렉토리에 마운트할 수 있다고 했다. 이 경우
바이너리들은 유틸리티 디스켓 상에 존재하면서 /bin 디렉토리 아래에 위치하게 되는 것이다.
따라서 /usr/bin 을 PATH 에 포함시켜두면 이를 액세스 할 수 있다.
실행화일에 필요한 각종 라이브러리들은 유틸리티 디스켓의 /lib 디렉토리에 두면된다.
유틸리티 디스크 제작시 명심해야할 중요한 사항
1. 시스템 부트후 마운트될수 있기 때문에 핵심적인 시스템 바이너리나 라이브러리들은 디스크에 담지마라.
2. 플로피 디스켓과 플로피 테이프 드라이브를 동시에 엑세스할 수없다. 즉, 플로피 테이프 드라이브를
가지고 있다해도 유틸리티 디스켓이 마운트 되어있는 동안에는 이 테이프 드라이브를 액세스 할수없다
3. 유틸리티 디스켓에 있는 파일을 엑세스하는 속도는 상당히 느리다.
부록 유틸리티 디스크 견본은 유틸리티 디스크에 들어가는 파일들의 예를 보여준다.
도움되는 아이디어를 발견할 수 있을 것이다
디스크를 다루는 프로그램들(format, fdisk)과 fs용 프로그램들(tt/mke2fs, fsck, debugfs, isofs.o/),
간단한 텍스트 에디터 (elvis,jove), 압축및 아카이브 유틸리티(gzip, tar, cpio, afio),
테이프 유틸리티(mt,tob,taper), 통신 유틸리티(ppp.o, slip.o, minicom),
디바이스용 유틸리티(setserial, mknod) 등이 들어있다.
##############################
##############################
boot disk 만드는 여러 방법
#####
##### 라이브러리없이 static으로 구성 - grub 와 패포판 이미지 이용 ###
디렉토리구조는 데스크탑 리눅스의 축소판으로 구성하며 기본 리눅스 명령어는 busybox를 사용한다.
그리고 /dev 밑의 여러가지 노드는 커널의 Devfs로 간단히 해결하도록 하겠으며
부트 로더 GRUB도 포함하여 구성하도록 하겠다.
### boot image make ###
boot.img 다운받기
ftp://ftp.mizi.com/pub/mizios/2.0/i586/1st/images/boot.img
boot.img, bootnet.img, pcmcia.img 파일은 부트 이미지 파일인데 여기서는 특별히
한글화에 관련된 작업을 하지 않는다.
*** 루프백(loopback)으로 마운트 하기
여기서 우리가 필요한 파일 menu.lst, stage1, stage2를 제외하고 모두 삭제하도록 한다.
# mount -o loop boot.img /mnt/boot_image
# ls -l
루프백으로 마운트한후 파일 리스트를 보면 다음과 같다.
-rw-r--r-- 1 root root 710804 12월 17 17:46 initrd.img
-rw-r--r-- 1 root root 406 8월 29 2001 menu.lst
-rw-r--r-- 1 root root 974 8월 29 2001 menu.lst.all
-rw-r--r-- 1 root root 14505 8월 3 2001 mizios.msg.gz
-rw-r--r-- 1 root root 512 8월 3 2001 stage1
-rw-r--r-- 1 root root 132736 8월 3 2001 stage2
-rw-r--r-- 1 root root 570980 11월 1 2001 vmlinuz
initrd.img 압축된 ext2 fs 이미지 파일인데 압축을 풀고 루프백으로 마운트하여 내용을 수정한다.
# gzip -dc initrd.img > /tmp/initrd.ext2
# mount /tmp/inird.ext2 /mnt/iso3 -o loop
menu.lst GRUB 부트 로더의 config 파일로 커널이미지의 위치, root 디바이스의 위치 및
커널 파라메터 값을 셋팅할 수 있다. (LILO로 치자면 lilo.conf 에 해당한다.)
stage1 GRUB에 있어 필수적인 파일이며 부트 섹터나 MBR에 꼭 들어가야 하는 파일이다.
PC의 부트 섹터가 512Byte 인것처럼 stage1 역시 512Byte의 사이즈를 가진다.
stage2 GRUB 이미지 파일. (http://www.gnu.org/software/grub/ 참고)
*** 커널 이미지 만들기
[*] /dev file system support (EXPRIMENTAL)
<M> Loopback device support
menu.lst 수정하기
# vi menu.lst
timeout 10
color
default
title floppy-boot
root (fd0)
append = "devfs=mount" # 부팅시 devfs 사용을 위해
kernel /vmlinuz root=/dev/fd0 vga=0x307
# umount /tmp/boot_image
# dd if=boot.img of=/dev/fd0
부트 로더 GRUB으로 부팅 가능한 플로피 디스크 이미지를 만들때 stage1, stage2를 그냥
플로피 디스크에 카피한다고 하여 부팅 가능한 디스크가 되는것은 아니다.
부트 섹터 즉 최초 512Byte에 stage1 이 들어가야하고 그 뒤쪽 영역에 stage2가 들어가야지만
부팅 가능한 이미지가 된다.
이렇게 하여 첫번째 플로피 디스크의 구성은 끝이 났다. 이 디스켓으로 부팅한다면 부트 로더가 뜨고
카피한 커널 이미지가 로딩되어 부팅되기는 하겠으나 루트 fs이 없으므로 에러가 날것이다.
### root image make ###
Busybox
busybox를 카피한후 Config.h에서 정의해준 여러 명령어를 busybox에 심벌릭 링크 해준다.
(이렇게 링크된 명령어는 마치 busybox의 인자값처럼 동작하게 된다.)
busybox는 busybox란 바이너리 파일 하나로 구성되어 있지만 리눅스의 여러가지 utility를
포함하고 있으며 또한 사이즈가 아주 적어 루트 fs을 구성할때 많이 사용한다.
우선 루트 fs의 뿌리가 되는 busybox를 만들어 보자. (http://busybox.lineo.com을 참고)
# wget http://www.busybox.net/downloads/busybox-0.60.3.tar.gz
# vi Config.h
/* vi: set sw=4 ts=4: */
//#define BB_AR
#define BB_ASH
#define BB_BASENAME
#define BB_CAT
...
Config.h는 busybox가 포함할 여러 utility를 설정해주는 설정 파일로 각 명령어가
#define 되어있는데 필요한 명령어의 주석을 제거해주면 그 명령어를 사용할 수 있다.
자신만의 busybox를 만들어도 상관없지만
shell인 BB_ASH 관련 설정과 init인 BB_INIT와 mount등 필수적인 기본 명령어는 꼭 포함하자
# vi Makefile
PROG := busybox
VERSION := 0.60.3
BUILDTIME := $(shell TZ=UTC date -u "+%Y.%m.%d-%H:%M%z")
# If you want a static binary, turn this on.
#DOSTATIC = # 주석처리
DOSTATIC = true # 이 부분을 수정
컴파일은 간단하게 make라는 명령으로 끝나지만 우리는 라이브러리를 사용하지 않으므로
static으로 컴파일해야한다.
그러기 위해 Makefile을 'DOSTATIC = true'로 수정한후 make 명령으로 컴파일 하자.
-lnss_dns이나 -lnss_files 관련 에러로 컴파일이 되지 않는다면 다음 두 부분을 수정하고 컴파일 하라.
#LIBRARIES = -lc -lresolv -lnss_dns -lnss_files # 주석처리
LIBRARIES = -lc -lresolv # 이 부분을 수정
# dd if=/dev/zero of=root.img bs=1024 count=1440
플로피 디스크 1장 사이즈로 root.img란 제로 파일을 만든다.
# mke2fs -F root.img
root.img를 강제로 ext2 fs으로 만들자. 그렇지 않으면 fs이 없으므로 마운트 할 수가 없다.
# mount -o loop root.img /tmp/root_image
boot.img과 같은 방법으로 /tmp/root_image란 디렉토리를 만들고 루프백으로 마운트 한다.
아래와 같은 디렉토리를 만든다.
이 중에서 /dev, /proc, /tmp는 어떤 파일도 포함하지 않는 단지 이름뿐인 디렉토리이다.
bin/ dev/ etc/ proc/ sbin/ tmp/
/bin의 세부적인 파일은 다음과 같다.
'['를 test에 링크걸고 test을 busybox에 링크건 까닭은
shell 스크립트등에서 "if [ -e" 같은 구문을 사용하기 위해서이다.
# ls /bin
[ -> test*
basename -> busybox*
cat -> busybox*
chgrp -> busybox*
chmod -> busybox*
chown -> busybox*
clear -> busybox*
...
cp cut date dd df dmesg du echo env expr
false free grep gunzip gzip head hostname init
ln ls mkdir mknod more mount mv ping ps pwd
rm rmdir sed sh sleep sync tail telnet test true
umount uname uptime usleep vi
# ls /sbin
lrwxrwxrwx 1 root root 12 6월 15 18:30 halt -> /bin/busybox
lrwxrwxrwx 1 root root 12 6월 15 18:30 init -> /bin/busybox
lrwxrwxrwx 1 root root 12 6월 15 18:30 reboot -> /bin/busybox
# ls /etc
-rw-r--r-- 1 root root 137 6월 11 20:00 fstab
drwxr-xr-x 2 root root 1024 6월 15 17:13 init.d/
-rw-r--r-- 1 root root 0 5월 2 2001 mtab
# vi fstab
none /proc proc defaults 0 0
none /dev/pts devpts mode=0622 0 0
tmpfs /dev/shm tmpfs defaults 0 0
/dev/floppy/0 / ext2 defaults 1 1
# touch /etc/mtab
# vi /etc/init.d/rcS
#!/bin/sh
/bin/mount -a
#exec /etc/rc.local
busybox의 init 은 /etc/init/rcS를 디폴트 sysinit 스크립트로 사용한다.
# chmod 755 rcS
busybox의 init에서 이 rcS을 실행하기 때문에 꼭 실행권한이 있어야 한다.
# ./busybox
Usage: busybox [function] [arguments]...
Currently defined functions:
[, ash, basename, busybox, cat, chgrp, chmod, chown, clear, cp, date, df, dmesg,
du, echo, env, expr, false, free, grep, gunzip, gzip, halt, head, hostname, init, kill,
...
busybox를 그냥 실행해보면 Config.h에서 지정한 명령어를 확인 할 수 있다.
# ./busybox ls
busybox의 특정 명령어는 위와 같이도 실행 할 수도 있다.
# umount /tmp/root_image
#####
##### dd 유틸리티 이용해서 만들기 ###
dd 명령을 사용해서 부팅 디스켓을 만들때는 lilo 가 포함된 부팅 디스크와는 달리 리눅스가 설치되어있는
루트 파티션에 대한 정보가 올바른 형태로 저장되어 있어야 한다
rdev [장치화일명] 을 입력하면 현재 설정되어 있는 루트 파티션을 확인해 볼수 있는데 현재의 루트파티션이
lilo 가 설치되어있는 mbr 영역을 의미하는 /dev/hda1 이고 실제 리눅스 커널이 설치되어 있는 파티션이
/dev/hdb1이라면 rdev /dev/fd0 /dev/hdb1 을 실행해 루트파티션에대한 정보를 변경시켜야 한다
# dd if=/boot/vmlinuz-2.0.36-1kr of=/dev/fd0
단순히 커널 이미지만 디스켓으로 복사되기 때문에 lilo가 포함되지 않으며
컴퓨터로 부팅함과 동시에 lilo를 건너뛰고 바로 리눅스로 부팅 된다
# dd if=/cdrom/disks/rescue.img of=/dev/fd0 bs=72k
구조용 플로피 디스크를 생성. boot.img 를 이용한 부트 디스크로 부팅한후 rescue.img 로
복구용 디스크를 만든후 먼저 부팅 디스크로 부팅하고 boot: 프롬프트에서 rescue 를 입력한다
이어서 두번째 disk를 넣으라는 메시지가 나오면 삽입한다
# dd if=/mnt/cdrom/images/boot.img of=/dev/fd0 bs=72k
부팅용 디스크 작성
# dd if=/mnt/cdrom/images/supp.img of=/dev/fd0 bs=72k
설치용 디스크 작성
#####
##### rawrite 이용해서 만들기 ###
도스에서(리눅스 CD에 포함된) 디스크 생성방법
usage :
rawrate -f '이미지위치' -d '저장할 드라이브'
-f <path> 저장할 이미지의 위치
-d<drive> 저장할 드라이브 위치 A 또는 B 드라이브
-n 사용자가 디스크를 드라이브에 삽입을 기다리지 않고 실행
-h help
C:\> rawrite -f "L:\images\boot.img" -d "a:"
여러가지 이미지중 boot.img라는 부팅용 이미지 파일을 디스크로 옮긴다
C:\> rawrite
-f,-d 옵션을 이용해서 옮겨도 되고,
옵션없이 명령어를 입력한다음 순차적으로 요구하는것을 입력해도된다
Enter source file name: ..\images\supp.img ::: 설치용 디스크 작성
Enter destionation drive: a: ::: a 드라이브 선택
Please insert a formatted diskette into drive a: and press
-Enter-:
같은 방법으로 루트 디스크를 만든다
#####
##### Tomsrtbt 부트 디스크 만들기 ###
http://www.toms.net/~toehser/rb/
tomsrtbt 는 커널 2.0 기반의 한장짜리 boot/root 디스크다.
IDE, SCSI, 테이프, 네트웍 어댑터, PCMCIA 기타 여러가지를 지원한다.
디스크 복구 및 수리에 관련된 약 100 개 이상의 유틸리티와 툴이 포함되어 있다.
이미지를 풀어 재구축 할수있는 스크립트가 포함되어 있으므로 필요하면 새로운 것을 첨가할 수 있다.
John Comyns 씨가 제작한 rescue02 는 커널 1.3.84 기반의 복구 디스크이다. IDE, 아답텍 1542, NCR53C7,
8xx 를 지원한다. ELF 바이너리를 사용하지만 충분한 명령어들을 가지고 있으므로 어떤 시스템에도
사용할 수 있다. 부팅 후에는 그밖의 SCSI 카드들에 대한 모듈도 로드할수 있다. 이 디스크는 3 메가의
램디스크를 사용하므로 4 mb 의 램을 가진 시스템에서는 쓸수 없다.
Sergei Viznyuk 씨가 제작한 resque_disk-2.0.22 는 본격적인 boot/root 디스크로서 커널 2.0.22 를
기반으로 한다. IDE, 다양한 SCSI 컨트롤러들, ELF/A.OUT 에 대한 지원을 커널에 내장하고 있다. 또한
많은 모듈들과 하드디스크의 수리와 복구에 유용한 많은 유틸리티들을 가지고 있다.
커널 2.0.23 에 기반한 cramdisk 이미지들은 4 MB 나 8 MB 머신에서 사용가능하다. math emulation,
네트워킹(PPP 와 다이얼링 스크립트, NE2000, 3C509), 병렬포트 ZIP 드라이브 등에 대한 지원을 포함하고
이 디스켓 이미지들은 4 MB 이상의 램을 가진 386 에서 사용가능하다.
MSDOS 지원이 포함 되어 있으므로 도스파티션으로 다운받을 수 있다.
http://metalab.unc.edu/pub/Linux/system/recovery/images
#####
##### mkbootdisk 스크립트 ###
usage : mkbootdisk --device /dev/fd0 --verbose [커널버전]
- mkbootdisk는 부트 이미지를 만들어주는 스크립트이다 이것은 쉘스크립트 화일인데 명령 실행시
의존성 에러가 생기면 해당 패키지를 설치해야 한다
- /lib/modules 디렉토리에 [커널번호] 에 해당하는 커널 모듈 디렉토리가 있어야 이미지가 만들어진다
# cd /boot
# ln /boot/bzImage-2.4.4 /boot/vmlinuz-2.4.4
bzImage(예, bzImage-2.4.4)로서 커널을 컴파일 한다면, vmlinuz-2.4.4에 대한 하드 링크(hard link)를
생성하여야만 한다 (vmlinuz 명칭에서 z를 주의하라. vmlinux가 아니다)
이것을 제대로 하지 못하면, mkbootdisk 명령은 실패할 것이다
# ls -d /lib/modules/2.0.*
/lib/modules/2.0.36-1kr
# mkbootdisk --device /dev/fd0 2.0.36-1kr
실제 모듈 버젼이 2.0.36 이라해도 /lib/modules 에있는 정확한 이름인 2.l.36-kr 을 사용해야한다
#####
##### boot cd 제작 ###
점검사항
mkbootdisk ::: 부트 이미지를 만들어주는 스크립트
mkisofs
루트 권한으로
# mkbootdisk --device ./linux-bootcd.img 2.4.2-xx
linux-bootcd.img 는 부트 이미지를 저장할 화일 이름이다.
플로피에 직접 쓰는 경우 화일 이름 대신 디바이스 화일 이름을 사용한다.
# mkdir temp
# cd temp
# cp some_path/linux-bootcd.img ./
만들어질 시디의 최상위 디렉토리와 같은 의미가 되는 임시 디렉토리를 만들고 linux-bootcd.img 화일을
복사해 넣어둔다. 그 외에 자기가 복사해두고 싶은 파일들을 잔뜩 복사한다
# mkisofs -r -b linux-bootcd.img -c boot.catalog -o bootcd.iso .
iso 이미지 화일을 만든다 반드시 temp 디렉토리에서 위처럼 한다
-b 부트 이미지의 이름
-c 부트 카달로그 파일 이름 (규약상 필요한 것이고 무조건 이렇게 해야 부팅 시디가 만들어진다
boot.catalog 라는 파일을 손으로 만들 필요는 없다)
-o 만들어질 iso 이미지 파일 이름
-r 화일 퍼미션, 소유권등을 적절히 바꾸라는 옵션.
마지막에 "."을 빠뜨리면 안되고, 파일패스는 만들어질 시디롬의 루트 디렉토리를 기준으로 써야한다
만들어진 이미지를 각자 좋아하는 프로그램으로 시디를 굽는다
##############################
##############################
etc
*** 복구 패키지들
배포본 부트 디스크 외에도 다음의 복구 디스크 이미지들을 쓸 수도 있다.
metalab.unc.edu 에 복구디스크를 만드는 패키지가 있다. 이 패키지들을 쓸 경우, 포함 시키고자 하는
파일들을 지정해 주기만 하면 소프트웨어가 어느정도 자동적으로 부트 디스크를 만든다.
(http://metalab.unc.edu/pub/Linux/system/ 참고) recovery/!INDEX.html 파일의 날짜를 체크하라.
패키지들 중 몇몇은 지난 수년간 갱신되지 않았기 때문에 램디스크로 로딩되는 압축 루트 fs 제작을
지원하지 않는다. (현재까지 Yard 패키지만이 지원한다.)
*** 리눅스 부트 프로세스
리눅스 부트 프로세스에 관한 보다 자세한 사항은 다음을 참고
- "리눅스 시스템 관리자 가이드" 에 부팅에 관한 절이 있다. (http://linuxdoc.org/LDP/sag/c1596.html)
- LILO "Technical overview" http://metalab.unc.edu/pub/Linux/system/boot/lilo/lilo-t-21.ps.gz
에는 부트 프로세스에서부터 커널이 시작되는 단계까지에 관한 기술적인 사항 및 저수준 에서의
동작에 관한 중요한 설명이 있다.
소스코드야 말로 궁극적인 안내서다. 아래의 파일들은 부트프로세스와 관련된 몇가지 커널 파일이다.
리눅스 커널 소스 코드를 가지고 있면 /usr/src/linux 아래에 있을 것이다.
다른 방법으로는, Shigio Yamaguchi (shigio@tamacom.com) 씨가 다음 홈페이지에서 아주 훌륭한
하이퍼텍스트 커널 브라우저를 제공하고 있다. http://www.tamacom.com/tour/linux/index.html
다음은 관련 파일들이다.
arch/i386/boot/bootsect.S,setup.S
부트섹터에 해당되는 어셈블리 코드가 있다.
arch/i386/boot/compressed/misc.c
커널의 압축을 해제하는 코드가 있다.
arch/i386/kernel/
커널을 초기화시키는 코드가 이 디렉토리에 들어있다. setup.c 에 램디스크 워드가 있다.
drivers/block/rd.c
램디스크 드라이버가 있다. rd_load 와 rd_load_image 프로시저가 디바이스에서
램디스크로 데이터 블록들을 로드한다. identify_ramdisk_image 프로시저는 어떤 종류의
fs이 발견되었는지, 또 그것이 압축된 상태인지 아닌지를 판별한다.
#####
##### 애로사항과 문제해결 ###
부트 디스크를 만들 때 단번에 성공하는 일을 거의 없다. 루트디스크를 만드는 일반적인 접근방법은
현재 시스템 으로부터 필요한 요소들을 끌어모아 조립한 디스켓 기반의 시스템을 가지고 시행착오를 거쳐
콘솔 상에 어떤 메시지가 나타나는 단계에까지 진입하는 것이다.
이 단계까지오면 출력된 메시지를 보고 무엇이 문제인지를 파악해 나갈 수 있으므로 시스템이 원활히
동작할 때까지 각각의 개별적 문제들을 해결해 나가기만 하면 된다.
시스템이 아무런 메시지 없이 그냥 멈추어 버린 경우라면 그 원인을 찾는 것은 어려운 일이다.
시스템이 부트되어 어떤 메시지를 보낼수 있는 단계까지 왔다는 말은 몇 가지 구성요소들은 동작하고 있으며
거기까지는 제대로 설정이 되었다는 말이된다.
만일 시스템이 아무런 메시지를 남기지 않고 멈추어 버렸다면 아래의 순서대로 원인을 조사하자
### 다음과 같은 메시지가 나온 경우 ###
Kernel panic: VFS: Unable to mount root fs on XX:YY
이는 흔히 발생하는 문제이며 이유는 몇가지 밖에 없다.
디바이스 XX:YY 가 디바이스 코드의 리스트에 있는지 체크하자. 그것이 올바른 루트 디바이스인가?
아니라면 원인은 틀림없이 rdev -R 을 실행하지 않았거나 잘못된 이미지에 대해 rdev 명령을 내린 것이다.
디바이스 코드가 올바르다면 커널내에 컴파일 되어있는 디바이스 드라이버들을 주의깊게 체크하라
- 루트 fs의 /lib/libc.so 의 링크가 하드디스크의 /lib 디렉토리에 있는 링크와 같은지 확인.
- 루트디스크에 정말로 당신이 생각했던 디렉토리들이 포함되어 있는지 확인.
루트디스켓 fs의 /dev 디렉토리의 심볼릭 링크가 당신 시스템의 그것과 동일한지 확인.
- /dev/tty1, /dev/null, /dev/zero, /dev/mem, /dev/ram, /dev/kmem 이 포함되었는지 확인.
특히 /dev/console 링크는 대부분의 경우 반드시 있어야 한다.
- 커널 설정을 확인. 로그인 단계에 다다를 때까지 필요한 자원에 대한 지원은 커널에 내장 되어야 한다.
따라서 램디스크와 ext2 에 대한 지원은 반드시 커널에 내장되어야 한다.
커널 루트 디바이스와 램디스크 설정이 올바른지 확인.
일단 위의 일반적인 사항들을 확인했다면 이제 보다 구체적인 파일들을 확인한다.
1. init 가 /sbin/init 혹은 /bin/init 로 제대로 포함되어 실행가능한 상태인지 확인.
2. ldd init 해서 init 의 라이브러리들을 체크. 보통 이것은 libc.so 가 되지만 다시 확인.
필요한 라이브러리와 로더들을 포함시켰는지 확인.
3. 각 라이브러리들에 대해 그에 해당하는 알맞은 로더를 가지고 있는지를 확인.
a.out 에는 ld.so 가 있어야 하고 ELF 에는 ld-linux.so 가 있어야 한다.
4.- 부트 디스크 fs에 있는 /etc/inittab 파일을 열어 getty를 호출하는 부분을 체크.
(혹은 agetty, mgetty, getty_ps 등의 이른바 getty 류 프로그램)
이 부분을 하드 디스크의 inittab 과 비교하면서 되풀이 하여 확인.
- 당신이 사용하는 프로그램의 맨 페이지를 펼쳐놓고 과연 제대로 설정되었는지 확인
- /etc/inittab 가 시스템 초기화 엔트리를 가지고 있는지 확인
이 파일에는 시스템 초기화 스크립트들을 수행시키는 명령어가 반드시 포함되어 있어야 한다.
- inittab 는 리눅스 시스템에서 가장 교묘한 부분이다. 그 이유는 init 의 문법과 내용은 사용되는
init 프로그램에 따라 서로 다르고, 또 각 시스템의 특성에 의존적이기 때문이다.
init 에 관한 문제를 다루는 유일한 방법은 init 와 inittab 에 대한 맨 페이지를 숙지한 후,
시스템이 부트될때 일어나는 과정들이 플로피 디스크 상에서도 똑같이 일어나도록 하는 것이다.
5. init 에 했던 것처럼 getty 에 대해서도 ldd 를 실행시켜서 getty 가 무엇을 필요로 하는지 확인하고
필요한 라이브러리와 로더들이 루트 fs에 들어있는지 확인.
6. rc 스크립트를 실행시키는 쉘 프로그램 (bash, ash 등)을 포함시켰는지 확인
7. 만일 복구디스켓에 /etc/ld.so.cache 파일을 포함시켰다면 그것을 리메이크한다.
### init 가 시작되기는 하는데 다음과 같은 메시지를 내는 경우 ###
Id xxx respawning too fast: disabled for 5 minutes
이것은 init 가 발생시킨 메시지로서 주로 getty 나 login 이 시작하자마자 죽어버렸음을 알리는 것이다.
getty와 login 이 의존하는 실행파일들과 라이브러리들을 확인하라.
/etc/inittab 내의 호출형식이 정확한지 확인.
만일 getty 로부터 이상한 메시지를 받았다면 /etc/inittab 내의 호출형식이 어딘가 틀렸을 것이다.
getty 프로그램들의 옵션은 다양하다. 버전별로 호출형식이 상이한 경우도 있다.
만일 로그인 프롬프트가 떴고 제대로 사용자 이름을 넣었는데도 시스템 프롬프트가 즉각 또다른 로그인
네임을 요구한다면, 아마도 PAM 이나 NSS 에 관련된 것이다. (PAM 과 NSS에 대한 대책절을 참고)
shadow password 를 사용하면서 /etc/shadow 를 부트 디스크로 복사해 넣지 않았기 때문일 수도있다.
### 복구 디스켓에 있는 df 등의 일부 실행파일을 실행했을때 다음과 비슷한 메시지를 받는 경우 ###
df: not found
- 그 바이너리가 위치한 디렉토리가 PATH 에 잡혀있는지 확인
- 그 프로그램이 필요로 하는 라이브러리와 로더를 포함시켰는지.
#####
##### 전문가들이 사용하는 방법 ###
슬랙웨어, 레드햇, 데비안 등의 주요한 배포본들에 사용되는 부트 디스크도 한번쯤 생각해 볼수 있다.
이런 것들은 이 문서에서 설명한 것보다 복잡하게 구성되어 있다.
전문적인 배포본의 부트 디스크들 역시 대체로 여기에서 설명한 원리에 기초하고 있지만,
그 외에도 그런 부트 디스크들은 다음의 기능들을 구비하기 위해 보다 다양한 기교를 사용한다.
첫째, 폭넓은 종류의 하드웨어를 지원해야 한다. 따라서 사용자의 입력을 받을수 있어야 하고
다양한 디바이스 드라이버들을 로드할수 있어야 한다.
둘째, 여러가지 많은 설치 옵션을 입력받아 각각을 자동적으로 처리할 수 있어야 한다.
셋째, 배포본의 부트 디스크들은 대개의 경우 설치기능과 응급조치의 기능을 함께 가지고 있다.
슬랙웨어(v.3.1)는 "디스켓에 LILO 와 커널을 함께 담기 부분" 에서 설명한 부트방식을 그대로 사용한다.
슬랙웨어의 부트 디스크는 LILO 의 메시지 파라메터를 이용하여 부트업 메시지
("Welcome tothe Slackware Linux bootkernel disk!")를 화면에 출력한다.
이 메시지는 사용자로 하여금 필요한 경우 부트 파라메터 라인을 입력토록 지시한다.
부팅 후 루트 fs은 두번째 디스크에서 로드된다.
이제 사용자는 초기화과정을 처리하는 셋업 스크립트를 가동시키게 됩니다.
모듈화된 커널을 쓰는 대신 슬랙웨어는 각각의 커널을 다양하게 준비해 두고
그 중에서 사용자가 자신의 하드웨어 사양에 맞는 것 하나를 골라쓰는 방법을 택하고 있다.
레드햇(v.4.0) 역시 LILO 부트를 이용한다.
레드햇은 압축된 루트디스크를 첫번째 디스크에 가지고 있으며 이것은 레드햇 특유의 init 프로그램을 기동시킨다.
이 프로그램은 드라이버를 물어본 후 필요한 경우 보충 디스크에서 추가적인 파일들을 로드하게 된다.
데비안(V.1.3) 은 설치디스크들 중에서 가장 복잡한 방법을 쓰고 있다.
이것은 SYSLINUX 로더를 써서 다양한 로드 옵션을 제공한 다음,
initrd 이미지를 사용해서 설치 과정동안 사용자를 안내한다.
데비안은 데비안 특유의 init 와 쉘을 사용하는 듯하다.
##############################
##############################
자주 받는 질문들 (FAQ : Frequently Asked Question)
Q. XYZ 드라이버를 포함한 부트 디스크를 만들려면?
가장 쉬운 방법은 가까운 슬랙웨어 미러 사이트에서 슬랙웨어 커널을 받는 것이다.
슬랙웨어 커널들은 가능한 한 많은 디바이스 드라이버들을 포함하는 포괄적인 커널들이므로 만일 SCSI 나
IDE 컨트롤러를 가지고 있다면 해당 드라이버가 슬랙웨어 커널에 있을 가능성이 높다.
a1 디렉토리에 가서 당신의 컨트롤러 타입에 맞는 IDE 나 SCSI 커널을 선택하라. 선택하신 커널에 대한
xxxxkern.cfg 파일을 보면 해당 드라이버가 그 커널에 들어있는지 확인할 수 있다. 원하는 디바이스가
리스트 안에 있다면, 그 커널은 당신 컴퓨터를 부팅시킬 수다. xxxxkern.tgz 파일을 다운받은 후
본 문서의 부트 디스크 제작에 관한 부분에 적힌 방법대로 부트 디스크로 복사하라
그 다음, rdev 명령을 써서 커널의 루트 디바이스를 체크해야 한다.
# rdev zImage
rdev 명령은 커널 내에 지정된 현재의 루트 디바이스가 무엇인지 출력한다.
만일 당신이 원하는 루트디바이스가 아니라면, rdev 명령을 써서 루트 디바이스를 바꿔주어야 한다.
예를 들어 지금 다운받은 커널에는 /dev/sda2 가 루트 디바이스로 지정되어 있는데 정작
자신의 루트 디바이스는 /dev/sda8 이라는 SCSI 파티션이라고 하자.
루트디스켓을 사용하기 위해서는 다음 명령을 써야한다.
# rdev zImage /dev/fd0
Q. 부트디스켓의 커널을 새로운 커널로 갱신하려면 어떻게 해야 하나요?
fs이 없는 부트디스켓의 경우는 dd 명령어를 써서 단순히 부트디스켓에 커널을 복사하면 된다.
boot/root 디스크인 경우 cp 명령어를 사용한다.
Q. 루트디스켓의 파일들을 새로운 파일들로 갱신하려면 어떻게 해야 하나요?
가장 쉬운 방법은 루트디스크의 fs을 당신이 사용했던 DEVICE (fs의 제작에서 나왔다)에 역으로 복사한후,
그 fs을 마운트해서 필요한 부분을 갱신한다. 당신의 루트 fs이 어디서부터 시작했고 얼마만큼의 블록을
차지했는지를 반드시 기억해두어야 한다.
# dd if=/dev/fd0 bs=1k skip=ROOTBEGIN count=BLOCKS | gunzip > DEVICE
# mount -t ext2 DEVICE /mnt
갱신한 다음에는 만들어진 fs을 포장하기 부분에서 한것처럼 작업한 후, 루트 fs을 다시 디스크로 옮긴다.
이때, 새로운 루트 fs의 시작위치를 바꾸지 않았다면
커널을 다시 넣는다거나 램디스크 워드를 재계산해줄 필요는 없다.
Q. 커널과 부트 디스크를 모두 잃어버렸는데 부팅시킬 방법이 있을까요?
준비해놓은 부트 디스크가 없다면, 가장 쉬운 방법은 당신의 디스크 컨트롤러 타입(IDE 혹은 SCSI)에 맞는
슬랙웨어 커널을 구하는 것이다. 위의 "XYZ 드라이버를 포함한 부트 디스크를 만들려면?" 답변에서 설명했다.
그렇게 구한 커널을 써서 컴퓨터를 부트시킨 후 손상된 부분을 고치시기 바랍니다.
구한 커널의 루트 디바이스 세팅이 원하시는 디스크 타입과 파티션으로 설정되어있지 않았을 수 있다.
슬랙웨어에서는 일반적으로 커널의 SCSI 루트 디바이스가 /dev/sda2 로 잡혀있는데 필자의 리눅스의
루트파티션은 /dev/sda8 로 되어있다면, 이 경우 커널내의 루트 디바이스 설정을 수정해야 한다.
심지어는 당신이 가진 것이 달랑 커널 하나와 DOS 나 그 외 다른 운영체제뿐이라고 하더라도 그걸로도
커널내의 루트 디바이스와 램디스크 설정을 바꿀수 있다.
rdev 명령은 커널파일내에 고정되어있는 오프셋의 값을 바꿔줌으로써 커널의 세팅을 바꾸는 것이다.
따라서 현재 어떤 시스템을 갖고 있든지 간에 hex 에디터만 있다면 rdev 와 똑같은 일을 해낼 수 있다.
한 예로 DOS 의 노턴 유틸리티 디스크에디터를 사용할 수도 있다.
에디터를 써서 커널내의 다음 값들을 체크하고 필요하다면 이를 수정하면된다.
HEX DEC DESCRIPTION
0x01F8 504 Low byte of RAMDISK word
0x01F9 505 High byte of RAMDISK word
0x01FC 508 Root minor device number - see below
0X01FD 509 Root major device number - see below
램디스크 워드의 해석은 램디스크 워드의 설정 부분에 나와 있다.
메이저, 마이너 디바이스 넘버들은 루트 fs이 마운트되는 디바이스로 설정되어야 한다.
쓸만한 값들은 다음과 같다.
DEVICE MAJOR MINOR
/dev/fd0 2 0 1st floppy drive
/dev/hda1 3 1 partition 1 on 1st IDE drive
/dev/sda1 8 1 partition 1 on 1st SCSI drive
/dev/sda8 8 8 partition 8 on 1st SCSI drive
일단 이 값들을 설정했다면 이제 노턴 유틸리티 디스크 에디터나 rawrite.exe 같은 프로그램을 써서
파일을 디스켓 상에 써넣어야 한다. 이것은 도스 프로그램으로서 어떤 파일을 fs 내에 쓰는 것이 아니라
부트섹터부터 그대로(raw 하게) 디스크로 써넣어 버리는 프로그램이다.
노턴 유틸리티를 사용하신다면 파일을 물리적인 디스크의 첫부분에 서부터 그대로 써넣어야 한다.
Q. boot/root 디스켓의 복사본을 만들려면?
자성 매체는 시간이 지남에 따라 그 자기적 특성이 저하되기 때문에,
원본을 읽을 수 없게 될 경우에 대비해 복구용 디스켓을 여벌로 가지고 있는 것이 좋다.
디스켓의 복사본을 만드는 가장 손쉬운 방법은 dd 명령으로 원본디스켓의 내용을 하드디스크의
파일로 복사해 온 후, 같은 명령으로 그 파일을 새로운 디스켓에 복사해 넣는 것이다.
dd 명령은 raw device 인터페이스를 사용하기 때문에 디스켓을 마운트해서도 안된다.
원본을 복사하기 위해서는 다음과 같은 명령을 사용한다.
# dd if=DEVICENAME of=FILENAME
DEVICENAME 은 디스켓 드라이브의 디바이스 이름, FILENAME 은 생성되는 파일의 이름이다.
dd 명령에서 count 파라메터를 생략하면 디스크 전체(고밀도 = 2880 블록)를 복사하게 된다.
# dd if=FILENAME of=DEVICENAME
얻어낸 파일을 새로운 디스켓으로 복사하려면 새 디스켓을 넣고 명령을 반대로 내린다.
Q. 매번 부트할 때마다 "ahaxxxx=nn,nn,nn" 식으로 입력하지 않고 부트할 수는 없나요?
디스크 디바이스가 자동으로 감지되지 않는다면 커널에 디바이스 파라메터 문자열을 써 주어야 한다.
aha152x=0x340,11,3,1
LILO 사용시 이 파라메터 문자열을 전달하는 몇 가지 방법이 있다.
- 시스템이 LILO 를 통해 부트될 때마다 명령어 라인에 문자열을 써주는 방법.
- LILO 의 "lock" 키워드를 써서 원하는 명령어 라인을 디폴트로 저장시키는 방법.
이렇게 하면 LILO 는 부트 할 때마다 매번 이 옵션을 사용하게 된다.
- LILO 설정파일내에 append= 구문을 쓰는 방법. (파라메터 문자열은 반드시 인용부호로 감싸야 한다)
zImage aha152x=0x340,11,3,1 root=/dev/sda1 lock
파라메터 문자열을 사용한 명령어 라인 예
디바이스 파라메터 문자열을 넘겨주면서 동시에 커널로 하여금 루트 디바이스를 /dev/sda1 로
설정케 한 후, 명령어 라인 전체를 저장시켜 차후로 부트할 때마다 이를 사용한다.
APPEND = "aha152x=0x340,11,3,1"
APPEND 구문의 예.
파라메터 문자열은 명령어 라인에서는 절대로 인용부호를 써서는 안되며, 반대로 APPEND
구문에서는 반드시 인용부호를 같이 써야한다.
또, 파라메터 문자열대로 제대로 동작하게 하려면 커널은 반드시 그 디스크 타입에 해당하는
드라이버를 가지고 있어야한다. 만일 해당 드라이버를 가지고 있지 않다면 그 파라메터 문자열은
아무런 작용을 못하는 존재가 되므로 이럴때는 필요한 드라이버를 포함하는 커널을 다시 만들어
설치하거나 아니면 그 디스크 타입에 맞는 일반적인 커널을 구해 설치해도 된다.
lilo 의 BOOT 구문을 부주의하게 사용하면 파티션이 손상될 수 있다.
Q. 부트할 때 "A: cannot execute B" 라는 에러가 났습니다. 왜인가요?
어떤 프로그램의 이름이 다른 유틸리티 프로그램의 코드내에서 직점 코딩된 경우가 있다.
자주있는 것은 아니지만 이러한 경우는 실행파일이 분명히 존재하는데도 불구하고 특정 프로그램이
그 파일을 찾지 못하는가를 설명해줍니다. 특정 프로그램이 코드내에서 다른 파일의 이름을 사용하고
있는지 여부를 확인하려면 strings 명령을 쓴후 그 출력을 grep 으로 파이프 받아확인하면 된다.
이런 경우의 몇가지 예를 들어 보겠습니다.
- 어떤 리눅스 버전에서의 shutdown 프로그램은 그 코드내에 /etc/reboot 라는 이름을 사용하고 있다.
따라서 이 경우 reboot 프로그램은 반드시 /etc 디렉토리 밑에 위치해야한다.
- 커널이 init 를 찾지 못해서 문제가 되는 경우도 있다.
이런 문제들을 해결하기 위해서는, 해당 프로그램을 올바른 디렉토리에 두거나 설정파일(inittab)들을
고쳐 올바른 디렉토리를 가리키도록 해야한다. 아무래도 미심쩍다면 하드디스크의 환경과 동일한 환경을
만들어 주라 (하드디스크와 동일한 디렉토리에 두고, inittab, /etc/rc.d 도 하드와 동일한 파일을 사용)
Q. 제 커널은 램디스크를 지원합니다만 램디스크를 0K 로 초기화시켜 버립니다.
이런 일이 발생하면 부팅시에 다음과 같은 커널 메시지가 뜹니다.
Ramdisk driver initialized : 16 ramdisks of 0K size
이는 틀림없이 부트시에 커널 파라메터가 램디스크의 크기를 0 으로 세팅했기 때문이다.
아마도 LILO 설정파일의 파라메터가 ramdisk= 0 으로 설정되어있는 것을 간과했을 것이다.
일부 오래된 배포판에 포함된 LILO 설정의 샘플 파일에 이런 옵션이 들어 있는 수가 있다.
만일 0K 로 설정되어있는 램디스크를 사용하려 한다면 그 결과는 예상할 수 없다.
이는 커널 패닉으로 이어질 수도 있다. (위와 같은 라인이 있다면 삭제하라.)
##############################
##############################
루트 디스크 견본
Root directory:
bin dev etc lib mnt proc root sbin tmp usr var
/dev:
cdrom -> cdu31a cdu31a console cua0 cua1
cua2 cua3 fd0 fd0D1040 fd0D1120 fd0D360
fd0D720 fd0D800 fd0E2880 fd0E3200 fd0E3520
fd0E3840 fd0H1440 fd0H1600 fd0H1680 fd0H1722 fd0H1743
fd0H1760 fd0H1840 fd0H1920 fd0H360 -> fd0D360 fd0H720 -> fd0D720
fd0H820 fd0H830 fd0d360 fd0h1200 fd0h1440 fd0h1476 fd0h1494
fd0h1600 fd0h360 fd0h410 fd0h420 fd0h720 fd0h880
hda hda1 hda2 hda3 hda4 hda5 hda6
hdb hdb1 hdb2 hdb3 hdb4 hdb5 hdb6
kmem mem modem -> ../dev/ttyS1 mouse -> ../dev/psaux
null psaux ram ram0 ram1 ram2 ram3 ram4 ramdisk -> ram0
tty0 tty1 tty2 tty3 tty4 tty5 tty6 tty7 tty8 tty9 ttyS1
zero
/lib:
ld-2.0.7.so ld-linux.so.2 -> ld-2.0.7.so
libc-2.0.7.so libc.so.6 -> libc-2.0.7.so
libcom_err.so.2.0 libcom_err.so.2 -> libcom_err.so.2.0
libcrypt-2.0.7.so libcrypt.so.1 -> libcrypt-2.0.7.so
libdl-2.0.7.so libdl.so.2 -> libdl-2.0.7.so
libext2fs.so.2.4 libext2fs.so.2 -> libext2fs.so.2.4
libnsl-2.0.7.so libnsl.so.1 -> libnsl-2.0.7.so
libnss_files-2.0.7.so libnss_files.so.1 -> libnss_files-2.0.7.so
libpam.so.0.64 libpam.so.0 -> libpam.so.0.64
libpam_misc.so.0.64 libpam_misc.so.0 -> libpam_misc.so.0.64
libproc.so.1.2.6
libpwdb.so.0.54 libpwdb.so.0 -> libpwdb.so.0.54
libtermcap.so.2.0.8 libtermcap.so.2 -> libtermcap.so.2.0.8
libutil-2.0.7.so libutil.so.1 -> libutil-2.0.7.so
libuuid.so.1.1 libuuid.so.1 -> libuuid.so.1.1
modules
security
/lib/modules:
2.0.35
/lib/modules/2.0.35:
block cdrom
/lib/modules/2.0.35/block:
loop.o
/lib/modules/2.0.35/cdrom:
cdu31a.o
/lib/security:
pam_permit.so
/etc:
conf.modules fstab gettydefs group inittab issue ld.so.cache
motd nsswitch.conf pam.d passwd profile rc shells
termcap ttytype utmp -> ../var/run/utmp wtmp -> ../var/log/wtmp
/etc/pam.d:
other
/sbin:
fdisk fsck e2fsck fsck.ext2
mkfs mke2fs mkfs.ext2 mkswap
badblocks
swapoff -> swapon swapon
reboot -> halt shutdown halt init
insmod lsmod rmmod depmod modprobe
getty agetty ifconfig route probe dbflush
kerneld ldconfig
telinit -> init update
/bin:
sh -> ash ash bash false true
cut cat vi more
ls cp pwd rm date ln mv touch mkdir
grep egrep gzip gunzip zcat tar compress
ps dd df hostname login sync
ping rdev mount umount
su stty mknod e2fsck
chmod chown
/usr:
bin lib man sbin share tmp -> ../var/tmp
/usr/bin:
afio chroot cut diff du find free head id passwd tail tr wc whoami
/usr/lib:
libncurses.so.4 -> libncurses.so.4.2
libncurses.so.4.2
/usr/sbin:
fuser mklost+found
/usr/share:
terminfo
/usr/share/terminfo:
l
v
/usr/share/terminfo/l:
linux linux-m linux-nic
/usr/share/terminfo/v:
vt100 vt100-am
/var:
log run tmp
/var/log:
wtmp
/var/run:
utmp
/var/tmp:
/mnt:
cdrom floppy
/root:
.bashrc .cshrc .glintrc .profile .tcshrc
/proc:
/tmp:
#####
##### 유틸리티 디스크 견본 ###
cpio* debugfs* elvis* fdisk* ftape.o ftmt* grep* gzip*
insmod* lsmod* mt -> mt-st* mt-st* rmmod -> insmod*
tar* vi -> elvis*

감사합니다. 잘 배웠습니다.