Como criar uma distribuição Linux personalizada que executa apenas um programa e nada mais?

12

Como eu poderia criar minha própria distribuição Linux "personalizada" que executaria apenas um programa, exatamente da mesma maneira que o XBMCbuntu .

user3462992
fonte
Bem-vindo ao U&L, faça uma visita guiada e aprenda a fazer uma pergunta, o que você quer fazer? porque a definição de aplicação é bastante vaga e não significa nada, porque meu conselho seria usar, busyboxmas provavelmente não é isso que você deseja. por isso, reserve o tempo necessário para expressar sua necessidade e poderemos ajudá-lo. Não hesite em editar sua pergunta para adicionar qualquer elemento relevante nela.
Kiwy #
1
Parece bastante claro para mim ...
Goldilocks
@ TAFKA'goldilocks 'bem, não, porque eu aposto que você ainda pode ter acesso a um terminal ou algo semelhante no XBMCubuntu enquanto parece que apenas um aplicativo está sendo executado graficamente, mas não apenas um aplicativo. Fiz uma pequena distribuição uma vez do zero, apenas com um kernel e um busybox, nesse caso, mesmo se houver serviços iniciados pelo kernel, você pode dizer que o busybox é seu único aplicativo.
Kiwy #
@ Kiwi Essa é uma boa resposta então (melhor que o LFS). Lembre-se: 1) Esta pergunta pode ser útil para outras pessoas cujo objetivo geral é o mesmo; portanto, uma série de respostas é boa; 2) Embora exista uma variedade de soluções possíveis aqui - por exemplo, TIMTOWTDI - e algumas podem ser mais adequado a um objetivo mais específico do que outros, tenho certeza de que todos funcionarão e que um aspecto significativo da decisão de uma solução será subjetivo (por exemplo, devido ao conhecimento e à experiência anteriores do OP, não à natureza objetiva da tarefa) .
Goldilocks

Respostas:

6

Eu não começaria a mexer com o LFS, que é um caminho de jardim que leva a algumas madeiras escuras.

Comece com uma distribuição onde você tem muito controle sobre a instalação inicial, como o Arch, ou uma edição sem cabeça, como o servidor Ubuntu. O objetivo disso não é tanto economizar espaço, como delimitar a complexidade da configuração init; a partir de uma distribuição sem cabeça, se o aplicativo que você deseja executar exigir uma GUI, você poderá adicionar o necessário para isso sem ter que terminar com um login da GUI (também conhecido como gerenciador de exibição ou DM) iniciado pelo init e uma área de trabalho completa ambiente para acompanhá-lo.

