LIVE CD 만들기 HowTo Ver 0.2
만든이: Kmu ISM(임인경, 윤신수, 함형민, 황대복)
출처 : http://wiki.kldp.org/wiki.php/LiveCD-HOWTO
1 들어가면서 #
우선 이 문서는 Live CD를 만드는 것을 도와주기 위한 문서이다. 현실적으로 대부분의 많은 유저들은 Linux 대신 Windows를 사용하고 있고, 게다가 Live CD의 필요성을 많이 못 느끼고 있는 게 사실이다. 필자 역시 Linux보다 Windows가 익숙한 것이 사실이다. 하지만 우리는 어떤 프로젝트의 준비과정으로 Live CD를 만드는 중 많은 삽질을 거듭하였고, 그 과정에서 아직까지 제대로 된 Live CD에 대한 전문적인 문서가 존재하지 않는 점에 놀랐다. 또한 부팅관련 문서들과 관련 script문서들조차 예전 것이 많았기에 아쉬운 점들이 한 두 가지가 아니었다. 이런 환경들이 우리에게 많은 삽질을 요구 하였고, 하나씩 해결해나가는 과정에서 조금이나마 도움이 될 것들이 있었던 것 같다. 또한 Live CD로 인해 우리와 같은 삽질 리눅서들이 더 이상 없어지기를 바라며 짧은 지식이지만 ?HowTo문서를 작성하기로 결정했다. 잘못된 점이나 오류, 문의사항 등이 있다면 언제든지 메일로 연락해주길 바란다.1.1 Live CD란? #
Linux를 써본 경험이 있는가? 있다면 리눅스 설치 과정이 얼마나 번거로운지 알 것이다.이런 번거로움을 없애기 위한 일환에서 시작된 것이 Live CD라고 할 수 있다. 즉, 어떤 운영체제가 설치 되어있는 컴퓨터라도 CD 한 장만 넣으면 하드웨어에 변화를 주지 않으면서 리눅스 환경을 제공하고, 사용할 수 있게 만들어 주는 CD를 말한다. 이는 Install CD가 아닌 Ramdisk에 상주하는 Linux로서 그냥 전원을 끈 경우라도 커널의 깨짐을 걱정 하지 않아도 되는 Linux이다. ^^* 물론 HDD를 마운트 해서 그 안에 있는 자료들을 볼 수 있고 저장할 수도 있다.1.2 사용 용도 #
사용 용도는 Linux 맛배기용도 될 수 있고, 윈도우가 깔려있는 환경에서의 Linux교육도 가능하겠다. 인스톨의 압박에서 벗어나, 인스톨 전에 Linux를 사용해 볼 수도 있고, Linux 사용의 두려움을 조금이나마 없애 전반적으로 Linux 보급을 널리 퍼지게 할 수 있을 듯 하겠다. 하지만 필자는 딱히 용도를 바라고 만든 것이 아니라… ^.^; 사용 용도는 유저들의 자유로운 상상에 맡기겠다.1.3 작업 동기 #
우리 프로젝트의 목표는 가정용 게임 콘솔에서 리눅스의 인스톨 및 별도의 하드웨어 세팅없이 리눅스 환경을 제공함으로서 PC의 역할을 가능하게 하여, 게임콘솔의 활용도를 높이고 나아가 홈서버를 구현하는 것이다. 자세히 말하자면, 홈서버의 가능성을 찾는 것이라고 해야 옳을 것 같다.1.4 현재 Live CD를 구할 수 있는 곳 #
사이트 주소: http://www.frozentech.com/content/livecd.php 이 사이트는 100여가지 이상의 Live CD를 제공한다. 물론 이 사이트 이외에 다른 사이트들도 있지만, 대부분 이 내용에 포함되므로 생략하겠다.1.5 문서에 대한 책임 #
우선 문서는 자유롭게 배포될 수 있고, 수정 될 수 있다. 우리 역시 좀 더 많은 사람이 이 문서를 접하고, 좀 더 발전 시켜 더 나은 Live CD를 만드는 것을 원한다. 하지만, 꼭 출처는 밝혀주길 바라고, 수정 시 우리에게도 알려주길 바란다. 그리고 이 문서는 단순히 ?HowTo만을 제공할 뿐이다. 하지만 Live CD가 램에만 올라갈 것이기에 하드웨어적으로 아무런 영향을 미치지 않는 것을 확신한다. 하지만 혹시 이 과정 중에 문제가 생긴다면 우리는 그것에 대해 아무런 책임도 지지 않는다는 것을 밝히겠다. 또한 잘못 구워진 CD에 대해서도 우리는 상관하지 않을 것이다. 이를 위해 속도는 좀 느리겠지만 처음엔 RW를 이용하는 것이 좋은 방법이 될 것이다.2 준비물 #
Live CD를 위해선 몇 가지 준비물이 필요하다. 시작하기 전에 이를 꼭 확인하고 시작하기 바란다. 만일 준비물들 중 없는 것이 있다면, 도둑질만 하지 말고, 어디서든 구하길 바란다.2.1 필요한 준비사항 #
정말 무엇보다도 삽질하고자 하는 마음이 필요하다. 이 Live CD를 만들어서 무엇을 하겠느냐 싶지만 우리는 진정한 리눅서를 지향하기에… ^^;- Floppy Diskette 1
- Empty CD-R 또는 CD-RW
- CD-R Writer
- 리눅스 설치 가능 시디(한컴, 와우, 레드햇기반 배포판이면 가능)
- 2G 이상의 물리적 여유공간, 파티션 또는 폴더라도 무관(폴더 경우는 뒤에 자세히 설명)
2.2 주의할 점 #
특별히 주의 할 점은 없다. 하지만, CD를 만드는 과정에서 압축하고, 굽는 과정이 가장 시간이 오래 걸리는 과정이기 때문에 웬만하면 빠른 속도의 내장형 CD-RW Writer를 권장한다. 필자의 경험으로 외장형 CD-RW Writer를 사용할 때는 아무리 RW가 지원을 하더라도 최대배속 4배속으로 밖에 안 구워졌다. 게다가 외장형 CD-RW Writer는 특정 시디만 되는 문제점이 있었다. 즉 몇몇 회사의 CD만 가능했다. 경험 상으로는 Imation, SONY가 가능했고, 나머지는 자세히 확인해보지 못했다. 암튼 외장형 4배속으로 굽다보면 한-두 장 구울때 한나절 걸릴 때도 있었다. -_-; 내장형으로 구웠으면 금방 구워질 것을… 아무쪼록 좋은 사양에서 삽질하길 바란다. 참고로 필자는 LG 48배속 CD-RW Writer와 Acer 12x, SK 10x CD-RW를 사용했다.3 순 서 #
3.2 리눅스 배포판 설치 #
가장 먼저 할 일은 리눅스를 별도의 파티션에 설치하는 것이다. 일단 라이브 시디로 만들고 싶은 리눅스 배포판을 준비해야 한다. 필자의 Live CD에서는 레드햇 계열의 한컴 리눅스3.1을 사용했다. 설치를 위해서는 현재 부팅 되는 시스템에 파티션을 준비한다. 이는 대략 2G정도의 용량이 필요하다. 이 공간은 라이브 시디로 설치될 리눅스가 차지할 공간이다. 새로 생성한 파티션을 ext2로 포맷 후 배포판 시디를 이용하여 리눅스를 설치하고, 설치된 시스템이 이상 없이 부팅되는지 여부를 확인한다.(설치 방법에 대한 자세한 문서는 다른 기술 문서를 참고하거나 리눅스 관련 서적을 참고하기 바란다.)default=redhat
boot=/dev/hda1
map=/boot/map
install=/boot/boot.b
message=/boot/message
ramdisk=8192 # 이 부분 추가
image=/boot/vmlinuz
label=redhat
initrd=/boot/initrd.gz
read-only
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You do not have a /boot partition. This means that
# all kernel and initrd paths are relative to /, eg.
# root (hd0,0)
# kernel /boot/vmlinuz-version ro root=/dev/hda1
# initrd /boot/initrd-version.img
#boot=/dev/hda
default=0
timeout=10
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title Red Hat Linux (2.4.20-31.9)
root (hd0,0)
kernel /boot/vmlinuz-2.4.20-31.9 ro root=LABEL=/ ramdisk_size=8192 # ramdisk_size 라는것에 주의
initrd /boot/initrd-2.4.20-31.9.img
3.3 부팅 이미지 작성 #
배포판이 무사히 설치됐고, Ramdisk까지 사용한다면, 이제 Ramdisk에 풀릴 이미지와 커널 그리고 부트로더가 들어있는 부팅을 위한 부팅 이미지를 만들어야 한다. 이는 디스켓을 이용하여 우선 테스트을 해본 후 문제가 없으면 boot.img 파일로 만들게 된다.- /boot/boot.b vmlinuz map message initrd.gz
boot.img - /dev/fd0
- /etc/lilo.conf
# cp -a /dev/fd0 'target folder'명령으로 원래 리눅스에서 복사한다. lilo.conf는 별도로 작성해야 한다.
prompt
timeout=0 # 부팅시 대기 시간
default=ism # dafault label 세팅
boot=/dev/fd0
map=/boot/map
install=/boot/boot.b
message=/boot/message
lba32image=/boot/vmlinuz # 커널
label=ism # label
initrd=/boot/initrd.gz # 램디스크 이미지
read-only
append="devfs=mount boot=cdrom" # 커맨드 옵션(2가지는 필수)
이제 boot.img는 내용을 편집해 보자. 내용을 보기 위해선 다음과 같은 과정이 필요하다. 일단 적당한 폴더 두개를 만든다. 한 곳은 boot.img가 풀릴 폴더이고, 한 곳은 initrd.gz가 풀릴 폴더이다.
# mkdir livecd
# cd livecd
# mkdir -p init image # 이는 임의로 정한 것임
# mount -o loop boot.img image # boot.img를 image폴더에 마운트(루프백 디바이스)
# cp /livecd/image/boot/initrd.gz ‘현재폴더’ # boot.img내에서 initrd.gz를 가져온다.
# gzip -d initrd.gz # initrd.gz의 압축을 푼다. initrd란 파일이 생길것이다.
# mount -o loop initrd init # initrd를 init폴더에 마운트(루프백 디바이스)
#!/static/sh : 쉘 해석기 이름# < init >
PATH=/bin:/sbin # PATH 설정# < define > : 루트, 모듈 디렉토리, 마운트 할 ISM 폴더 설정
looproot=/ISM/ISM
moddir=/modules
sysdir=/ISM# < 모듈 설정 >
SCSI_MODULES="aic7xxx.o aic7xxx_old.o BusLogic.o \
ncr53c8xx.o NCR53c406a.o \
initio.o \
advansys.o aha1740.o aha1542.o aha152x.o \
atp870u.o dtc.o eata.o fdomain.o gdth.o \
megaraid.o pas16.o pci2220i.o pci2000.o psi240i.o \
qlogicfas.o qlogicfc.o qlogicisp.o \
seagate.o t128.o tmscsim.o u14-34f.o ultrastor.o wd7000.o \
a100u2w.o 3w-xxxx.o"# < function > : 장치를 검색해서 마운트하는 함수, 모듈을 올리는 함수,
# 마운트 실패 시 쉘을 띄우는 함수 설정# BUILTIN_FS라는 변수에 들어 있는 각 파일시스템들을 적절한 옵션을 주어서 마운트
# 예> if pmount $i /cdrom "-o ro" >/dev/null 2>&1
# iso9660 이란 파일시스템을 사용하여 /cdrom 에 Read Only로 -o옵션을 주어서 마운트
pmount()
{
BUILTIN_FS="iso9660 ext3 vfat ext2"
for fs in $BUILTIN_FS; do
test -b $1 && mount -t $fs $3 $1 $2 >/dev/null 2>&1 && return 0
done
return 1
}# scsi 모듈을 찾아서 올려준다.
loadmodules()
{
TYPE="$1"; shift
for i in "$@"; do
if test -f ${moddir}/scsi/$i && insmod -f ${moddir}/scsi/$i >/dev/null 2>&1
then
case "$TYPE" in scsi|SCSI) FOUND_SCSI="yes"; ;; esac
fi
done
}# debug 시 사용. 모든 것이 제대로 load 안 되었을 시 곧바로 쉘로 떨어지게 한다.
startash()
{
echo "Dropping you to a (very limited) shell."
echo "Press reset button to quit."PS1="# "
export PS1
echo "6" > /proc/sys/kernel/printk# Allow signals : 허용되는 인터럽트
# (1 SIGHUP(Hangup), 2 SIGINT(Interrupt..Ctrl-C), 3 SIGQUIT(Quit..Ctrl-\..) 15 SIGTERM(terminatd..shutdown 시)
trap 1 2 3 15exec /static/ash
}# < 허용되지 않는 인터럽트 >
trap "" 1 2 3 15# < Clean input/output > : 콘솔 초기화
exec >/dev/console </dev/console 2>&1
umask 022# < Linux start >
echo "ISM Linux Start…"# < Mount /proc >
mount -t proc /proc /proc# < disable kernel messages while probing modules in autodetect mode >
echo "0" > /proc/sys/kernel/printk# < Read boot command line > : 커맨드 라인을 읽어옴
CMDLINE="$(cat /proc/cmdline)"# < Use devfs ? > : /dev 폴더에 장치 생성
devfs=""
case "$CMDLINE" in *devfs=mount*) devfs="y"; ;; esac
if test -z "${devfs}"; then
mount -t devpts none /dev/pts
fi# < Boot mode > : lilo.conf의 부팅 모드를 읽어와서 CDROM인 경우 Read Only로 설정
boot=""
case "$CMDLINE" in *boot=cdrom*) boot="-o ro"; ;; esac# < Does the user want to skip scsi detection ? > : SCSI장비 사용 여부 검사
NOSCSI=""
case "$CMDLINE" in *noscsi*) NOSCSI="yes"; ;; esac# < load modules > 각종 필요한 모듈 올려주기
echo "Loading Modules…"# loop module
insmod ${moddir}/loop.*o# cdrom modules
insmod ${moddir}/cdrom.*o
insmod ${moddir}/ide-cd.*o
insmod ${moddir}/isofs.*o# native language support modules
insmod ${moddir}/nls_cp437.*o
#insmod ${moddir}/nls_cp932.*o
insmod ${moddir}/nls_iso8859-1.*o# vfat modules
insmod ${moddir}/fat.*o
insmod ${moddir}/vfat.*o# ext3 modules
insmod ${moddir}/jbd.*o
insmod ${moddir}/ext3.*o# scsi modules
insmod ${moddir}/scsi/scsi_mod.*o
insmod ${moddir}/scsi/sr_mod.*o# usb storage
insmod ${moddir}/usbcore.o > /dev/null 2>&1# 스카시 장비 사용한다면 해당 모듈 올리기
# < Check for SCSI, use modules on boot disc first >
# these are the autoprobe-safe modules
MODULES="$SCSI_MODULES"test -z "$NOSCSI" && test -n "$MODULES" && loadmodules SCSI $MODULES
# End of SCSI check# < Check for ide-scsi supported CD-Roms et al >
# 스카시 장비 사용할 수 있는지 여부 판별
test -f /proc/scsi/scsi && FOUND_SCSI="yes"# < mount device >^I # CD-ROM 마운트
echo "Mounting ISM Linux CDROM…"# Now that the right SCSI driver is (hopefully) loaded, try to find CDROM
# 스카시 장비를 사용하길 원한다면 그에 맞는 CD-Rom을 찾아서 mount 해주기
if test -n "${devfs}"; then
loop0=/dev/loop/0
loop1=/dev/loop/1
cloop0=/dev/cloop/0
DEVICES="/dev/cdroms/cdrom? /dev/discs/disc?/part? /dev/discs/disc?"
fifor i in $DEVICES
do
if pmount $i /sysroot "${boot}" >/dev/null 2>&1
then
# for CD-ROM boot
if test -f /sysroot${looproot}
then
FOUND_CD="$i"
break
fi
umount /sysroot
fi
done# CD-ROM 마운트 후 cloop 이용하여 압축 파일시스템 풀기
if test -n "$FOUND_CD" -a -f /sysroot${looproot}
then
# < mount real root as loop0 >
insmod ${moddir}/zlib_inflate.*o > /dev/null 2>&1
insmod -f ${moddir}/cloop.*o file=/sysroot${looproot} > /dev/null 2>&1
pmount ${cloop0} ${sysdir} "-o ro" || FOUND_CD=""
bloop="${cloop0}"if [ -z "${FOUND_CD}" ]; then
losetup ${loop0} /sysroot${looproot} > /dev/null 2>&1
pmount ${loop0} ${sysdir} "-o ro" || startash
FOUND_CD="${i}"
bloop="${loop0}"
fi# fstab과 mtab 세팅
cat > /etc/fstab << EOM
${FOUND_CD} /sysroot iso9660 ro 0 0
${bloop} ${sysdir} ext2 ro 0 0
none /proc proc defaults 0 0
/dev/fd0 /mnt/floppy auto users,noauto,exec 0 0
EOMcat > /etc/mtab << EOM
/dev/root / ext2 rw 0 0
${FOUND_CD} /sysroot iso9660 ro 0 0
${bloop} ${sysdir} ext2 ro 0 0
devfs /dev devfs rw 0 0
EOMelse # 마운트 실패시
echo "Mount Failed!"
startash
fi# < copy library cache > 라이브러리 캐시 복사
cat ${sysdir}/etc/ld.so.cache > /etc/ld.so.cache
echo# < enable kernel messages >
echo "6" > /proc/sys/kernel/printk# < set paths > 경로 설정
PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:."
export PATH# < clean up / > CD를 mount하기 위해 사용했던 modules/static 제거
rm -rf ${moddir} /static# < memory infomation > share memory 세팅
FOUNDMEM="$(awk '/MemTotal/{print $2}' /proc/meminfo)"
TOTALMEM="$(awk 'BEGIN{m=0};/MemFree|Cached/{m+=$2};END{print m}' /proc/meminfo)"# < Calc RAM Size > 사용가능한 램 사이즈 계산
# Minimum size of additional ram partitions
MINSIZE=2000
# At least this much memory minus 30% should remain when home and var are full.
MINLEFT=32000
# Maximum ramdisc size
MAXSIZE="$(expr $TOTALMEM - $MINLEFT)"
# Default ramdisc size for ramdisc
RAMSIZE="$(expr $TOTALMEM / 5)"# < Create Ramdisc > Ramdisk를 크기에 맞게 설정
mkdir -p /ramdisc# Check for sufficient memory to mount extra ramdisc for /home + /var
if test -n "$TOTALMEM" -a "$TOTALMEM" -gt "$MINLEFT"; then
test -z "$RAMSIZE" && RAMSIZE=1000000
# tmpfs/varsize version, can use swap
RAMSIZE=$(expr $RAMSIZE \* 4)
# We need /bin/mount here for the -o size= option
/bin/mount -t tmpfs -o "size=${RAMSIZE}k" /dev/shm /ramdisc
fi# 링크 및 파일, 폴더 생성 제거 부분
mkdir -p /ramdisc/home /ramdisc/var
mv /etc /ramdisc
ln -s /ramdisc/home /ramdisc/var /ramdisc/var/tmp /ramdisc/etc /# Create common WRITABLE (empty) dirs
# 필요한 디렉토리 생성
mkdir -p /var/run /var/backups /var/cache/apache /var/local /var/lock/news \
/var/nis /var/preserve /var/state/misc /var/tmp /var/lib \
/var/spool/cups/tmp /mnt/floppy /mnt/cdrom \
/home/root /etc/X11 /etc/cups /myconfigcp -a /ISM/root /
# Create empty utmp and wtmp 파일 생성 부팅시 필요
:> /var/run/utmp
:> /var/run/wtmp# CUPS wants writable files. 읽고 쓰기가 가능해야 하는 폴더들은 미리 생성
cp -a ${sysdir}/etc/cups/*.conf /etc/cups/ 2>/dev/null
cp -a ${sysdir}/var/local ${sysdir}/var/log ${sysdir}/var/spool /var/ 2>/dev/null# Debian-apt
ln -s ${sysdir}/etc/skel /etc/ 2>/dev/null# Create links from CDROM for UNWRITABLE (remaining) files
# 부팅시 rw로 되어야 하는 파일 생성 및 링크 작업cp -aus ${sysdir}/var/* /var/ 2>/dev/null
cp -aus ${sysdir}/etc/* /etc/ 2>/dev/null
rm -rf /etc/X11/XF86Config*
cp -a /ISM/etc/X11/XF86Config.in /etc/X11
cp -a /ISM/etc/X11/XF86Config-4.in /etc/X11
rm -rf /etc/sysconfig
cp -a ${sysdir}/etc/sysconfig /etc/ 2>/dev/null
rm -rf /etc/modules.conf /etc/sysconfig/hwconf
rm -rf /etc/adjtime /etc/hosts
cp -a /ISM/etc/adjtime /etc/
cp -a /ISM/etc/hosts /etc/
chmod 644 /etc/adjtime /etc/hosts /etc/X11/XF86Config*
ln -s /dev/psaux /dev/mouse
cp -a ${sysdir}/myconfig/* /myconfig/ 2>/dev/null# Make SURE that these are files, not links!
rm -rf /etc/rc?.d
ln -s /etc/rc.d/rc?.d /etc/# < Now tell kernel where the real modprobe lives >
echo "/sbin/modprobe" > /proc/sys/kernel/modprobe# < root를 /dev/fd0에서 /dev/ram으로 변경>
echo "0x100" > /proc/sys/kernel/real-root-dev
umount /proc# < init에게 실행을 넘김, 즉 init 프로세서 실행 >
echo "Starting init process…"
rm -f /linuxrc
exit 0
# umount /livecd/init
# dd if=initrd bs=1k | gzip -v9 > initrd.gz # initrd파일을 initrd.gz 압축파일로 만든다.
# cp -a initrd.gz /livecd/image/boot/ # 새로 수정한 initrd.gz를 저장
# umount image # image폴더 마운트 해제
# dd if=boot.img of=/dev/fd0 bs=1k # 디스켓에 저장
# mount -o dev /dev/fd0 ‘임의의 폴더’ # 리로를 업데이트하기 위해 디스켓을 마운트
# lilo -r ‘임의의 폴더’ # 리로를 업데이트. add *ism이란 메세지를 볼 수 있을 것이다.
# dd if=/dev/fd0 of=‘복사될 폴더’/boot.img bs=1k이 명령어를 수행하면 boot.img란 파일을 얻을 수 있을 것이다.
3.4 나만의 리눅스 이미지 작성 #
필자는 주로 한컴 리눅스를 이용했다. 이미지 작성법은 간단하다. 설치된 리눅스로 부팅을 한 뒤 X windows를 실행한다. 그리고 메뉴에서 프로그램 추가 삭제를 이용하여, 자신에게 필요 없다고 생각되는 것들은 일일이 지운다. 이 과정에서 core file이나 필수적으로 있어야 되는 파일은 지우지 않길 바란다.ex)
# cp -a /dev /‘리눅스 설치된 폴더’/dev
# chroot ‘리눅스 설치된 폴더명'
# mkisofs -R -l -V "ISM iso9660 filesystem" -v /시디에 넣을 리눅스 폴더 | create_compressed_fs - 65536 > /파일이 생성될 폴더/ISM
# mkisofs -l -r -J -V "ISM Linux" -v -b boot.img -c boot.cat /.iso파일이 생성될 폴더/name.iso /ISM파일이 있는 폴더
# cdrecord -v -dev=0,0,0 -speed=x name.iso
# cdrecord -v -dev=0,0,0 -blank=fast
4 문제점 및 Q/A #
4.1 발견된 문제점들 #
라이브 시디를 작성하면서 예기치 못한 문제점들이 몇 가지 발생하였다. 대부분 설정 파일에 관한 문제였으며, 대충 해결을 하였으나 아직까지도 완벽하게 해결했다고는 장담하지 못한다.- VFS panic
- Cloop 사용 시 에러
- rw 권한 폴더 및 파일 파악
- rc.sysinit의 불필요한 부분 선택 문제
- 필요 없는 데몬 구분
- 부팅 시 로그인 과정 없애기
- /root를 home directory로 인식하지 못하는 문제점
- 원하는 프로그램 바로 실행시키기
- DHCP 사용 시 설정 파일 문제
- 장치 및 X 윈도우 해상도 등 자동 설정 문제
- X 윈도우의 폰트 문제
- 종료 시 root인 CDROM의 mount를 해제하지 못하여 발생하는 문제점