Linux From Scratch X: Preparando la compilación del sistema definitivo

Después del breve resumen que he hecho en mi anterior post, ha llegado el momento de empezar a compilar definitivamente nuestro Linux From Scratch. Ya tenemos un sistema temporal que permite hacer la compilación sin que influya nuestro sistema operativo, así que es momento de pasar al siguiente capítulo del libro.

Preparando el sistema para hacer chroot

Lo que vamos a hacer ahora es crear un entorno similar al de una distribución de linux, con los ficheros y directorios más básicos de manera que podamos hacer un chroot y trabajar en ese entorno. Las herramientas que contendrá el entorno serán las del sistema temporal y las usaremos para compilar todo el sistema.

En primer lugar y siempre según el libro, creamos los directorios /dev, /proc y /sys. Todos los pasos a partir de ahora hay que hacerlos como root.

[lfs@corellia ~]$ su
Password: 
[root@corellia lfs]# mkdir -v $LFS/{dev,proc,sys}
mkdir: created directory '/mnt/lfs/dev'
mkdir: created directory '/mnt/lfs/proc'
mkdir: created directory '/mnt/lfs/sys'
[root@corellia lfs]#

Los directorios se crean en /mnt/lfs usando la variable LFS. Esto es porque ahí es donde hemos montado la partición y donde vamos a hacer el chroot, de manera que cuando hayamos hecho chroot el directorio /mnt/lfs se convertirá en /.

El siguiente paso es crear los ficheros /dev/null y /dev/console. El kernel necesita estos ficheros para arrancar.

[root@corellia lfs]# mknod -m 600 $LFS/dev/console c 5 1
[root@corellia lfs]# mknod -m 666 $LFS/dev/null c 1 3
[root@corellia lfs]#

Ahora hay que montar los directorios /dev, /dev/pts, /proc y /sys. Estos directorios los proporciona el kernel llenándolos automáticamente con información sobre los dispositivos detectados, los procesos existentes y datos sobre el sistema. La única excepción es /dev. Éste lo proporciona udev, pero nuestro sistema no tiene udev todavía, así que lo montamos con bind para que use el /dev de nuestra distro.

[root@corellia lfs]# mount -v --bind /dev $LFS/dev
mount: /dev binded on /mnt/lfs/dev
[root@corellia lfs]# mount -vt devpts devpts $LFS/dev/pts
mount: devpts mounted on /mnt/lfs/dev/pts
[root@corellia lfs]# mount -vt proc proc $LFS/proc
mount: proc mounted on /mnt/lfs/proc
[root@corellia lfs]# mount -vt sysfs sysfs $LFS/sys
mount: sysfs mounted on /mnt/lfs/sys
[root@corellia lfs]#

Otro directorio que hay que montar es /dev/shm. Este directorio se usa para memoria compartida y en algunos sistemas es un enlace a /run/shm, lo cual nos podría dar problemas porque nuestro Linux From Scratch todavía no tiene /run/shm, así que si fuera así habría que cambiarlo.

En mi caso, en mi sistema ArchLinux no es un enlace, sino un directorio normal y corriente, pero de todos modos voy a poner el comando completo según viene en el libro, aunque yo podría omitir el if.

[root@corellia lfs]# if [ -h /dev/shm ]; then
>    rm -f $LFS/dev/shm
>    mkdir $LFS/dev/shm
> fi
[root@corellia lfs]# mount -vt tmpfs shm $LFS/dev/shm
mount: shm mounted on /mnt/lfs/dev/shm
[root@corellia lfs]#

Dentro del chroot

Ya estamos en posición de entrar en el chroot y continuar el resto de la instalación desde ahí.

[root@corellia lfs]# chroot "$LFS" /tools/bin/env -i \
>     HOME=/root                  \
>     TERM="$TERM"                \
>     PS1='\u:\w\$ '              \
>     PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
>     /tools/bin/bash --login +h
I have no name!:/#

El pobre se nos queja de que no tiene nombre porque el fichero /etc/passwd no está creado todavía. 🙂 Esto no tiene ninguna importancia. Lo crearemos pronto.

Es de destacar aquí que usamos env para controlar las variables de entorno que le pasamos al shell igual que hicimos anteriormente en el fichero .bash_profile, y la opción +h que le pasamos al shell para desactivar el hash.

A continuación vamos a crear la estructura de directorios típica de un sistema linux mínimo.

