Dispositivo de sistema em lote OpenWrt

O sistema operacional OpenWrt é comumente usado como firmware para roteadores. A aplicação típica é definir e esquecer. Mas se de repente algo não for suficiente para você, você terá que entender o kit de distribuição.











OpenWrt usa opkg como seu gerenciador de pacotes, ou melhor, seu próprio fork . Os engenheiros do Debian o acharão familiar de várias maneiras: comandos semelhantes, repositório semelhante e formato de pacote.



Eu queria corrigir o LUCI (isso não estará no artigo), mas não encontrei uma introdução rápida adequada, tive que coletar independentemente fragmentos de informações de documentação dispersa, artigos e exemplos, olhando para o código e os resultados do trabalho. Como bônus, coletei um pacote primitivo (mas inútil na prática) que ainda não está no repositório. Eu compartilho o programa educacional coletado abaixo.



Dispositivo de repositório



Há um arquivo no sistema de arquivos OpenWrt /etc/opkg/distfeeds.conf



que especifica a lista de repositórios do sistema (fornecida pelos desenvolvedores OpenWrt e opkg). Repositórios próprios e de terceiros podem ser especificados em /etc/opkg/customfeeds.conf



. O formato é de uma linha, consiste em três palavras:



  1. src



    ou src/gz



    , depende Packages



    se o arquivo será baixado ou Packages.gz



    . A julgar pelo código, existem outras opções para a primeira palavra, mas não encontrei nenhum repositório para o qual isso seria relevante. Apesar do src



    nome, este é um repositório para pacotes binários. Opkg não possui um formato de repositório especial para pacotes fonte semelhante ao usado no Debian / APT.
  2. O nome do repositório ou "feed" na terminologia opkg / OpenWrt.
  3. O URL que contém o Packages



    / Packages.gz



    .


Quando executado , ou adicionado opkg update



ao URL , a lista de pacotes e assinaturas são salvas em , o arquivo é nomeado de acordo com a segunda palavra na lista de repositórios. Existem duas conclusões importantes disso:/



Packages



Packages.gz



/tmp/opkg-lists







  1. Na reinicialização, o cache será limpo. Em sistemas embarcados como roteadores, isso faz todo o sentido.
  2. Você /etc/opkg/customfeeds.conf



    pode substituir feeds do sistema pelos seus, dando-lhes o mesmo nome. opkg irá jurar, mas engolir a substituição, adicionando o arquivo desejado ao invés do carregado anteriormente.


Ao mesmo tempo, ele será carregado Packages.sig



, o que deve conter o hash da lista de pacotes descompactada. A própria lista simplesmente lista os pacotes, existem vários valores para cada pacote, os valores para diferentes pacotes são separados por uma linha em branco. Aqui estão os campos mais importantes para cada pacote:



  • Package



    , nome do pacote;
  • Version



    , versão, se houver vários pacotes com o mesmo nome, você pode selecionar a versão, a mais recente será instalada por padrão;
  • Depends



    , dependendo de outros pacotes, o gerenciador de pacotes instalará os pacotes listados se eles não estiverem presentes no sistema;
  • Filename



    , o caminho para o arquivo é relativo à URL base do repositório, geralmente o repositório é simples e tudo está no mesmo lugar que `Packages.gz`;
  • SHA256sum



    o hash do pacote declarado pelo repositório.


Se você quiser mais detalhes, pode simplesmente ler uma dessas listas diretamente no seu navegador .



Pacotes binários



Os pacotes binários são quase idênticos aos pacotes Debian. A diferença é a seguinte:



  1. Extensão em .ipk



    vez de .deb



    .
  2. `tar` gzip



    , . Debian ar



    , .tar.xz



    , .


Se você mudar a extensão do pacote para OpenWrt para .tar.gz



e descompactá-lo, você o encontrará dentro de dois arquivos e um arquivo de texto. O arquivo tem um nome debian-version



, contém a versão do formato do arquivo binário e não é muito interessante para nós, nos sistemas modernos essa versão é sempre igual a 2.0



.



O arquivo data.tar.gz



contém arquivos executáveis, arquivos de configuração e tudo para o qual o pacote está instalado. Se você descompacte-o para a raiz dos FS, você receberá todos os arquivos esperados nos lugares certos, em /usr/bin/



, /etc/



e assim por diante.



E nele control.tar.gz



