====== LFS(Linux From Scratch) 설치하기 ====== ====== LFS 란 ====== 쉽게 말해 리눅스를 소스로 설치한다고 생각하면 쉬울 것이다. 필자를 포함해서 거의 대부분의 리눅서들이 CD나 다른 매체를 통해서 배포판으로 설치하고 있다. 필자도 LFS라는 말을 들은 지는 한달도 채 되지 않았다. 하지만, LFS의 의미를 알고 나서 왠지 모르는 해보고 싶다는 충동이 일었다. 그동안 써오던 레드햇 기반의 리눅스가 싫증이 난 것도 한 몫 했을 것이다. 이 LFS는 내가 이제까지 해왔던 작업중 가장 힘들고 지루했었다. 밤 12시에 시작해서 아침 7시 30분까지 작업을 했으니....ㅡ.ㅡ;; 이제 본격적인 LFS 설치를 해보자!! ====== 준비운동 하기 ====== 우선 LFS를 설치하기 위해서는 리눅스 파티션이 있어야 한다. 기존의 리눅스 파티션을 이용해도 되고 하드에 여유가 있다면 리눅스 파티션을 하나 만들자!! 하지만 리눅스 파티션을 하나 만들기를 적극 권장한다. 필자는 '/dev/hdd1' 파티션을 만들었다. 만드는 방법은 다음과 같다. #mke2fs /dev/hdd1 용량은 최대한 충분히 잡아주기 바란다. 필자는 모두 설치했을 때 500메가 정도 되었었다. 여러분들은 최소한 1기가는 잡아주어야 한다. 새 파티션을 만들었다면, LFS 사이트에 가서 설치에 필요한 소스를 다운받아야 한다. 주소는 http://www.linuxfromscratch.org/ 이다. 이 글을 쓰는 현재 3.0 버전이 최신버전이다. LFS를 설치하기 위한 프로그램들은 거의 30여개가 넘는다. 이를 모두 일일이 받는 다는 것은 비효율적이다. 그러므로 이것들을 패키지로 묶어놓은 패키지 파일을 받도록 하자. 필자는 ftp://ftp.linuxfromscratch.org/lfs-packages/3.0/lfs-packages-3.0.tar 를 받았다. ====== 설치하기 ====== 위에서 우리가 만들어 놓은 새 파티션(/dev/hdd1)을 마운트 시킨다. 이 새 파티션에다가 LFS를 설치할 것이다. #mkdir -p /mnt/lfs #mount /dev/hdd1 /mnt/lfs 마운트 할 디렉토리 이름은 lfs로 한다. 앞으로 우리는 /mnt/lfs 라는 이름 대신에 $LFS 라는 변수로 대신할 것이다. 그러므로 아래와 같이 변수를 지정해준다. #export LFS=/mnt/lfs 재부팅을 하고 나면 설정이 지워지므로 /root/.bashrc 파일에다가 한줄 추가시켜준다. 그리고 나서 아래를 실행시켜 디렉토리를 만들어준다. #cd $LFS #mkdir -p bin boot dev/pts etc/opt home lib mnt proc root sbin tmp var opt #for dirname in $LFS/usr $LFS/usr/local do mkdir $dirname cd $dirname mkdir bin etc include lib sbin share src var ln -s share/man man ln -s share/doc doc ln -s share/info info cd $dirname/share mkdir dict doc info locale man nls misc terminfo zoneinfo cd $dirname/share/man mkdir man{1,2,3,4,5,6,7,8} done #cd $LFS/var #mkdir -p lock log mail run spool tmp opt cache lib/misc local #cd $LFS/opt #mkdir bin doc include info lib man #cd $LFS/usr #ln -s ../var/tmp tmp #cd $LFS #chmod 0750 root #chmod 1777 tmp var/tmp 위의 설정까지 마쳤다면 LFS를 설치하기 위한 설정은 모두 마친 셈이다. 이제 본격적으로 설치해보자! 이제부터 우리가 위에서 다운받은 lfs-packages-3.0.tar은 $LFS/usr/src 에다가 옮겨 놓고 압축을 풀고 설치할 것이다. ===== Bash-2.05 ===== #cd /usr/lib && ln -s libncurses.a libcurses.a #./configure --enable-static-link --prefix=$LFS/usr \ --bindir=$LFS/bin --with-curses && make && make install && cd $LFS/bin && ln -sf bash sh ===== Binutils-2.11.2 ===== #./configure --prefix=$LFS/usr --disable-nls && make LDFLAGS=-all-static tooldir=$LFS/usr && make tooldir=$LFS/usr install ===== Bzip2-1.0.1 ===== #make CC="gcc -static" && make PREFIX=$LFS/usr install && cd $LFS/usr/bin && mv bzcat bunzip2 bzip2 bzip2recover $LFS/bin ===== Diffutils-2.7 ===== ※ glib 버전이 2.1.x 이면, #export CPPFLAGS=-Dre_max_failures=re_max_failures2 && ./configure --prefix=$LFS/usr && unset CPPFLAGS && make LDFLAGS=-static && make install ※ glib 버전이 2.2.x 이면, #./configure --prefix=$LFS/usr && make LDFLAGS=-static && make install ===== Fileutils-4.1 ===== #cp lib/Makefile.in lib/Makefile.in.backup && sed -e 's/\(.*\)\(fopen-safer\.c \)\\/\1\2atexit.c \\/' \ -e 's/\(.*\)\(idcache\$U\.\$.*\)\\/\1\2atexit$U.$(OBJEXT) \\/' \ lib/Makefile.in > lib/Makefile.in~ && mv lib/Makefile.in~ lib/Makefile.in #./configure --disable-nls \ --prefix=$LFS/usr --libexecdir=$LFS/bin --bindir=$LFS/bin && make LDFLAGS=-static && make install && cd $LFS/usr/bin && ln -sf ../../bin/install ===== Gcc-2.95.3 ===== #patch -Np1 -i ../gcc-2.95.3-2.patch && mkdir ../gcc-build && cd ../gcc-build && ../gcc-2.95.3/configure --prefix=/usr --enable-languages=c,c++ \ --disable-nls --disable-shared --enable-threads=posix && make BOOT_LDFLAGS=-static bootstrap && make prefix=$LFS/usr install && cd $LFS/lib && ln -sf ../usr/bin/cpp && cd $LFS/usr/lib && ln -sf ../bin/cpp && cd $LFS/usr/bin && ln -sf gcc cc ===== Grep-2.4.2 ===== ※ glibc-2.1.x 이면 #export CPPFLAGS=-Dre_max_failures=re_max_failures2 && ./configure --prefix=$LFS/usr --disable-nls && unset CPPFLAGS && make LDFLAGS=-static && make install ※ glibc-2.2.x 이면 #./configure --prefix=$LFS/usr --disable-nls && make LDFLAGS=-static && make install ===== Gzip-1.2.4a ===== #patch -Np1 -i ../gzip-1.2.4a.patch #./configure --prefix=$LFS/usr && make LDFLAGS=-static && make install && cp $LFS/usr/bin/gunzip $LFS/usr/bin/gzip $LFS/bin && rm $LFS/usr/bin/gunzip $LFS/usr/bin/gzip ===== Kernel-2.4.8 ===== ※ 반드시 $LFS/usr/src 에 풀어놓고 작업을 해야 한다. #make mrproper && yes "" | make config && make dep && cd $LFS/usr/include && cp -a ../src/linux/include/linux . && chown -R root.root $LFS/usr/include/linux && mkdir asm && cp -a ../src/linux/include/asm/* asm && chown -R root.root $LFS/usr/include/asm ===== Make-3.79.1 ===== #./configure --prefix=$LFS/usr --disable-nls && make LDFLAGS=-static && make install ===== Mawk-1.3.3 ===== #./configure && make CC="gcc -static" && make BINDIR=$LFS/usr/bin \ MANDIR=$LFS/usr/share/man/man1 install ===== Patch-2.5.4 ===== #./configure --prefix=$LFS/usr && make LDFLAGS=-static && make install ===== sed-3.02 ===== ※ glibc-2.1.x export CPPFLAGS=-Dre_max_failures=re_max_failures2 && ./configure --prefix=$LFS/usr --bindir=$LFS/bin && unset CPPFLAGS && make LDFLAGS=-static && make install ※ glibc-2.2.x ./configure --prefix=$LFS/usr --bindir=$LFS/bin && make LDFLAGS=-static && make install ===== Sh-uils-2.0 ===== #patch -Np1 -i ../sh-utils-2.0.patch #./configure --prefix=$LFS/usr --disable-nls && make LDFLAGS=-static && make install && cd $LFS/usr/bin && mv date echo false pwd stty $LFS/bin && mv su true uname hostname $LFS/bin ===== Tar-1.13 ===== #patch -Np1 -i ../tar-1.13.patch #./configure --prefix=$LFS/usr --disable-nls \ --libexecdir=$LFS/usr/bin --bindir=$LFS/bin && make LDFLAGS=-static && make install ===== Texinfo-4.0 ===== #./configure --prefix=$LFS/usr --disable-nls && make LDFLAGS=-static && make install ===== Textuils-2.0 ===== #./configure --prefix=$LFS/usr --disable-nls && make LDFLAGS=-static && make install && mv $LFS/usr/bin/cat $LFS/bin ===== passwd 와 group 파일 만들기 ===== echo "root:x:0:0:root:/root:/bin/bash" > $LFS cat > $LFS/etc/group << "EOF" root:x:0: bin:x:1: sys:x:2: kmem:x:3: tty:x:4: tape:x:5: daemon:x:6: floppy:x:7: disk:x:8: lp:x:9: dialout:x:10: audio:x:11: EOF ===== old NSS library files 복사하기 ===== #/lib/libc.so.6 #cp -av /lib/libnss* $LFS/lib ===== $LFS/proc file system 마운트하기 ===== #mount proc $LFS/proc -t proc ===== $LFS/root/.bash_profile 파일 만들기 ===== #cat > $LFS/root/.bash_profile << "EOF" # Begin /root/.bash_profile PS1='\u:\w\$ ' PATH=/bin:/usr/bin:/sbin:/usr/sbin export PS1 PATH # End /root/.bash_profile EOF ===== 기본 시스템 환경으로 설치하기 ===== #cd $LFS && chroot $LFS /usr/bin/env -i HOME=/root \ TERM=$TERM /bin/bash --login ===== Glibc-2.2.4 ===== ※ glibc-linuxthreads를 glibc-2.2.4 디렉토리 안에 풀어서 같이 설치합니다. #mknod -m 0666 /dev/null c 1 3 && touch /etc/ld.so.conf && cp malloc/Makefile malloc/Makefile.backup && sed 's%\$(PERL)%/usr/bin/perl%' malloc/Makefile > tmp~ && mv tmp~ malloc/Makefile && cp login/Makefile login/Makefile.backup && sed 's/root/0/' login/Makefile > tmp~ && mv tmp~ login/Makefile && mkdir ../glibc-build && cd ../glibc-build && ../glibc-2.2.4/configure --prefix=/usr \ --enable-add-ons --libexecdir=/usr/bin && cp config.make config.make.backup && sed 's/cross-compiling = yes/cross-compiling = no/' \ config.make > tmp~ && mv tmp~ config.make && make && make install && make localedata/install-locales && exec /bin/bash --login ===== Makedev-1.3 ===== #./MAKEDEV -v generic ===== Man-pages-1.39 ===== #patch -Np1 -i ../man-pages-1.39.patch && make install ===== Findutils-4.1 ===== #patch -Np1 -i ../findutils-4.1.patch && ./configure --prefix=/usr && make && make libexecdir=/usr/bin install ※ 여기서부터 전에 설치했던 것을 다시 설치하는 경우가 생깁니다. 그럴 때는 전에 설치할 때 풀어놓았던 디렉토리를 지우고 새로 압축을 풀어서 설치합니다. ===== Mawk-1.3.3 ===== #./configure && make && make BINDIR=/usr/bin \ MANDIR=/usr/share/man/man1 install && cd /usr/bin && ln -sf mawk awk ===== Ncurses-5.2 ===== #./configure --prefix=/usr --libdir=/lib \ --with-shared --disable-termcap && make && make install && cd /lib && mv *.a /usr/lib && chmod 755 *.5.2 && cd /usr/lib && ln -sf libncurses.a libcurses.a && ln -sf ../../lib/libncurses.so && ln -sf ../../lib/libcurses.so && ln -sf ../../lib/libform.so && ln -sf ../../lib/libpanel.so && ln -sf ../../lib/libmenu.so ===== Vim-5.8 ===== #echo '#define SYS_VIMRC_FILE "/etc/vimrc"' >> \ src/feature.h && ./configure --prefix=/usr && make && make install && cd /usr/bin && ln -sf vim vi ===== GCC-2.95.3 ===== #patch -Np1 -i ../gcc-2.95.3-2.patch && mkdir ../gcc-build && cd ../gcc-build && ../gcc-2.95.3/configure --prefix=/usr --enable-shared \ --enable-languages=c,c++ --enable-threads=posix && make bootstrap && make install ===== Bison-1.28 ===== #./configure --prefix=/usr \ --datadir=/usr/share/bison && make && make install #cat > /usr/bin/yacc << "EOF" #!/bin/sh # Begin /usr/bin/yacc exec /usr/bin/bison -y "$@" # End /usr/bin/yacc EOF #chmod 755 /usr/bin/yacc ===== Less-358 ===== #./configure --prefix=/usr --bindir=/bin && make && make install ===== Groff-1.17.2 ===== ./configure --prefix=/usr && make && make install ===== Man-1.5i2 ===== #for i in configure src/Makefile.in src/makewhatis.sh do cp $i $i.backup && sed 's/gawk/awk/g' $i > tmp~ && mv tmp~ $i done && chmod 755 configure && ./configure -default && make && make install ===== Perl-5.6.1 ===== #./Configure -Dprefix=/usr && make && make install ===== M4-1.4 ===== #./configure --prefix=/usr && make && make install ===== Texinfo-4.0 ===== #./configure --prefix=/usr && make && make install && make TEXMF=/usr/share/texmf install-tex ===== Autoconf-2.52 ===== #./configure --prefix=/usr && make && make install ===== Automake-1.5 ===== #./configure --prefix=/usr && make install ===== Bash-2.05 ===== #./configure --prefix=/usr --with-curses \ --bindir=/bin && make && make install && exec /bin/bash --login ===== Flex-2.5.4a ===== #./configure --prefix=/usr && make && make install && cd /usr/bin && ln -sf flex lex ===== File-3.36 ===== #cp readelf.h readelf.h.backup && sed $'/#define __/a \\\n#include ' readelf.h.backup > readelf.h && ./configure --prefix=/usr --datadir=/usr/share/misc && make && make install ===== Libtool-1.4 ===== #./configure --prefix=/usr && make && make install ===== Bin86-0.16.0 ===== #make && make PREFIX=/usr install ===== Binutils-2.11.2 ===== #./configure --prefix=/usr --enable-shared && make tooldir=/usr && make tooldir=/usr install && make tooldir=/usr install-info ===== Bzip2-1.0.1 ===== #make -f Makefile-libbz2_so && make bzip2recover libbz2.a && ln -s libbz2.so.1.0.1 libbz2.so && cp bzip2-shared /bin/bzip2 && cp bzip2recover /bin && cp bzip2.1 /usr/share/man/man1 && cp bzlib.h /usr/include && cp -a libbz2.so* /lib && rm /usr/lib/libbz2.a && cp libbz2.a /usr/lib && cd /usr/lib && ln -sf ../../lib/libbz2.so && cd /bin && ln -sf bzip2 bunzip2 && ln -sf bzip2 bzcat && cd /usr/share/man/man1 && ln -sf bzip2.1 bunzip2.1 && ln -sf bzip2.1 bzcat.1 && ln -sf bzip2.1 bzip2recover.1 ===== Ed-0.2 ===== #cp buf.c buf.c.backup && sed 's/int u/int u, sfd/' buf.c.backup | \ sed '/.*\*mktemp.*/d' | \ sed 's/.*if (mktemp.*/ sfd = mkstemp(sfn);\ if ((sfd == -1) || (sfp = fopen (sfn, "w+")) == NULL)/' > buf.c && ./configure --prefix=/usr && make && make install && mv /usr/bin/ed /usr/bin/red /bin ===== Gettext-0.10.39 ===== #./configure --prefix=/usr && make && make install ===== Kbd-1.06 ===== #./configure --datadir=/usr/share/kbd && make && make install ===== Diffutils-2.7 ===== #./configure --prefix=/usr && make && make install ===== E2fsprogs-1.24 ===== #./configure --prefix=/usr --with-root-prefix=/ \ --enable-elf-shlibs && make && make install && make install-libs ===== Fileutils-4.1 ===== #./configure --prefix=/usr --bindir=/bin \ --libexecdir=/bin && make && make install ===== Grep-2.4.2 ===== #./configure --prefix=/usr && make && make install ===== Gzip-1.2.4a ===== #./configure --prefix=/usr && make && make install && cd /usr/bin && mv gzip /bin && rm gunzip zcat && cd /bin && ln -sf gzip gunzip && ln -sf gzip zcat && ln -sf gzip compress && ln -sf gunzip uncompress ===== Lilo-21.7.5 ===== #make && make install ===== Make-3.79.1 ===== #./configure --prefix=/usr && make && make install ===== Modutils-2.4.7 ===== #./configure && make && make install ===== Netkit-base-0.17 ===== #./configure && make && make install && cd etc.sample && cp services protocols /etc ===== Patch-2.5.4 ===== #./configure --prefix=/usr && make && make install ===== Procinfo-18 ===== #make LDLIBS=-lncurses && make install ===== Procps-2.0.7 ===== #make && make XSCPT='' install && mv /usr/bin/kill /bin ===== Psmisc-20.1 ===== #./configure --prefix=/usr --exec-prefix=/ && make && make install ===== Tar-1.13 ===== #patch -Np1 -i ../tar-1.13.patch #./configure --prefix=/usr --libexecdir=/usr/bin \ --bindir=/bin && make && make install ===== Textutils-2.0 ===== #./configure --prefix=/usr && make && make install && mv /usr/bin/cat /bin ===== Util-linux-2.11h ===== #cp hwclock/hwclock.c hwclock/hwclock.c.backup && sed 's%etc/adjtime%var/lib/hwclock/adjtime%' \ hwclock/hwclock.c > tmp~ && mv tmp~ hwclock/hwclock.c && mkdir -p /var/lib/hwclock ===== old NSS library files 옮기기 ===== #rm /lib/libnss*.so.1 /lib/libnss*2.0* ====== 소프트웨어 설정 ====== ===== Vim ===== #cat > /root/.vimrc << "EOF" " Begin /root/.vimrc set nocompatible set bs=2 " End /root/.vimrc EOF ===== Glibc ===== #cat > /etc/nsswitch.conf << "EOF" # Begin /etc/nsswitch.conf passwd: files group: files shadow: files publickey: files hosts: files dns networks: files protocols: db files services: db files ethers: db files rpc: db files netgroup: db files # End /etc/nsswitch.conf EOF #cd /etc && ln -sf ../usr/share/zoneinfo/ localtime OR #ln -sf ../usr/share/zoneinfo/EST5EDT localtime Or: #ln -sf ../usr/share/zoneinfo/Canada/Eastern localtime ====== Configuring Dynamic Loader ====== #cat > /etc/ld.so.conf << "EOF" # Begin /etc/ld.so.conf /lib /usr/lib /usr/local/lib # End /etc/ld.so.conf EOF ===== Configuring Sysklogd ===== #cat > /etc/syslog.conf << "EOF" # Begin /etc/syslog.conf auth,authpriv.* -/var/log/auth.log *.*;auth,authpriv.none -/var/log/sys.log daemon.* -/var/log/daemon.log kern.* -/var/log/kern.log mail.* -/var/log/mail.log user.* -/var/log/user.log *.emerg * # End /etc/syslog.conf EOF ===== Configuring Shadow Password Suite ===== #/usr/sbin/pwconv ===== Configuring Sysvinit ===== #cat > /etc/inittab << "EOF" # Begin /etc/inittab id:3:initdefault: si::sysinit:/etc/init.d/rcS l0:0:wait:/etc/init.d/rc 0 l1:S1:wait:/etc/init.d/rc 1 l2:2:wait:/etc/init.d/rc 2 l3:3:wait:/etc/init.d/rc 3 l4:4:wait:/etc/init.d/rc 4 l5:5:wait:/etc/init.d/rc 5 l6:6:wait:/etc/init.d/rc 6 ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now su:S016:respawn:/sbin/sulogin 1:2345:respawn:/sbin/agetty tty1 9600 2:2345:respawn:/sbin/agetty tty2 9600 3:2345:respawn:/sbin/agetty tty3 9600 4:2345:respawn:/sbin/agetty tty4 9600 5:2345:respawn:/sbin/agetty tty5 9600 6:2345:respawn:/sbin/agetty tty6 9600 # End /etc/inittab EOF ===== Creating the /var/run/utmp, /var/log/wtmp and /var/log/btmp files ===== #touch /var/run/utmp /var/log/wtmp \ /var/log/btmp /var/log/lastlog && chmod 644 /var/run/utmp /var/log/wtmp \ /var/log/btmp /var/log/lastlog ===== Creating root password ===== #passwd root ====== 부트 스크립트 ====== ===== Creating directories ===== #cd /etc && mkdir rc{0,1,2,3,4,5,6,S}.d init.d sysconfig && cd init.d ===== Creating the rc script ===== #cat > /etc/init.d/rc << "EOF" #!/bin/sh # Begin /etc/init.d/rc # # By Jason Pearce - jason.pearce@linux.org # Modified by Gerard Beekmans - gerard@linuxfromscratch.org # print_error_msg based on ideas by Simon Perreault - # nomis80@videotron.ca # # # Include the functions declared in the /etc/init.d/functions file # source /etc/init.d/functions # # The print_error_msg function prints an error message when an unforeseen # error occurred that wasn't trapped for some reason by a evaluate_retval # call or error checking in different ways. print_error_msg() { echo $FAILURE echo -n "You should not read this error message. It means " echo "that an unforeseen error " echo -n "took place and subscript $i exited with " echo "a return value " echo -n "of $error_value for an unknown reason. If you're able " echo "to trace this error down " echo -n "to a bug in one of the files provided by this book, " echo "please be so kind to " echo -n "inform us at lfs-dev@linuxfromscratch.org" $NORMAL echo echo echo "Press a key to continue..." read } # # If you uncomment the debug variable below none of the scripts will be # executed, just the script name and parameters will be echo'ed to the # screen so you can see how the scripts are called by rc. # # Un-comment the following for debugging. # debug=echo # # Start script or program. # startup() { $debug "$@" } # # Ignore CTRL-C only in this shell, so we can interrupt subprocesses. # trap ":" INT QUIT TSTP # # Now find out what the current and what the previous runlevel are. The # $RUNLEVEL variable is set by init for all it's children. This script # runs as a child of init. # runlevel=$RUNLEVEL # # Get first argument. Set new runlevel to this argument. If no runlevel # was passed to this script we won't change runlevels. # [ "$1" != "" ] && runlevel=$1 if [ "$runlevel" = "" ] then echo "Usage: $0 " >&2 exit 1 fi # # The same goes for $PREVLEVEL (see above for $RUNLEVEL). previous will # be set to the previous run level. If $PREVLEVEL is not set it means # that there is no previous runlevel and we'll set previous to N. # previous=$PREVLEVEL [ "$previous" = "" ] && previous=N export runlevel previous # # Is there an rc directory for the new runlevel? # if [ -d /etc/rc$runlevel.d ] then # # If so, first collect all the K* scripts in the new run level. # if [ $previous != N ] then for i in /etc/rc$runlevel.d/K* do [ ! -f $i ] && continue # # the suffix variable will contain the script name without the leading # Kxxx # suffix=${i#/etc/rc$runlevel.d/K[0-9][0-9][0-9]} # # If there is a start script for this K script in the previous runlevel # determine what it's full path is # previous_start=/etc/rc$previous.d/S[0-9][0-9][0-9]$suffix # # If there was no previous run level it could be that something was # started in rcS.d (sysinit level) so we'll determine the path for that # possibility as well. # sysinit_start=/etc/rcS.d/S[0-9][0-9][0-9]$suffix # # Stop the service if there is a start script in the previous run level # or in the sysinit level. If previous_start or sysinit_start do not # exist the 'continue' command is run which causes the script to abort # this iteration of the for loop and continue with the next iteration. # This boils down to that it won't run the commands after the next two # lines and start over from the top of this for loop. See man bash for # more info on this. # [ ! -f $previous_start ] && [ ! -f $sysinit_start ] && continue # # If we found previous_start or sysinit_start, run the K script # startup $i stop error_value=$? # # If the return value of the script is not 0, something went wrong with # error checking inside the script. the print_error_msg function will be # called and the message plus the return value of the K script will be # printed to the screen # if [ $error_value != 0 ] then print_error_msg fi done fi # # Now run the START scripts for this runlevel. # for i in /etc/rc$runlevel.d/S* do [ ! -f $i ] && continue if [ $previous != N ] then # # Find start script in previous runlevel and stop script in this # runlevel. # suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9][0-9]} stop=/etc/rc$runlevel.d/K[0-9][0-9][0-9]$suffix previous_start=/etc/rc$previous.d/S[0-9][0-9][0-9]$suffix # # If there is a start script in the previous level and no stop script in # this level, we don't have to re-start the service; abort this # iteration and start the next one. # [ -f $previous_start ] && [ ! -f $stop ] && continue fi case "$runlevel" in 0|6) # # levels 0 and 6 are halt and reboot levels. We don't really start # anything here so we call with the 'stop' parameter # startup $i stop error_value=$? # # If the return value of the script is not 0, something went wrong with # error checking inside the script. the print_error_msg function will be # called and the message plus the return value of the K script will be # printed to the screen # if [ $error_value != 0 ] then print_error_msg fi ;; *) startup $i start error_value=$? # # If the return value of the script is not 0, something went wrong with # error checking inside the script. the print_error_msg function will be # called and the message plus the return value of the K script will be # printed to the screen # if [ $error_value != 0 ] then print_error_msg fi ;; esac done fi # End /etc/init.d/rc EOF ===== Creating the rcS script ===== #cat > /etc/init.d/rcS << "EOF" #!/bin/sh # Begin /etc/init.d/rcS # # See the rc script for the extensive comments on the constructions # used here # source /etc/init.d/functions print_error_msg() { echo $FAILURE echo -n "You should not read this error message. It means " echo "that an unforeseen error " echo -n "took place and subscript $i exited with " echo "a return value " echo -n "of $error_value for an unknown reason. If you're able " echo "to trace this error down " echo -n "to a bug in one of the files provided by this book, " echo "please be so kind to " echo -n "inform us at lfs-dev@linuxfromscratch.org" $NORMAL echo echo echo "Press a key to continue..." read } runlevel=S prevlevel=N umask 022 export runlevel prevlevel trap ":" INT QUIT TSTP # # Collect all the S scripts in /etc/rcS.d and execute them # for i in /etc/rcS.d/S* do [ ! -f "$i" ] && continue; $i start error_value=$? if [ $error_value != 0 ] then print_error_msg fi done # End /etc/init.d/rcS EOF ===== Creating the functions script ===== #cat > /etc/init.d/functions << "EOF" #!/bin/sh # Begin /etc/init.d/functions # # Set a few variables that influence the text that's printed on the # screen. The SET_COL variable starts the text in the column number # decided by the COL and WCOL section (as defined by the COL # variable). NORMAL prints text in normal mode. # SUCCESS prints text in a green colour and FAILURE prints text in a red # colour # # If COLUMNS hasn't been set yet (bash sets it but not when called as # sh), do it ourself if [ -z "$COLUMNS" ] then # Get the console device if we don't have it already # This is ok by the FHS as there is a fallback if # /usr/bin/tty isn't available, for example at bootup. test -x /usr/bin/tty && CONSOLE=`/usr/bin/tty` test -z "$CONSOLE" && CONSOLE=/dev/console # Get the console size (rows columns) SIZE=$(stty size < $CONSOLE) # Strip off the rows leaving the columns COLUMNS=${SIZE#*\ } fi COL=$[$COLUMNS - 10] WCOL=$[$COLUMNS - 30] SET_COL="echo -en \\033[${COL}G" SET_WCOL="echo -en \\033[${WCOL}G" NORMAL="echo -en \\033[0;39m" SUCCESS="echo -en \\033[1;32m" WARNING="echo -en \\033[1;33m" FAILURE="echo -en \\033[1;31m" # # The evaluate_retval function evaluates the return value of the process # that was run just before this function was called. If the return value # was 0, indicating success, the print_status function is called with # the 'success' parameter. Otherwise the print_status function is called # with the failure parameter. # evaluate_retval() { if [ $? = 0 ] then print_status success else print_status failure fi } # # The print_status prints [ OK ] or [FAILED] to the screen. OK appears # in the colour defined by the SUCCESS variable and FAILED appears in # the colour defined by the FAILURE variable. Both are printed starting # in the column defined by the COL variable. # print_status() { # # If no parameters are given to the print_status function, print usage # information. # if [ $# = 0 ] then echo "Usage: print_status {success|failure}" return 1 fi case "$1" in success) $SET_COL echo -n "[ " $SUCCESS echo -n "OK" $NORMAL echo " ]" ;; warning) $SET_COL echo -n "[ " $WARNING echo -n "ATTN" $NORMAL echo " ]" ;; failure) $SET_COL echo -n "[" $FAILURE echo -n "FAILED" $NORMAL echo "]" ;; esac } # # The loadproc function starts a process (often a daemon) with # proper error checking # loadproc() { # # If no parameters are given to the print_status function, print usage # information. # if [ $# = 0 ] then echo "Usage: loadproc {program}" exit 1 fi # # Find the basename of the first parameter (the daemon's name without # the path # that was provided so /usr/sbin/syslogd becomes plain 'syslogd' after # basename ran) # base=$(/usr/bin/basename $1) # # the pidlist variable will contains the output of the pidof command. # pidof will try to find the PID's that belong to a certain string; # $base in this case # pidlist=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $base) pid="" for apid in $pidlist do if [ -d /proc/$apid ] then pid="$pid $apid" fi done # # If the $pid variable contains anything (from the previous for loop) it # means the daemon is already running # if [ ! -n "$pid" ] then # # Empty $pid variable means it's not running, so we run "$@" (all # parameters giving to this function from the script) and then check the # return value # "$@" evaluate_retval else # # The variable $pid was not empty, meaning it was already running. We'll # print [ ATTN ] now # $SET_WCOL echo -n "Already running" print_status warning fi } # # The killproc function kills a process with proper error checking # killproc() { # # If no parameters are given to the print_status function, print usage # information. # if [ $# = 0 ] then echo "Usage: killproc {program} [signal]" exit 1 fi # # Find the basename of the first parameter (the daemon's name without # the path # that was provided so /usr/sbin/syslogd becomes plain 'syslogd' after # basename ran) # base=$(/usr/bin/basename $1) # # Check if we gave a signal to kill the process with (like -HUP, -TERM, # -KILL, etc) to this function (the second parameter). If no second # parameter was provided set the nolevel variable. Else set the # killlevel variable to the value of $2 (the second parameter) # if [ "$2" != "" ] then killlevel=-$2 else nolevel=1 fi # # the pidlist variable will contains the output of the pidof command. # pidof will try to find the PID's that belong to a certain string; # $base in this case # pidlist=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $base) pid="" for apid in $pidlist do if [ -d /proc/$apid ] then pid="$pid $apid" fi done # # If $pid contains something from the previous for loop it means one or # more PID's were found that belongs to the processes to be killed # if [ -n "$pid" ] then # # If no kill level was specified we'll try -TERM first and then sleep # for 2 seconds to allow the kill to be completed # if [ "$nolevel" = 1 ] then /bin/kill -TERM $pid # # If after -TERM the PID still exists we'll wait 2 seconds before # trying to kill it with -KILL. If the PID still exist after that, wait # two more seconds. If the PIDs still exist by then it's safe to assume # that we cannot kill these PIDs. # if /bin/ps h $pid >/dev/null 2>&1 then /usr/bin/sleep 2 if /bin/ps h $pid > /dev/null 2>&1 then /bin/kill -KILL $pid if /bin/ps h $pid > /dev/null 2>&1 then /usr/bin/sleep 2 fi fi fi /bin/ps h $pid >/dev/null 2>&1 if [ $? = 0 ] then # # If after the -KILL it still exists it can't be killed for some reason # and we'll print [FAILED] # print_status failure else # # It was killed, remove possible stale PID file in /var/run and # print [ OK ] # /bin/rm -f /var/run/$base.pid print_status success fi else # # A kill level was provided. Kill with the provided kill level and wait # for 2 seconds to allow the kill to be completed # /bin/kill $killlevel $pid if /bin/ps h $pid > /dev/null 2>&1 then /usr/bin/sleep 2 fi /bin/ps h $pid >/dev/null 2>&1 if [ $? = 0 ] then # # If ps' return value is 0 it means it ran ok which indicates that the # PID still exists. This means the process wasn't killed properly with # the signal provided. Print [FAILED] # print_status failure else # # If the return value was 1 or higher it means the PID didn't exist # anymore which means it was killed successfully. Remove possible stale # PID file and print [ OK ] # /bin/rm -f /var/run/$base.pid print_status success fi fi else # # The PID didn't exist so we can't attempt to kill it. Print [ ATTN ] # $SET_WCOL echo -n "Not running" print_status warning fi } # # The reloadproc functions sends a signal to a daemon telling it to # reload it's configuration file. This is almost identical to the # killproc function with the exception that it won't try to kill it with # a -KILL signal (aka -9) # reloadproc() { # # If no parameters are given to the print_status function, print usage # information. # if [ $# = 0 ] then echo "Usage: reloadproc {program} [signal]" exit 1 fi # # Find the basename of the first parameter (the daemon's name without # the path that was provided so /usr/sbin/syslogd becomes plain 'syslogd' # after basename ran) # base=$(/usr/bin/basename $1) # # Check if we gave a signal to send to the process (like -HUP) # to this function (the second parameter). If no second # parameter was provided set the nolevel variable. Else set the # killlevel variable to the value of $2 (the second parameter) # if [ -n "$2" ] then killlevel=-$2 else nolevel=1 fi # # the pidlist variable will contains the output of the pidof command. # pidof will try to find the PID's that belong to a certain string; # $base in this case # pidlist=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $base) pid="" for apid in $pidlist do if [ -d /proc/$apid ] then pid="$pid $apid" fi done # # If $pid contains something from the previous for loop it means one or # more PID's were found that belongs to the processes to be reloaded # if [ -n "$pid" ] then # # If nolevel was set we will use the default reload signal SIGHUP. # if [ "$nolevel" = 1 ] then /bin/kill -SIGHUP $pid evaluate_retval else # # Else we will use the provided signal # /bin/kill $killlevel $pid evaluate_retval fi else # # If $pid is empty no PID's have been found that belong to the process. # Print [ ATTN ] # $SET_WCOL echo -n "Not running" print_status warning fi } # # The statusproc function will try to find out if a process is running # or not # statusproc() { # # If no parameters are given to the print_status function, print usage # information. # if [ $# = 0 ] then echo "Usage: status {program}" return 1 fi # # $pid will contain a list of PID's that belong to a process # pid=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $1) if [ -n "$pid" ] then # # If $pid contains something, the process is running, print the contents # of the $pid variable # echo "$1 running with Process ID $pid" return 0 fi # # If $pid doesn't contain it check if a PID file exists and inform the # user about this stale file. # if [ -f /var/run/$1.pid ] then pid=$(/usr/bin/head -1 /var/run/$1.pid) if [ -n "$pid" ] then echo "$1 not running but /var/run/$1.pid exists" return 1 fi else echo "$1 is not running" fi } # End /etc/init.d/functions EOF ===== Creating the checkfs script ===== #cat > /etc/init.d/checkfs << "EOF" #!/bin/sh # Begin /etc/init.d/checkfs # # Include the functions declared in the /etc/init.d/functions file # source /etc/init.d/functions # # Activate all the swap partitions declared in the /etc/fstab file # echo -n "Activating swap..." /sbin/swapon -a evaluate_retval # # If the /fastboot file exists we don't want to run the partition checks # if [ -f /fastboot ] then echo "Fast boot, no file system check" else # # Mount the root partition read-only (just in case the kernel mounts it # read-write and we don't want to run fsck on a read-write mounted # partition). # /bin/mount -n -o remount,ro / if [ $? = 0 ] then # # If the /forcefsck file exists we want to force a partition check even # if the partition was unmounted cleanly the last time # if [ -f /forcefsck ] then echo -n "/forcefsck exists, forcing " echo "file system check" force="-f" else force="" fi # # Check all the file systems mentioned in /etc/fstab that have the # fs_passno value set to 1 or 2 (the 6th field. See man fstab for more # info) # echo "Checking file systems..." /sbin/fsck $force -a -A -C -T # # If something went wrong during the checks of one of the partitions, # fsck will exit with a return value greater than 1. If this is # the case we start sulogin so you can repair the damage manually # if [ $? -gt 1 ] then $FAILURE echo echo -n "fsck failed. Please repair your file " echo "systems manually by running /sbin/fsck" echo "without the -a option" echo echo -n "Please note that the root file system " echo "is currently mounted in read-only mode." echo echo -n "I will start sulogin now. When you " echo "logout I will reboot your system." echo $NORMAL /sbin/sulogin /sbin/reboot -f else print_status success fi else # # If the remount to read-only mode didn't work abort the fsck and print # an error # echo -n "Cannot check root file system because it " echo "could not be mounted in read-only mode." fi fi # End /etc/init.d/checkfs EOF ===== Creating the halt script ===== #cat > /etc/init.d/halt << "EOF" #!/bin/sh # Begin /etc/init.d/halt # # Call halt. See man halt for the meaning of the parameters # /sbin/halt -d -f -i -p # End /etc/init.d/halt EOF ===== Creating the loadkeys script ===== #cat > /etc/init.d/loadkeys << "EOF" #!/bin/sh # Begin /etc/init.d/loadkeys # # Include the functions declared in the /etc/init.d/functions file # source /etc/init.d/functions # # Include /etc/sysconfig/keyboard which contains the LAYOUT variable # source /etc/sysconfig/keyboard # # Load the default keymap file # echo -n "Loading keymap..." /bin/loadkeys $LAYOUT 2>/dev/null evaluate_retval # End /etc/init.d/loadkeys EOF ===== Creating the /etc/sysconfig/keyboard file ===== #cat > /etc/sysconfig/keyboard << "EOF" # Begin /etc/sysconfig/keyboard LAYOUT= # End /etc/sysconfig/keyboard EOF ※ == /usr/share/kbd/keymaps/i386/qwerty/us.map.gz ===== Creating the mountfs script ===== #cat > /etc/init.d/mountfs << "EOF" #!/bin/sh # Begin /etc/init.d/mountfs # # Include the functions declared in the /etc/init.d/functions file # source /etc/init.d/functions case "$1" in start) # # Remount the root partition in read-write mode. -n tells mount # not to # write to the /etc/mtab file (because it can't do this. The # root # partition is most likely still mounted in read-only mode # echo -n "Remounting root file system in read-write mode..." /bin/mount -n -o remount,rw / evaluate_retval # # First empty the /etc/mtab file. Then remount root partition # in read-write # mode again but pass -f to mount. This way mount does # everything # except the mount itself. This is needed for it to write to the # mtab # file which contains a list of currently mounted file systems. # echo > /etc/mtab /bin/mount -f -o remount,rw / # # Remove the possible /fastboot and /forcefsck files. they are # only # supposed to be used during the next reboot's checkfs which just # happened. If you want to fastboot or forcefsck again you'll # have to # recreate the files # /bin/rm -f /fastboot /forcefsck # # Walk through /etc/fstab and mount all file systems that don't # have the noauto option set in the fs_mntops field (the 4th # field. # See man fstab for more info) # echo -n "Mounting other file systems..." /bin/mount -a evaluate_retval ;; stop) # # Deactivate all the swap partitions # echo -n "Deactivating swap..." /sbin/swapoff -a evaluate_retval # # And unmount all the file systems, mounting the root file # system # read-only (all are unmounted but because root can't be # unmounted # at this point mount will automatically mount it read-only # which # is what supposed to happen. This way no data can be written # anymore from disk) # echo -n "Unmounting file systems..." /bin/umount -a -r evaluate_retval ;; *) echo "Usage: $0 {start|stop}" exit 1 ;; esac # End /etc/init.d/mountfs EOF ===== Creating the reboot script ===== #cat > /etc/init.d/reboot << "EOF" #!/bin/sh # Begin /etc/init.d/reboot # # Call reboot. See man halt for the meaning of the parameters # echo "System reboot in progress..." /sbin/reboot -d -f -i # End /etc/init.d/reboot EOF ===== Creating the sendsignals script ===== #cat > /etc/init.d/sendsignals << "EOF" #!/bin/sh # Begin /etc/init.d/sendsignals # # Include the functions declared in the /etc/init.d/functions file # source /etc/init.d/functions # # Send all the remaining processes the TERM signal # echo -n "Sending all processes the TERM signal..." /sbin/killall5 -15 evaluate_retval # # Send all the remaining process (after sending them the TERM signal # before) the KILL signal. # echo -n "Sending all processes the KILL signal..." /sbin/killall5 -9 evaluate_retval # End /etc/init.d/sendsignals EOF ===== Creating the setclock script ===== #cat > /etc/init.d/setclock << "EOF" #!/bin/sh # Begin /etc/init.d/setclock # # Include the functions declared in the /etc/init.d/functions file # and include the variables from the /etc/sysconfig/clock file # source /etc/init.d/functions source /etc/sysconfig/clock # # Right now we want to set the kernel clock according to the hardware # clock, so we use the -hctosys parameter. # CLOCKPARAMS="--hctosys" # # If the UTC variable is set in the /etc/sysconfig/clock file, add the # -u parameter as well which tells hwclock that the hardware clock is # set to UTC time instead of local time. # case "$UTC" in yes|true|1) CLOCKPARAMS="$CLOCKPARAMS --utc" ;; no|false|0) CLOCKPARAMS="$CLOCKPARAMS --localtime" ;; esac echo -n "Setting clock..." /sbin/hwclock $CLOCKPARAMS evaluate_retval # End /etc/init.d/setclock EOF ===== Creating the /etc/sysconfig/clock file ===== #cat > /etc/sysconfig/clock << "EOF" # Begin /etc/sysconfig/clock UTC=0 # End /etc/sysconfig/clock EOF ===== Creating the sysklogd script ===== #cat > /etc/init.d/sysklogd << "EOF" #!/bin/sh # Begin /etc/init.d/sysklogd # # Include the functions declared in the /etc/init.d/functions file # source /etc/init.d/functions case "$1" in start) echo -n "Starting system log daemon..." loadproc /usr/sbin/syslogd -m 0 echo -n "Starting kernel log daemon..." loadproc /usr/sbin/klogd ;; stop) echo -n "Stopping kernel log daemon..." killproc klogd echo -n "Stopping system log daemon..." killproc syslogd ;; reload) echo -n "Reloading system log daemon configuration file..." reloadproc syslogd 1 ;; restart) $0 stop /usr/bin/sleep 1 $0 start ;; status) statusproc /usr/sbin/syslogd statusproc /usr/sbin/klogd ;; *) echo "Usage: $0 {start|stop|reload|restart|status}" exit 1 ;; esac # End /etc/init.d/sysklogd EOF ===== Creating the template script ===== #cat > /etc/init.d/template << "EOF" #!/bin/sh # Begin /etc/init.d/ # # Include the functions declared in the /etc/init.d/functions file # source /etc/init.d/functions case "$1" in start) echo -n "Starting ..." loadproc ;; stop) echo -n "Stopping ..." killproc ;; reload) echo -n "Reloading ..." reloadproc ;; restart) $0 stop /usr/bin/sleep 1 $0 start ;; status) statusproc ;; *) echo "Usage: $0 {start|stop|reload|restart|status}" exit 1 ;; esac # End /etc/init.d/ EOF ====== 환경 설정 파일 생성 ====== ===== Creating the localnet script ===== #cat > /etc/init.d/localnet << "EOF" #!/bin/sh # Begin /etc/init.d/localnet # # Include the functions declared in the /etc/init.d/functions file # and include the variables from the /etc/sysconfig/network file. # source /etc/init.d/functions source /etc/sysconfig/network case "$1" in start) echo -n "Bringing up the loopback interface..." /sbin/ifconfig lo 127.0.0.1 evaluate_retval echo -n "Setting up hostname..." /bin/hostname $HOSTNAME evaluate_retval ;; stop) echo -n "Bringing down the loopback interface..." /sbin/ifconfig lo down evaluate_retval ;; restart) $0 stop sleep 1 $0 start ;; *) echo "Usage: $0: {start|stop|restart}" exit 1 ;; esac # End /etc/init.d/localnet EOF ===== Creating the /etc/sysconfig/network file ===== #echo "HOSTNAME=lfs" > /etc/sysconfig/network ===== Creating the /etc/hosts file ===== #cat > /etc/hosts << "EOF" # Begin /etc/hosts (no network card version) 127.0.0.1 www.mydomain.com localhost # End /etc/hosts (no network card version) EOF #cat > /etc/hosts << "EOF" # Begin /etc/hosts (network card version) 127.0.0.1 localhost.localdomain localhost 192.168.1.1 www.mydomain.org # End /etc/hosts (network card version) EOF ===== Creating the ethnet script ===== #cat > /etc/init.d/ethnet << "EOF" #!/bin/sh # Begin /etc/init.d/ethnet # # Main script by Gerard Beekmans - gerard@linuxfromscratch.org # GATEWAY check by Jean-Francois Le Ray - jfleray@club-internet.fr # "Specify which IF to use to reach default GATEWAY" by # Graham Cantin - gcantin@pacbell.net # # # Include the functions declared in the /etc/init.d/functions file # and the variables from the /etc/sysconfig/network file. # source /etc/init.d/functions source /etc/sysconfig/network case "$1" in start) # # Obtain all the network card configuration files # for interface in $(/bin/ls /etc/sysconfig/nic-config/ifcfg* | \ grep -v ifcfg-lo) do # # Load the variables from that file # source $interface # # If the ONBOOT variable is set to yes, process this file and bring the # interface up. # if [ "$ONBOOT" == yes ] then echo -n "Bringing up the $DEVICE interface..." /sbin/ifconfig $DEVICE $IP broadcast $BROADCAST \ netmask $NETMASK evaluate_retval fi done # # If the /etc/sysconfig/network file contains a GATEWAY variable, set # the default gateway and the interface through which the default # gateway can be reached. # if [ "$GATEWAY" != "" ]; then echo -n "Setting up routing for $GATEWAY_IF interface..." /sbin/route add default gateway $GATEWAY \ metric 1 dev $GATEWAY_IF evaluate_retval fi ;; stop) # # Obtain all the network card configuration files # for interface in $(/bin/ls /etc/sysconfig/nic-config/ifcfg* | \ grep -v ifcfg-lo) do # # Load the variables from that file # source $interface # # If the ONBOOT variable is set, process the file and bring the # interface down # if [ $ONBOOT == yes ] then echo -n "Bringing down the $DEVICE interface..." /sbin/ifconfig $DEVICE down evaluate_retval fi done ;; restart) $0 stop sleep 1 $0 start ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 ;; esac # End /etc/init.d/ethnet EOF ===== Adding default gateway to /etc/sysconfig/network ===== #cat >> /etc/sysconfig/network << "EOF" GATEWAY=192.168.1.2 GATEWAY_IF=eth0 EOF ===== Creating NIC configuration files ===== #mkdir /etc/sysconfig/nic-config #cat > /etc/sysconfig/nic-config/ifcfg-eth0 << "EOF" ONBOOT=yes DEVICE=eth0 IP=192.168.1.1 NETMASK=255.255.255.0 BROADCAST=192.168.1.255 EOF ===== Setting up symlinks and permissions ===== #cd /etc/init.d && chmod 754 rc rcS functions checkfs halt loadkeys mountfs reboot && chmod 754 sendsignals setclock sysklogd template && chmod 754 localnet ethnet && cd ../rc0.d && ln -sf ../init.d/ethnet K800ethnet && ln -sf ../init.d/sysklogd K900sysklogd && ln -sf ../init.d/sendsignals S800sendsignals && ln -sf ../init.d/mountfs S900mountfs && ln -sf ../init.d/halt S999halt && cd ../rc6.d && ln -sf ../init.d/ethnet K800ethnet && ln -sf ../init.d/sysklogd K900sysklogd && ln -sf ../init.d/sendsignals S800sendsignals && ln -sf ../init.d/mountfs S900mountfs && ln -sf ../init.d/reboot S999reboot && cd ../rcS.d && ln -sf ../init.d/localnet S100localnet && ln -sf ../init.d/checkfs S200checkfs && ln -sf ../init.d/mountfs S300mountfs && ln -sf ../init.d/setclock S400setclock && ln -sf ../init.d/loadkeys S500loadkeys && cd ../rc1.d && ln -sf ../init.d/ethnet K800ethnet && ln -sf ../init.d/sysklogd K900sysklogd && cd ../rc2.d && ln -sf ../init.d/sysklogd S100sysklogd && ln -sf ../init.d/ethnet K800ethnet && cd ../rc3.d && ln -sf ../init.d/sysklogd S100sysklogd && ln -sf ../init.d/ethnet S200ethnet && cd ../rc4.d && ln -sf ../init.d/sysklogd S100sysklogd && ln -sf ../init.d/ethnet S200ethnet && cd ../rc5.d && ln -sf ../init.d/sysklogd S100sysklogd && ln -sf ../init.d/ethnet S200ethnet ===== Creating the /etc/fstab file ===== #cat > /etc/fstab << "EOF" # Begin /etc/fstab # location of filesystem mount point fs-type options /dev/*LFS-partition device* / *fs-type* defaults 1 1 /dev/*swap-partition device* swap swap defaults 0 0 proc /proc proc defaults 0 0 # End /etc/fstab EOF ===== Installing a kernel 커널을 컴파일한다 ===== #cd /usr/src/linux && make mrproper && make menuconfig && make dep && make bzImage && make modules && make modules_install && cp arch/i386/boot/bzImage /boot/lfskernel && cp System.map /boot ===== Making the LFS system bootable ===== #logout #cp $LFS/boot/lfskernel /boot #cat >> /etc/lilo.conf << "EOF" image=/boot/lfskernel label=lfs root= read-only EOF #/sbin/lilo #cp /etc/lilo.conf $LFS/etc && cp $LFS/boot 길고긴 설치 과정이 끝났다. 이제 제대로 부팅이 되는지 확인해본다. ---- {{indexmenu>:#1|skipns=/^(wiki|etc|diary|playground)$/ skipfile=/^(about|guestbook|todays)$/ }} ----