I have no name!:/# mkdir -pv /{bin,boot,etc/{opt,sysconfig},home,lib,mnt,opt,run}
mkdir: created directory '/bin'
mkdir: created directory '/boot'
mkdir: created directory '/etc'
mkdir: created directory '/etc/opt'
mkdir: created directory '/etc/sysconfig'
mkdir: created directory '/home'
mkdir: created directory '/lib'
mkdir: created directory '/mnt'
mkdir: created directory '/opt'
mkdir: created directory '/run'
I have no name!:/# mkdir -pv /{media/{floppy,cdrom},sbin,srv,var}
mkdir: created directory '/media'
mkdir: created directory '/media/floppy'
mkdir: created directory '/media/cdrom'
mkdir: created directory '/sbin'
mkdir: created directory '/srv'
mkdir: created directory '/var'
I have no name!:/# install -dv -m 0750 /root
install: creating directory '/root'
I have no name!:/# install -dv -m 1777 /tmp /var/tmp
install: creating directory '/tmp'
install: creating directory '/var/tmp'
I have no name!:/# mkdir -pv /usr/{,local/}{bin,include,lib,sbin,src}
mkdir: created directory '/usr'
mkdir: created directory '/usr/bin'
mkdir: created directory '/usr/include'
mkdir: created directory '/usr/lib'
mkdir: created directory '/usr/sbin'
mkdir: created directory '/usr/src'
mkdir: created directory '/usr/local'
mkdir: created directory '/usr/local/bin'
mkdir: created directory '/usr/local/include'
mkdir: created directory '/usr/local/lib'
mkdir: created directory '/usr/local/sbin'
mkdir: created directory '/usr/local/src'
I have no name!:/# mkdir -pv /usr/{,local/}share/{doc,info,locale,man}
mkdir: created directory '/usr/share'
mkdir: created directory '/usr/share/doc'
mkdir: created directory '/usr/share/info'
mkdir: created directory '/usr/share/locale'
mkdir: created directory '/usr/share/man'
mkdir: created directory '/usr/local/share'
mkdir: created directory '/usr/local/share/doc'
mkdir: created directory '/usr/local/share/info'
mkdir: created directory '/usr/local/share/locale'
mkdir: created directory '/usr/local/share/man'
I have no name!:/# mkdir -v  /usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir: created directory '/usr/share/misc'
mkdir: created directory '/usr/share/terminfo'
mkdir: created directory '/usr/share/zoneinfo'
mkdir: created directory '/usr/local/share/misc'
mkdir: created directory '/usr/local/share/terminfo'
mkdir: created directory '/usr/local/share/zoneinfo'
I have no name!:/# mkdir -pv /usr/{,local/}share/man/man{1..8}
mkdir: created directory '/usr/share/man/man1'
mkdir: created directory '/usr/share/man/man2'
mkdir: created directory '/usr/share/man/man3'
mkdir: created directory '/usr/share/man/man4'
mkdir: created directory '/usr/share/man/man5'
mkdir: created directory '/usr/share/man/man6'
mkdir: created directory '/usr/share/man/man7'
mkdir: created directory '/usr/share/man/man8'
mkdir: created directory '/usr/local/share/man/man1'
mkdir: created directory '/usr/local/share/man/man2'
mkdir: created directory '/usr/local/share/man/man3'
mkdir: created directory '/usr/local/share/man/man4'
mkdir: created directory '/usr/local/share/man/man5'
mkdir: created directory '/usr/local/share/man/man6'
mkdir: created directory '/usr/local/share/man/man7'
mkdir: created directory '/usr/local/share/man/man8'
I have no name!:/# for dir in /usr /usr/local; do
>   ln -sv share/{man,doc,info} $dir
> done
'/usr/man' -> 'share/man'
'/usr/doc' -> 'share/doc'
'/usr/info' -> 'share/info'
'/usr/local/man' -> 'share/man'
'/usr/local/doc' -> 'share/doc'
'/usr/local/info' -> 'share/info'
I have no name!:/# case $(uname -m) in
>  x86_64) ln -sv lib /lib64 && ln -sv lib /usr/lib64 ;;
> esac
'/lib64' -> 'lib'
'/usr/lib64' -> 'lib'
I have no name!:/# mkdir -v /var/{log,mail,spool}
mkdir: created directory '/var/log'
mkdir: created directory '/var/mail'
mkdir: created directory '/var/spool'
I have no name!:/# ln -sv /run /var/run
'/var/run' -> '/run'
I have no name!:/# ln -sv /run/lock /var/lock
'/var/lock' -> '/run/lock'
I have no name!:/# mkdir -pv /var/{opt,cache,lib/{misc,locate},local}
mkdir: created directory '/var/opt'
mkdir: created directory '/var/cache'
mkdir: created directory '/var/lib'
mkdir: created directory '/var/lib/misc'
mkdir: created directory '/var/lib/locate'
mkdir: created directory '/var/local'
I have no name!:/#

Eso ha sido largo. 🙂 Lo más llamativo de esto son los dos comandos install que hay al principio. El primero crea el directorio /root con permisos sólo para el root, ya que de lo contrario todo el mundo podría entrar en él. El segundo crea el directorio /tmp con permisos para todo el mundo, ya que todo el mundo tiene que poder leer y escribir en ese directorio, pero con el sticky bit activado para que los usuarios sólo puedan borrar sus propios ficheros.

Vamos a ver qué aspecto tiene el directorio raíz de mi Linux From Scratch después de esto.