existem arquivos auxiliares para o gerenciador de pacotes. Este script que deve ser executado antes ou depois da instalação e remoção ( preinst



, postinst



, prerm



,postrm



), informações sobre arquivos que são arquivos de configuração e metainformações sobre o pacote, que são basicamente as mesmas contidas em Packages



.



Sistema de construção de pacotes



O sistema de montagem (também conhecido como SDK) é feito na forma de uma estrutura Make. O framework não implica que você construirá pacotes separadamente, sua principal tarefa é construir repositórios inteiros.



O SDK x86_64



está em git . Há um arquivo (o link ficará desatualizado em breve, mas não é difícil encontrar um novo) que poupará tempo na compilação do conjunto de ferramentas para montagem. No interior, o arquivo é de particular interesse feeds.conf.default



. O formato é simples, separado por um espaço:



  1. Palavra-chave src-git



    . Não apenas git é suportado , mas agora não há repositórios em outro VCS.
  2. Nome do feed.
  3. Um URL de repositório git onde você pode especificar um commit ou tag. Se você souber o nome dessa especificação, diga-me.


O repositório com pacotes em si é projetado da forma mais simples possível: na raiz do repositório há uma categoria de pacote, no segundo nível há um diretório com o nome do pacote e dentro dele está Makefile



, opcionalmente, `Config.in` para opções adicionais durante a execução make menuconfig



e um subdiretório patches



com o conteúdo correspondente. Para o pacote mais simples, apenas Makefile



. Por exemplo, você pode olhar no espelho do repositório principal .



Compilação de teste



Tentei construir o GNU Hello para testar como o SDK funciona. Este é um Hello World relativamente monstruoso, escrito em estrita conformidade com as diretrizes do projeto GNU, seu único propósito é ilustrar essas diretrizes. Não criei um repositório separado para ele, mas em vez disso "coloquei" nos pacotes básicos do SDK, de onde o compilei.



Para a operação do SDK Rodeado pelos pacotes Debian necessários libncurses-dev



(para a montagem do menu), build-essential



(de GCC e outros programas padrão, dependendo do C), gawk



, unzip



, file



, rsync



e python3



. Além disso, para criar um repositório dos pacotes coletados, você precisará de um utilitário para gerar chaves usign



. Ele não está no repositório, então você também precisará do `cmake` para compilar. Esta ferramenta pode ser substituída por GPG esignify-openbsd



mas é recomendado e desenvolvido pelo projeto OpenWrt e é muito mais agradável de usar.



Compile e instale usign



:



git clone https://git.openwrt.org/project/usign.git
cd usign
cmake .
make
sudo make install 
      
      





Em vez de definir ( sudo make install



), você pode simplesmente lembrar onde o binar está para puxá-lo ainda mais com suas mãos.



Agora, a configuração básica do SDK:



git clone https://git.openwrt.org/openwrt/openwrt.git
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a
      
      





Deixe-me lembrá-lo de que, em vez de clonar do git, você pode baixar e descompactar o arquivo com o conjunto de ferramentas pré-compilado. Não se esqueça de apenas baixar a versão mais recente!



Ao executar, ./scripts/feeds update -a



clonamos / atualizamos todos os repositórios de feeds.conf (.default), verificamos as dependências e preparamos um diretório staging_dir/host/bin



com arquivos executáveis ​​(estes são principalmente links simbólicos para utilitários do sistema). O comando a seguir ./scripts/feeds install -a



,, empurra links simbólicos para package/feeds



, de onde eles serão levados para compilação. Esses dois comandos não são necessários para construir meu pacote personalizado.



Em seguida é executadomake menuconfig



... Você pode ignorá-lo, mas ao compilar o pacote, ele ainda exibirá a janela apropriada. Nele, basta alterar o alvo e o sub-alvo para que tudo seja compilado em x86_64 e sair, concordando em salvar a configuração. Você também precisará coletar ferramentas de montagem auxiliares ( make tools/install



) e conjunto de ferramentas ( make toolchain/install



). Se você baixou o SDK do arquivo, make menuconfig



não serão mostradas opções para escolher um destino e não é necessário montar o kit de ferramentas e o conjunto de ferramentas - tudo já está no lugar.



Agora crio um diretório package/devel/hello



no qual coloco o Makefile



seguinte conteúdo:



Makefile
include $(TOPDIR)/rules.mk