Você quer aprender como configurar o sistema init para seus propósitos - observe que você não pode ficar sem o init, e pode ser o melhor meio de atingir seu objetivo. Existem três variações no init comumente usadas no linux (mas existem outras ):

  • O Debian usa uma variação no estilo clássico do Unix SysV init . Desde o jessielançamento, o Debian também mudou para systemd( https://wiki.debian.org/systemd )

  • Ubuntu e derivados usam upstart .

  • O Fedora, Arch e derivados usam o systemd .

Se você ainda não sabe nada sobre nenhum deles, nenhum deles é mais difícil de usar do que os outros. Se você optar por um dos dois últimos, eles fornecem alguns mecanismos para compatibilidade com versões anteriores do SysV, mas não se preocupe com isso , NÃO é mais simples. 1 1

O objetivo aqui é minimizar o que o init faz na inicialização, e é assim que você pode criar um sistema que executará uma quantidade mínima de software para dar suporte ao aplicativo em que você deseja se concentrar - é basicamente assim que um servidor é configurado, Entre, portanto, é uma tarefa comum (observe que você não pode literalmente ter "apenas um" processo de terra do usuário em execução, pelo menos de forma não útil).

Se o aplicativo que você deseja executar for um programa de GUI (um bom exemplo de por que você não pode literalmente executar apenas um aplicativo, já que os aplicativos de GUI requerem um servidor X), você pode ter um ~/.xinitrcparecido com este;

#!/bin/sh

myprogram

Quando você startx, então , seu programa será a única coisa em execução, e será impossível alterar as áreas de trabalho ou iniciar qualquer outra coisa, em parte porque não há gerenciador de janelas ou ambiente de área de trabalho (portanto, também não haverá moldura ou barra de título).

1. Para enfatizar um pouco o assunto: Quando você está pesquisando isso, pode encontrar algumas dúvidas sobre o systemd e sobre o início de pessoas que estavam anteriormente familiarizadas com o SysV alegando, por exemplo, que elas são muito complicadas. No entanto, objetivamente, eles não são mais complexos que o SysV (o sistema IMO é mais simples de usar), mas a maioria dos cães prefere seus velhos truques, por assim dizer. Essa aderência está começando a diminuir agora que os dois sistemas estão em uso há um tempo.

Cachinhos Dourados
fonte
1
Você não pode fazer sem init, mas certamente você pode fazer sem upstart, systemd,ou sysv. inité apenas um arquivo executável chamado initque seus invoca do kernel quando ele monta initramfs.Na maioria dos casos estes outros três não são ainda init, mas eles estão realmente execed em por init,que é comumentebusybox.
mikeserv
@mikeserv Absolutamente (e mencionei explicitamente que essas não são as únicas três opções). Observe também que eu deliberadamente excluí busyboxporque isso merece tratamento separado em uma resposta separada, mas não por mim.
GOLDILOCKS
Que gentileza sua em oferecer! Mas de jeito nenhum.
precisa
Seria interessante saber se essa abordagem realmente funciona na prática. Alguém realmente tentou?
Faheem Mitha 02/04
@FaheemMitha Se você quer dizer o que eu estou recomendando aqui (personalize a configuração do init), é claro que sim - é assim que o sistema já funciona, você apenas produziria uma versão simplificada e simplificada (tenho certeza de que isso é o que é XBMCbutu). Se você quer dizer que substituir o init por um ala busybox executável mais especializado, provavelmente é mais complicado do que vale a pena, a menos que você deva fazê-lo dessa maneira - o principal objetivo do busybox é para uso em pequenos ambientes incorporados (com, por exemplo, apenas alguns MB de RAM).
precisa
18

Programa mínimo init hello world passo a passo

insira a descrição da imagem aqui

Compile um olá mundo sem dependências que terminem em um loop infinito. init.S:

.global _start
_start:
    mov $1, %rax
    mov $1, %rdi
    mov $message, %rsi
    mov $message_len, %rdx
    syscall
    jmp .
    message: .ascii "FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n"
    .equ message_len, . - message

Não podemos usar a chamada do sistema de saída ou o kernel entra em pânico.

Então:

mkdir d
as --64 -o init.o init.S # assemble
ld -o d/init init.o      # link
cd d
find . | cpio -o -H newc | gzip > ../rootfs.cpio.gz
ROOTFS_PATH="$(pwd)/../rootfs.cpio.gz"

Isso cria um sistema de arquivos com o nosso hello world at /init, que é o primeiro programa da terra do usuário em que o kernel será executado. Também poderíamos ter adicionado mais arquivos d/e eles seriam acessíveis a partir do /initprograma quando o kernel for executado.

Em seguida, cdna árvore do kernel do Linux, build é como de costume e execute-o no QEMU:

git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
git checkout v4.9
make mrproper
make defconfig
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage -initrd "$ROOTFS_PATH"

E você deve ver uma linha:

FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR

na tela do emulador! Note que não é a última linha, então você precisa olhar um pouco mais adiante.

Você também pode usar programas C se os vincular estaticamente:

#include <stdio.h>
#include <unistd.h>

int main() {
    printf("FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR FOOBAR\n");
    sleep(0xFFFFFFFF);
    return 0;
}

com:

gcc -static init.c -o init

A vinculação dinâmica exigiria a configuração de um executável do vinculador dinâmico, sendo os mais comuns parte das bibliotecas padrão C, como a glibc.

Você pode executar em hardware real com um USB ativado /dev/sdXe:

make isoimage FDINITRD="$ROOTFS_PATH"
sudo dd if=arch/x86/boot/image.iso of=/dev/sdX

Ótima fonte sobre este assunto: Dica técnica: Como usar o initramfs | landley.net Ele também explica como usar gen_initramfs_list.sh, que é um script da árvore de fontes do kernel Linux para ajudar a automatizar o processo.

Testado no Ubuntu 16.10, QEMU 2.6.1.

Próximos passos

A próxima coisa que você quer fazer é configurar o BusyBox .

O BusyBox implementa utilitários básicos da CLI POSIX-y, incluindo um shell POSIX-y, que permite que você experimente mais facilmente o sistema interativamente.

Pessoalmente, neste ponto, prefiro confiar apenas no Buildroot , que é um conjunto incrível de scripts que automatiza a criação de tudo, desde a origem e a criação do sistema de arquivos raiz.

Fiz upload de um auxiliar altamente detalhado e automatizado para isso em: https://github.com/cirosantilli/linux-kernel-module-cheat

Ciro Santilli adicionou uma nova foto
fonte
4
Esta é provavelmente a resposta mais subestimada aqui: D. Impressionante!
msouth
1
@msouth um pouco menos agora :-)
Ciro Santilli escreveu:
1

Se você é um pouco de programação e deseja criá-lo do zero, pode usar o LFS, ou seja, Linux do Scratch http://www.linuxfromscratch.org/

se você deseja personalizar o ubutnu, pode usar o ubunt-builder e, se quiser, no rpm base, pode usar o SUsE-Studio, o Suse studio permitirá que você faça o suse linux personalizado

Felicidades

Besta de Segurança
fonte
1

É mais sobre o que o seu "único programa" exige.

Você ainda pode entender bem como montar as coisas criando um LFS (também conhecido como " Linux From Scratch ") . Depois, você adicionará as coisas exigidas pelo seu programa ou fará uma distribuição completa, pois a criação de subsistemas pesados ​​como o Gnome ou o KDE no LFS pode ser uma verdadeira dor de cabeça.

É claro que voltar atrás pode ser mais fácil no começo, mas remover coisas de um distrito completo pode ser problemático: faça isso em uma VM e copie-a em cada etapa.

(meus 2 centavos)

Editar :

Conforme apontado pelo SecurityBeast, em vez de iniciar a partir de uma distribuição completa como CentOS ou Ubuntu , você também pode dar uma olhada na criação de ferramentas de distribuição como:

Ouki
fonte
1

O que você precisa perguntar é o que o seu "programa único" precisa e quais recursos você possui.

Se ele precisar de uma ampla seleção de bibliotecas e binários de suporte, é melhor usar uma distribuição Linux "regular" (Debian ou similar) e apenas mexer um pouco no processo de inicialização.

Se ele precisar de uma seleção mais restrita de itens de suporte, mas ainda precisar de itens como rede ou suporte para uma variedade de hardware usando diferentes módulos do kernel ou bits de suporte à terra do usuário e você não desejar o espaço em disco sobrecarga de uma distribuição regular, sugiro que você analise distribuições incorporadas (buildroot ou similar) ou talvez uma abordagem linux do zero (embora isso possa ser uma dor de cabeça de manutenção)

Se você precisar exatamente do que um kernel não modular pode fornecer e nada mais, executar o seu próprio binário diretamente no kernel pode funcionar e ser a solução mais leve.

plugwash
fonte