I have no name!:/# ls -l /
total 84
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 bin
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 boot
drwxr-xr-x  19    0 0  3240 Jan  7 10:18 dev
drwxr-xr-x   4    0 0  4096 Jan  7 17:18 etc
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 home
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 lib
lrwxrwxrwx   1    0 0     3 Jan  7 17:22 lib64 -> lib
drwx------   2    0 0 16384 Dec 12 21:55 lost+found
drwxr-xr-x   4    0 0  4096 Jan  7 17:18 media
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 mnt
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 opt
dr-xr-xr-x 163    0 0     0 Jan  7 10:16 proc
drwxr-x---   2    0 0  4096 Jan  7 17:18 root
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 run
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 sbin
drwxrwxrwt   2 1001 0  4096 Dec 29 15:33 sources
drwxr-xr-x   2    0 0  4096 Jan  7 17:18 srv
dr-xr-xr-x  13    0 0     0 Jan  7 10:16 sys
drwxrwxrwt   2    0 0  4096 Jan  7 17:19 tmp
drwxr-xr-x  12    0 0  4096 Dec 29 16:06 tools
drwxr-xr-x   9    0 0  4096 Jan  7 17:22 usr
drwxr-xr-x  10    0 0  4096 Jan  7 17:23 var
I have no name!:/#

Me gusta. 🙂

Ahora hay que crear enlaces a algunos comandos que estan en /tools, porque hay herramientas que los buscan en /bin y no los tenemos ahí todavía.

I have no name!:/# ln -sv /tools/bin/{bash,cat,echo,pwd,stty} /bin
'/bin/bash' -> '/tools/bin/bash'
'/bin/cat' -> '/tools/bin/cat'
'/bin/echo' -> '/tools/bin/echo'
'/bin/pwd' -> '/tools/bin/pwd'
'/bin/stty' -> '/tools/bin/stty'
I have no name!:/# ln -sv /tools/bin/perl /usr/bin
'/usr/bin/perl' -> '/tools/bin/perl'
I have no name!:/# ln -sv /tools/lib/libgcc_s.so{,.1} /usr/lib
'/usr/lib/libgcc_s.so' -> '/tools/lib/libgcc_s.so'
'/usr/lib/libgcc_s.so.1' -> '/tools/lib/libgcc_s.so.1'
I have no name!:/# ln -sv /tools/lib/libstdc++.so{,.6} /usr/lib
'/usr/lib/libstdc++.so' -> '/tools/lib/libstdc++.so'
'/usr/lib/libstdc++.so.6' -> '/tools/lib/libstdc++.so.6'
I have no name!:/# sed 's/tools/usr/' /tools/lib/libstdc++.la > /usr/lib/libstdc++.la
I have no name!:/# ln -sv bash /bin/sh
'/bin/sh' -> 'bash'
I have no name!:/#

A continuación hay que crear tres ficheros importantes: el /etc/mtab, que contiene información sobre los sistemas de ficheros que hay montados, el /etc/passwd, que contiene las cuentas de los usuarios que existen en el sistema, incluyendo usuarios especiales, y el /etc/group, que contiene los grupos que hay en el sistema.

I have no name!:/# touch /etc/mtab
I have no name!:/# cat > /etc/passwd << "EOF"
> root:x:0:0:root:/root:/bin/bash
> bin:x:1:1:bin:/dev/null:/bin/false
> nobody:x:99:99:Unprivileged User:/dev/null:/bin/false
> EOF
I have no name!:/# cat > /etc/group << "EOF"
> root:x:0:
> bin:x:1:
> sys:x:2:
> kmem:x:3:
> tape:x:4:
> tty:x:5:
> daemon:x:6:
> floppy:x:7:
> disk:x:8:
> lp:x:9:
> dialout:x:10:
> audio:x:11:
> video:x:12:
> utmp:x:13:
> usb:x:14:
> cdrom:x:15:
> mail:x:34:
> nogroup:x:99:
> EOF
I have no name!:/#

El mtab se crea vacío, ya que no vamos a montar ningún sistema de ficheros más. Sin embargo tiene que existir porque algunos programas esperan encontrarlo. Los otros dos se crean con los usuarios y grupos especiales que los autores de Linux From Scratch han decidido usar. El más importante de todos en este momento es el root, que es el usuario con el que vamos a trabajar.

Ahora que ya tenemos un fichero passwd con un usuario root, el shell debería encontrar el nombre, así que lanzamos un nuevo shell para que lea los ficheros y desaparezca lo de I have no name.

I have no name!:/# exec /tools/bin/bash --login +h
root:/#

¡Perfecto! Ya lo hemos bautizado. 🙂 Sólo falta crear algunos ficheros de log para que los programas que los usan los encuentren.

root:/# touch /var/log/{btmp,lastlog,wtmp}
root:/# chgrp -v utmp /var/log/lastlog
changed group of '/var/log/lastlog' from root to utmp
root:/# chmod -v 664  /var/log/lastlog
mode of '/var/log/lastlog' changed from 0644 (rw-r--r--) to 0664 (rw-rw-r--)
root:/# chmod -v 600  /var/log/btmp
mode of '/var/log/btmp' changed from 0644 (rw-r--r--) to 0600 (rw-------)
root:/#

Y con esto queda todo listo para empezar a instalar paquetes. En el siguiente post empezaré por los headers del API de linux.

EOF