Um Diário da Minha Experiência no Linux From Scratch (LFS)
Esse post foi originalmente publicado no meu blog antigo entre 5 e 17 de Setembro de 2013.
Na época eu resolvi seguir o tutorial do Linux From Scratch (LFS), e conforme seguia os passos do tutorial, fui anotando algumas observações e problemas que encontrei. Talvez esse relato possa ser útil caso você também esteja interessado nesse tutorial.
Mas o que é o Linux From Scratch? O LFS é um livro/tutorial detalhando passo a passo como criar sua própria distribuição Linux do zero, desde a criação de uma partição no disco para a instalação, passando pela criação da toolchain usada para compilar os pacotes, até a compilação e instalação dos pacotes em si, tudo a partir do código-fonte. Esse tutorial não requere conhecimento de programação, mas é recomendado que o usuário já tenha alguma familiaridade com Linux.
O relato está incompleto, não sei porque, já que cheguei a completar a instalação, mas isso é o que encontrei. Talvez algumas coisas que eu digo abaixo também não façam muito sentido, já que na época meu entendimento sobre Linux era mais limitado do que é hoje.
LFS: Dia 1 - 7/3/13
Finalmente comecei o LFS, hoje, com o livro versão 7.2. Para dizer que
realmente comecei apenas executei o script que checa as versões dos programas
básicos que tenho que ter no meu computador hospedeiro. Estou usando um
Debian 6. Tive que instalar o bison
e o gawk
. No caso do gawk
, já tinha
instalado o mawk
, que dizem ser mais rápido, porém não é recomendado para
o LFS. Ainda tive que criar um link simbólico em /bin/awk
para /bin/gawk
.
LFS: Dia 2 - 8/3/13
Comecei a fazer algo de fato. Instalei o GParted para redimensionar minhas partições, mas quando fui ver elas já estavam estruturadas de uma boa forma, e eu já tinha uma partição livre de 4,7GB formatada como ext3 (acho que já tinha deixado ela para o LFS desde a última vez que formatei o computador - algo que tenho feito com alguma frequência).
Após isso, tive que usar o programa mke2fs
do pacote e2fsprogs
para criar um
sistema de arquivos ext3 na minha partição LFS (embora já estivesse criado,
resolvi sobrescrever para passar pelo processo e para garantir que tudo
ficaria igual ao livro). Bom, entendi errado uma nota do livro sobre usar o
debugfs
, e acabei achando que eu precisava compilar o e2fsprogs
dos fontes
(não precisava no meu caso). A compilação foi rápida e fácil, porém nunca havia
compilado um pacote no Linux a partir dos fontes, demorou alguns segundos a
compilação, mais do que eu estou acostumado quando compilo meus projetos com
20 arquivos fontes em C++.
Depois montei a partição.
Próximo passo, baixar os arquivos. São quase 1GB de arquivos, então acho que
deixarei baixando por umas horas ou minutos. Usei o arquivo wget-list
que
eles disponibilizam no site do LFS para facilitar o processo de download usando
o programa wget
. O wget
baixa uma lista de arquivos se receber como
parâmetro um arquivo que contenha o nome desses arquivos (um em cada linha).
Mais um comando útil aprendido.
Na verdade o download foi rápido, 307MB, 15min 24s. Então percebi que eu
havia usado o wget-list
do livro 7.3, porque as versões dos pacotes estavam
maiores que as do livro 7.2. Então resolvi baixar o livro novo (7.3) e dar uma
olhada para ver se precisava fazer algo diferente. Rodei o version-check.sh
do livro novo para ver se meu sistema hospedeiro ainda é atualizado o bastante
para essa versão do LFS. Felizmente tudo correu bem.
Agora preciso executar os MD5 sums para ver se os pacotes foram baixados
corretamente. Novamente existe um arquivo no site deles com as MD5 sums, então
com um comando tudo é checado. Na hora de fazer o checksum, o pacote
lfs-bootscripts
não passou. Procurei no Google pelo pacote na versão
indicada no livro, encontrei, baixei, e ele passou no checksum. Bom, por hoje é
só, no próximo dia vou para o início do capítulo 4.
LFS: Dia 3 - 9/3/13
Hoje tive que criar o diretório tools
. É importante lembrar de verificar se
a variável LFS
está setada e se a partição está montada. Após criar o
diretório, foram criados um usuário lfs
e um grupo lfs
. Um arquivo
bash_profile
foi criado para garantir que o ambiente será limpo quando
logado no shell com esse usuário. Não entendi o que o comando source
faz.
Tudo bem, vamos para o capítulo 5: Construindo um Sistema Temporário.
Antes de começar o processo de construir a toolchain, o livro reforça a
necessidade de garantir que você está usando o bash como shell e a
existência de alguns links simbólicos. Tive uma surpresa ao ver, usando o
comando file
, que o /usr/bin/awk
não apontava para o gawk
. Tinha certeza
que eu já havia criado esse link. O yacc
também não estava apontando para
o bison
. Removi o link e criei outro. O sh
também estava apontando para o
lugar errado: dash
ao invés de bash
. Para garantir que o shell usado era o
bash
tive que pesquisar, e descobri que podemos saber isso dando echo
na
variável $SHELL
.
Agora, hora de compilar o binutils
. Usei a recomendação do livro para medir o
tempo usando o programa time
, e colocando dentro dele tanto a chamada do
configure
quanto do make
e do make install
. Os resultados foram:
real 2m57.222s (177s)
user 2m42.906s (162s)
sys 0m32.010s (32s)
Então, minha SBU vale 177s, o que significa que devo demorar 3115s
(aproximadamente 52 minutos) para compilar o GCC, que é o maior pacote de
todos. Esqueci de executar os comandos dentro do diretório binutils-build
, o
que fez meus arquivos não ficarem nessa pasta. Removi os arquivos que foram
gerados na pasta sources manualmente e refiz da maneira correta.
real 2m53.382s (173s)
user 2m41.438s (161s)
sys 0m31.706s (31s)
Vou considerar esse novo tempo como minha SBU, que agora passa a ter 173s, o que reduz o tempo de compilação da GCC para 3045s (51 minutos). A instalação do pacote gerou vários arquivos e diretórios na pasta tools. Próximo passo: compilar o GCC.
LFS: Dia 4 - 10/3/13
Hoje é o dia de compilar o GCC (pass 1). Antes de começar o trabalho, sempre tenho que montar a partição do LFS, então resolvi criar um script para isso. Até a extração do GCC é demorada. No entanto a configuração, compilação e instalação demoraram muito menos que o esperado:
real 15m36.000s
user 14m19.018s
sys 1m48.811s
Será que correu tudo bem? Não faço a menor ideia. Chequei o diretório
tools
e notei que existem alguns arquivos novos lá, espero que tudo tenha
funcionado. A instalação dos Headers da API do Linux foi tranquila e rápida.
Perdi algum tempo checando se havia alguma coisa nova no diretório da
toolchain (tools
). Depois, hora de completar o primeiro pass
compilando a
glibc. A compilação foi bem demorada (mais demorada que do GCC):
real 18m53.522s
user 17m1.896s
sys 2m50.755s
A próxima etapa é começar o pass 2.
LFS: Dia 5 - 23/3/13
Hoje começa o binutils pass 2. Relembrando: antes de começar, montar a
partição do LFS e logar com o usuário lfs
. Extrair o arquivo do binutils
e entrar na pasta gerada. Para lembrar o comando tar
necessário para extrair
o binutils (que estava no formato .tar.bz2) usei o comando:
$ history | grep tar
que mostra os últimos comandos no histórico desse usuário contendo o termo
tar
. A compilação demorou menos de 7 minutos.
Tive dúvida se deveria ou não executar os testes do pacote, e como executar. Após uma busca no livro notei que anteriormente o autor fala que não é necessário testar as ferramentas compiladas no sistema temporário do capítulo 5.
LFS: Dia 6 - 28/4/13
Mais de um mês longe do LFS, resolvi voltar a fazê-lo. GCC pass 2. Bom, a
compilação foi a mais demorada que eu já vi, demorou mais de uma hora.
Infelizmente não usei o comando time
para medir o tempo. Após a longa
compilação, posso começar a compilação dos outros 23 pacotes da Toolchain.
O próximo pacote é o Tcl. Ele os 3 próximos pacotes são necessários para
rodar os testes. Após a instalação do Tcl, novamente chequei o diretório
/tools/lib
e notei que já haviam muitas libs lá, a maioria do dia que
compilei a GCC pass 1 e a glibc.
A esse ponto comecei a notar a importância de links simbólicos no Linux. Já tive que criar muitos até agora, e esse do Tcl me fez entender melhor o versionamento de shared objects (so) no Linux. Quando temos várias versões de libs instaladas, uma prática comum é a criação de um link simbólico para a versão padrão ou mais recente da lib.
Agora é hora de instalar o Expect
. Esse pacote será o menor de todos até
agora instalados, ocupando apenas uns 4,4MB. Realmente foi bem rápida a
compilação. Rodei o comando make test
e dos 26 testes 12 falharam, mas o
livro diz para não se preocupar com isso agora.
A compilação e instalação do pacote DejaGNU e Check foram rápidas. O teste do pacote Check foi um pouco demorado (cerca de 5 minutos). Em seguida instalei o pacote ncurses sem maiores problemas.
Estranhamente, após a instalação do pacote bash
, na tentativa de remover os
arquivos que restaram da extração dos fontes, alguns arquivos não tinham
permissão de escrita, com isso não era possível removê-los. Mudei a
permissão manualmente e removi os arquivos.
Os testes do coreutils são um pouco demorados. Um assustador aviso vermelho
dizendo 1 of 282 tests failed
apareceu. Vou imaginar que nessa fase isso é
normal. O mesmo problema de arquivos sem permissão de escrita ocorreu.
Após isso entrei num ritmo frenético de compilação e instalação de pacotes: diffutils, file, findutils, gawk, gettext, grep, gzip, m4, make, patch, perl, sed, tar, texinfo, xz. Tudo em sequência. Os mesmos passos: descompactar, entrar no diretório, configurar, compilar, testar, instalar, sair do diretório, remover fontes. As vezes era necessário mudar as permissões para remover os fontes.
Agora executei as instruções finais do capítulo para eliminar arquivos
desnecessários e liberar espaço, e também mudar as permissões do diretório da
toolchain. Daqui pra frente os comandos devem ser executados como usuário
root
(e não podemos nos esquecer de ter a variável $LFS
setada para esse
usuário). Caso eu pretenda usar essa toolchain para construir outros sistemas
LFS futuramente, o livro recomenda fazer o backup agora. Não sei se farei isso.
O que importa é que a próxima etapa é o início da construção do sistema LFS final
:D
LFS: Dia 7 - 29/4/13
Hoje resolvi fazer o backup do diretório tools
… Talvez eu queira usar a
toolchain novamente no futuro…
Bom, backup criado, usando um comando:
$ su root
# tar -cf ~/lfs/tools.tar $LFS/tools
Agora começo a iniciar a verdadeira construção do Linux. From scratch…
Começou um pouco nebuloso… Montei uns sistemas de arquivos e executei alguns comandos que não sei se estarão lá quando eu reiniciar a máquina… Mas vamos ver no próximo dia.
LFS: Dia 8 - 30/4/13
Percebi que os comandos mknod
que foram executados criaram um “arquivo”.
Executando o comando mount
para ver o que estava montado, vi que os sistemas
de arquivos que montei da última vez não estavam mais montados. Executei
novamente os comandos de montagem para dev, devpts, proc e sysfs, rodei
mount
e eles agora estavam lá. Executei também o comando com um if
que
monta o sistema de arquivos temporário shm.
A parte do livro que fala sobre atualização e gerenciamento de pacotes mostra que esse tema é muito mais complexo que eu imaginava. Vou ignorar isso, já que estou construindo o LFS para fins de aprendizado apenas.
O processo para copiar um LFS para outro computador (após finalizado) parece
ser razoavelmente simples: uma cópia da raiz do LFS usando tar
, extração do
tar para a partição na nova máquina, alteração de alguns arquivos e tornar
o sistema “bootável”.
Vou parar por aqui, o próximo passo é entrar no ambiente via chroot
. O livro
nos lembra que é preciso montar o sistema de arquivos do Kernel Virtual e fazer
chroot sempre que o computador for reiniciado, para executar os comandos à
frente. Para sair do ambiente chroot é simples:
$ logout
Resolvi continuar um pouco mais por hoje. Está ficando empolgante agora que o sistema está começando a tomar forma.
Para evitar digitar muitos comandos toda vez que eu reiniciar meu computador e
vier trabalhar no LFS, criei um script que faz tudo que preciso: monta os
sistemas de arquivos e faz chroot
.
Acho que montei duas vezes os sistemas de arquivos do kernel virtual, eles já estavam montados e executei novamente o comando. O mount mostrou duas vezes cada um deles. Vou tentar desmontá-los. Criei também um script para quando eu sair do chroot (que já desmonta tudo).
Após a criação de alguns arquivos e links, o trabalho volta a ser parecido com o que estava sendo antes: extração, compilação e instalação. Instalei os headers da API do Linux e as man-pages. Nenhuma surpresa. O próximo passo é a glibc, que será um tanto demorada, por isso deixarei para depois…
Compilando e rodando os testes da glibc, os tempos foram:
real 57m26.194s
user 42m47.832s
sys 14m50.088s
E os seguintes erros foram encontrados:
make[2]: [/sources/glibc-build/posix/annexc.out] Error 1 (ignored)
make[2]: *** [/sources/glibc-build/rt/tst-cpuclock2.out] Error 1
make[1]: *** [rt/tests] Error 2
make[2]: [/sources/glibc-build/conform/run-conformtest.out] Error 1 (ignored)
make: *** [check] Error 2
Aparentemente esses erros estão dentro do esperado. Vou parar antes de 6.9.2. Configuring Glibc.
LFS: Dia 9 - 1/5/13
Completei os ajustes na Glibc. Zlib, file e binutils instalados… Agora só faltam… 49 pacotes ainda!! Achei que terminaria de instalar pacotes hoje mas me enganei. Instalei gmp, mpfr, mpc… Mas vou parar por aqui hoje, o próximo pacote é a GCC, que, de acordo com os SBUs vai me levar cerca de 150 minutos… Boa noite!
LFS: Dia 10 - 2/5/13
A configuração da GCC foi rápida. A compilação demorou:
real 21m19.677s
user 19m35.961s
sys 1m33.374s
A execução da test suite da GCC é realmente demorada…
real 153m1.177s
user 133m29.701s
sys 33m32.402s
Apesar da extrema demora dos testes e algumas falhas, os resultados, após comparados com os que estão nas URLs sugeridas pelo livro, foram dentro do esperado.
A instalação foi bem rápida. Após isso, fiz todas as verificações e ajustes necessários para garantir o funcionamento correto da GCC. Tudo ok. Próximos passos: sed e mais 44 pacotes.
A instalação dos pacotes sed, bzip2, pkg-config, ncurses foram rápidas e simples. O próximo pacote é o util-linux (e depois mais 40 pacotes).