PKG_NAME:=hello
PKG_VERSION:=2.9
PKG_RELEASE:=1
PKG_LICENSE:=GPL-3.0-or-later

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@GNU/hello/
PKG_HASH:=ecbb7a2214196c57ff9340aa71458e1559abd38f6d8d169666846935df191ea7

include $(INCLUDE_DIR)/package.mk

define Package/hello
        SECTION:=devel
        CATEGORY:=Development
        TITLE:=GNU Hello
        URL:=https://www.gnu.org/software/hello/
endef

define Package/hello/description
        The GNU Hello program produces a familiar, friendly greeting. Yes,
        this is another implementation of the classic program that prints
        “Hello, world!” when you run it. However, unlike the minimal version
        often seen, GNU Hello processes its argument list to modify its
        behavior, supports greetings in many languages, and so on. The primary
        purpose of GNU Hello is to demonstrate how to write other programs that
        do these things; it serves as a model for GNU coding standards and GNU
        maintainer practices.
endef

define Package/hello/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/hello $(1)/usr/bin/
endef

$(eval $(call BuildPackage,hello))
      
      





Basicamente, tudo deve estar claro sem explicação. Os arquivos da estrutura são conectados, os principais parâmetros do pacote são descritos, @GNU



substituídos pelos espelhos do projeto GNU (definidos na estrutura) e o caminho consiste em duas partes: PKG_SOURCE_URL



que especifica a URL base para todas as versões e é expandido pela concatenação do nome do arquivo PKG_SOURCE



com uma barra. Ele Package/hello/install



contém instruções para montar binários em um arquivo data.tar.gz



. Opções de construção adicionais, se necessárias, estão disponíveis na documentação . A propósito, não se esqueça de que o make é muito exigente quanto ao recuo, usei tabulações simples em vez de espaços iniciais.



Ligue novamentemake menuconfig



, verifique se o pacote hello está marcado na seção indicada (Desenvolvimento no meu caso) e saia salvando a configuração. Por fim, montamos o pacote em três etapas; baixando, descompactando e realmente compilando:



make package/hello/download
make package/hello/prepare
make package/hello/compile
      
      





Como resultado, recebi um pacote bin/packages/x86_64/base/hello_2.9-1_x86_64.ipk



. Você pode construir um repositório. Nós gerar um par de chaves ( usign -G -c 'openwrt test repo' -s key-build -p key-build.pub



a chave privada deve ser chamado `key-build`), e recolher o repositório: make package/index



. Nesta fase, o conjunto pode jurar à ausência usign



no diretório com ferramentas auxiliares, decidi problema link simbólico: ln -s `which usign` staging_dir/host/bin/usign



. Agora, ao lado do pacote, está o conjunto completo necessário para o repositório.



Verificando o repositório junto com o pacote



Você pode verificar tudo em um roteador real (lembre-se de escolher o destino correto), mas usei o Docker. Em Dokerhabe tem imagem OpenWrt para x86_84, que pode ser executado, formação de gelo dentro do diretório recipiente com o SDK: sudo docker run -it --name openwrt_test -v $PWD:/opt openwrtorg/rootfs



. Pressione o botão Enter até que o prompt Bash apareça.



Eu copio a chave do diretório encaminhado (o cp /opt/key-build.pub /etc/opkg/keys/usign -F -p /opt/key-build.pub



nome da chave deve necessariamente corresponder ao identificador), adiciono meu repositório local ( echo src/gz local file:///opt/bin/packages/x86_64/base >> /etc/opkg/customfeeds.conf



), atualizo o repositório ( opkg update



). A conclusão começa com um texto encorajador, tudo está assinado corretamente:



# opkg update
Downloading file:///opt/bin/packages/x86_64/base/Packages.gz
Updated list of available packages in /var/opkg-lists/local
Downloading file:///opt/bin/packages/x86_64/base/Packages.sig
Signature check passed.
      
      





Resta apenas instalar e verificar:



root@34af2f6e849b:/# opkg install hello
Installing hello (2.9-1) to root...
Downloading file:///opt/bin/packages/x86_64/base/hello_2.9-1_x86_64.ipk
Configuring hello.
root@34af2f6e849b:/# hello
Hello, world!
      
      





Hurrah, está feito! Apesar da documentação espalhada pelos artigos, o processo de construção do pacote é bastante direto.










All Articles