4 pontos por GN⁺ 2024-12-09 | 1 comentários | Compartilhar no WhatsApp
  • Esta wiki não é apenas uma lista de scripts longos, mas reúne programas Shell “substanciais”, escritos manualmente e que usam até estruturas de dados e algoritmos
  • O critério é, em geral, mais de 5 mil linhas, e scripts gerados automaticamente ou scripts de completion repetitivos ficam fora dos casos principais
  • Entre os exemplos de destaque estão o ble.sh com 87 mil linhas, kalua com cerca de 56 mil SLoC/linhas, Relax-and-Recover com 35 mil linhas, nb com 26 mil linhas e winetricks com 22 mil linhas, indo muito além da percepção comum sobre scripts Shell
  • A lista inclui amplamente ferramentas de uso real, como editor interativo de linha, addon para OpenWRT, depurador de Bash, ferramenta de teste de TLS, implementação de Kubernetes, ferramenta de backup e recuperação, ferramenta de emissão de certificados e monitor de recursos
  • O teste OSH “Wild” faz parsing de mais de um milhão de linhas de Shell, mas a maior parte disso são programas pequenos e definições repetitivas de pacotes de distribuições, então é tratado separadamente de grandes programas Shell

O que conta como um “grande programa Shell”

  • Aqui, “biggest” não significa apenas número bruto de linhas, mas algo “substantial”, ou seja, com escala e complexidade reais
  • Em princípio, entram apenas scripts Shell escritos manualmente
    • Scripts grandes gerados pelo autoconf são tratados como exceção
    • Artefatos gerados automaticamente, como o script de 70 mil linhas do coreutils, não são considerados grandes programas Shell no sentido substantivo
  • Há atenção especial para programas Shell que usam estruturas de dados e algoritmos
    • O bash-completion é sofisticado, mas por ter uma estrutura repetitiva com funções relativamente simples para cada comando de uma máquina Unix, fica mais como contraexemplo
  • A linha de corte aproximada é mais de 5 mil linhas
    • Os maiores programas Shell não repetitivos normalmente ficam na faixa de 10 mil+ linhas
    • Ainda não foi confirmado nenhum programa acima de 100 mil linhas

Exemplos dos maiores programas Shell

  • akinomyoga/ble.sh: total de 87 mil linhas, 63 mil LoC sem comentários
    • É um editor interativo de linha parecido com o fish, escrito em bash puro
    • O arquivo principal out/ble.sh tem 39 mil linhas, 29 mil LoC sem comentários, e com os módulos o total passa de 80 mil linhas
    • Há muitos comentários em japonês
    • Usa bind -x para ler os bytes brutos do terminal, faz a decodificação manualmente com várias máquinas de estado explícitas e mantém/atualiza um drawing buffer
    • Também inclui timing e “fibers”
    • Detalhes sobre o parser Shell estão nos comentários da issue 663, e o projeto é considerado um dos exemplos mais sofisticados de uso de estruturas de dados em Shell
    • Há tentativas de executá-lo no OSH, e a maior parte já é parseada
    • O primeiro commit tinha 8 mil linhas / 6 mil LoC em 2015, e o desenvolvimento real começou em 2013
  • kalua: addon para OpenWRT, escrito em POSIX shell com cerca de 56 mil SLoC/linhas
  • Relax-and-Recover: ferramenta de backup e recuperação com 35 mil linhas e 24 mil LoC
    • O primeiro commit no git foi em março de 2009, quando tinha 4 mil linhas / 3 mil LoC
  • xwmx/nb: o próprio nb tem 26 mil linhas e 22 mil LoC em bash
    • Se os testes em bats forem contados como bash, há mais 91 mil linhas e 61 mil LoC adicionais
    • O primeiro commit é de 2014, e o histórico ativo de commits começa no início de 2016
  • vegardit/bash-funk: biblioteca Bash com 27 mil linhas no total e 24 mil LoC
    • O primeiro commit foi em maio de 2017, quando tinha 10 mil linhas / 8 mil LoC
  • winetricks: script Shell de 22 mil linhas que instala vários programas Windows sobre o Wine
  • drwetter/testssl.sh: arquivo único com 21 mil linhas de bash
    • Parece ter sido escrito manualmente
    • Começou em 2006 com alguns comandos openssl
    • Durante o parsing, trava na issue #606
  • rkhunter: programa em Bourne shell com 21 mil linhas, escrito de 2003 a 2018
  • Simplenetes: apresentado como “Kubernetes in 17K lines of Shell
  • inxi 2.3.56: programa em bash com 16 mil linhas, marcado como obsoleto
    • Foi derivado de infobash em 2008
    • Na época, infobash tinha 889 linhas, e havia começado em 2005
    • A partir da v2.9, o inxi foi substituído por uma implementação em Perl
  • bashdb: depurador de Bash com cerca de 14 mil linhas em bash
  • romkatv/powerlevel10k: há 12 mil linhas de script zsh no diretório internal/
    • Além disso, configs e helper scripts somam mais 8 mil linhas
    • O primeiro commit é de 2014
  • dylanaraps/neofetch: programa de 10 mil linhas escrito para Bash 3.2 que mostra informações do sistema
    • Também consegue fazer algumas coisas interessantes relacionadas a imagens
    • O primeiro commit é de 2015
  • distrobox: script bash com mais de 7 mil linhas que permite usar qualquer distribuição Linux dentro do terminal
  • acme.sh: script Shell de 8 mil linhas para emitir e renovar certificados

Implementações menores, mas marcantes

  • bashforth: com cerca de 3.800 linhas, não é tão grande, mas implementa uma linguagem de programação de verdade
    • Há muitos espaços em branco e comentários
  • yoda: tem cerca de metade do tamanho do bashforth, mas implementa o interpretador e o compilador completos
    • É uma implementação do mesmo autor, 20 anos mais nova, com mais funcionalidades
    • Vem com o comentário “What learned you have, unlearn you must!”

Outros programas Shell relevantes

  • abcde / A Better CD Encoder: usado para ripar CDs e tem cerca de 5,5 mil LoC
  • thc-segfault: 3,3 mil LoC, um servidor pubnix feito majoritariamente em Bash
  • ffmpeg/configure: script configure do FFmpeg, escrito manualmente, com 8,4 mil LoC
  • ffhevc: wrapper totalmente escrito à mão em Bash para codificar vídeo HEVC com FFmpeg e libx265, com 4 mil LoC
  • ffx264: wrapper totalmente escrito à mão em Bash para codificar vídeo H.264/AVC com FFmpeg e libx264, com 3,9 mil LoC
  • h264enc: wrapper totalmente escrito à mão em Bash para codificar vídeo H.264/AVC com MEncoder, com 9,2 mil LoC
  • bashtop: monitor de recursos com 5,3 mil LoC
  • halcyon: sistema de instalação de apps Haskell com 6,6 mil LoC
    • Código escrito manualmente, com atenção à semântica do bash e à checagem de erros, num estilo único inspirado em programação funcional
  • wordshell: cerca de 7 mil linhas de código para gerenciar vários sites WordPress pela linha de comando
  • BaCon: cerca de 10 mil linhas, converte programas escritos em BASIC para C
    • Há tanto uma implementação em BASIC quanto uma implementação em Shell script
  • FireHOL: o script principal tem 9 mil linhas, e a ferramenta FireQOS soma mais 3 mil linhas
    • É uma linguagem e também um programa executável para criar um firewall seguro e stateful a partir de uma configuração legível por humanos
  • gxadmin: 11 mil LoC, um conjunto de consultas SQL templated e utilitários de processamento de dados para administrar o motor de workflows científicos Galaxy
  • mulle-bashfunctions: biblioteca de funções para bash/zsh com cerca de 6 mil linhas
    • É usada no mulle-sde, que por sua vez é outro Shell script com 100 mil linhas
  • x11docker: 11,6 mil linhas, executa aplicações GUI em contêineres docker ou podman

Linguagens semelhantes a Shell e DSLs

  • modernish: dialeto shell portátil escrito em Shell
  • bats: DSL para escrever testes que gera código bash
  • bashible: DSL semelhante ao Ansible, escrita em bash
  • clash: framework orientado a objetos compatível com todos os shells POSIX modernos
  • bash Infinity: biblioteca padrão e framework boilerplate para bash

Programas menores e ecossistema relacionado

  • Scripts de Alpine, Aboriginal e Debian aparecem em um post de blog separado
  • Scripts de completion são grandes, mas muitas vezes repetitivos
    • O completion de Zsh para _git tem 8,3 mil linhas de código
    • git-completion.bash e o completion do Docker também são citados como exemplos
  • dyne/Tomb: script zsh com cerca de 3.500 linhas
  • Basalt: gerenciador de pacotes full-featured escrito em Bash puro
    • Tem alguns milhares de linhas, mas conta com um ecossistema rico, com mais de 15 apps e bibliotecas
    • bash-core: biblioteca que estende os builtins trap e shopt e adiciona stacktrace e recursos essenciais de conveniência
    • bash-object: biblioteca em Bash puro para construir estruturas de dados arbitrariamente aninhadas, com quase 200 testes
    • bash-json: biblioteca em Bash puro para fazer parsing e saída de JSON
  • tablespoon/fun/cli-clock: relógio textual multilinha escrito em bash
  • json.bash / jb: ferramenta de linha de comando e biblioteca bash para gerar JSON
    • Tem cerca de 1.700 linhas, e os testes somam cerca de 3 mil linhas

Testes do OSH e cuidados ao usar Shell

  • OSH "Wild" Tests fazem parsing de mais de um milhão de linhas de Shell
    • A maior parte disso são programas pequenos e definições repetitivas de pacotes de distribuições, como Alpine PKGBUILD e Gentoo ebuild
  • Shell Programs That Run Under OSH aponta para uma lista de programas Shell executados no OSH
  • shell script are dangerous alerta que Shell é uma linguagem para lidar com o interior do sistema em modo interativo ou não interativo, cheia de recursos, muito perigosa e não criada para desenvolver aplicações

1 comentários

 
GN⁺ 2024-12-09
Comentários do Hacker News
  • Há cerca de 25 anos, quando eu trabalhava na Sony, assumi um projeto para consertar um sistema de gerenciamento de pedidos que era muito lento e caía com frequência
    Ao investigar, descobri que o OMS era um enorme conjunto de scripts shell rodando em servidores AIX, que tinha evoluído por mais de 10 anos e depois sido abandonado. O código passava de 50 mil linhas; pedidos, pagamentos e outras informações eram movidos entre servidores via FTP e depois analisados com sed/awk complexos; o estoque também era rastreado em arquivos de texto e transferido por FTP
    Na época, Perl parecia a opção mais prática para migrar aquela bagunça, então comecei pelas partes mais simples, substituindo-as por pequenos módulos Perl e refatorando tudo gradualmente dentro de uma aplicação Perl maior. Em 3 meses, reduzi tudo para cerca de 5 mil linhas de Perl, e as falhas do sistema original praticamente desapareceram, com desempenho 10 a 100 vezes maior. Foi horrível, mas continua sendo um dos trabalhos mais satisfatórios que já fiz
    • Apenas 3 meses? Isso dá 800 linhas apagadas por dia
      Fico curioso se você leu todo o código original e o entendeu profundamente antes de reproduzir o comportamento com precisão, ou se descartou grandes blocos e reescreveu conforme achava que “deveria funcionar”. Também me pergunto se havia muito código boilerplate que podia ser substituído rapidamente
    • Para amenizar esse tipo de monstro em shell script, Perl ainda é a opção mais prática. Tcl também é uma boa alternativa
  • Preciso revirar de novo algumas coisas que escrevi antigamente
    O primeiro script realmente grande que escrevi foi um instalador de cerca de 7 mil linhas para Enrust CA e diretório, e ele precisava rodar em praticamente todos os Unix da época. Não começou assim, mas cresceu conforme as demandas dos clientes
    A instalação em si não era tão complicada, mas os upgrades eram um pouco complexos, e naquela época cada Unix tinha todos os utilitários ligeiramente diferentes. Uma boa parte do script era código para detectar e gerenciar essas diferenças, além de detecção de erros, recuperação, rollback e um gerenciamento muito primitivo de pacotes e dependências
    O Unix da DEC — o que não era Ultrix — era o mais obscuro. Levei dias para perceber que todos os utilitários de linha de comando cortavam a saída na largura das colunas do terminal, e ainda me lembro disso 30 anos depois
    O HP-UX tinha mudanças incompatíveis a cada release e, se minha memória não falha, demos suporte da versão 6.5 até a 11. Quase não me lembro de Ultrix, do lado da Novell, NeXT e Sequent. Lembro que AIX era estranho, mas esqueci o motivo. Os três/quatro sistemas operacionais da Sun também tinham diferenças, mas os manuais eram excelentes e eram os melhores
    • Essa saída cortada na largura das colunas soa realmente estranha. Fico imaginando se o terminal de fato não tinha algo como rolagem horizontal
    • Quando você diz Unix da DEC, está falando de OSF/1, Digital Unix ou Tru64 Unix?
    • Eu também cheguei a alguns milhares de linhas, mas algo em torno de 2 mil. Mesmo assim, tive sorte de só precisar dar suporte ao Red Hat e ao Ubuntu modernos
    • No ano passado, rodei wc no binário principal e nas bibliotecas auxiliares de um projeto e, até agora, são 6.224 linhas
      Era um script para gerenciar pipelines com garantia linear, compostos por adaptadores de protocolo de entrada, um ou mais filtros e adaptadores de protocolo de saída. O objetivo era permitir que pessoas que não fossem especialistas em contêineres ou protocolos, mas soubessem como queriam que os arquivos fossem filtrados e transformados ao passar pelo pipeline, pudessem usá-lo
      O binário de nível superior tem uma estrutura com subfunções, como git [ git options ] < git action> [action options] ou systemctl. Há até um subcomando que adiciona novos subcomandos, cria as bibliotecas necessárias e preenche previamente definições de funções a partir de templates. Os templates têm funções de uso curto/longo, de modo que cbap -h ou cbap pipeline -h forneçam orientações úteis
      Há subcomandos para manipular imagens base, componentes e pipelines. Boa parte do código é para testes que verificam se as definições de componentes e pipelines foram escritas corretamente. O formato dos pipelines é quase TOML, então há código para parsing de TOML e para converter seções em arrays; os componentes são arquivos simples key=value, então há código para extrair lado esquerdo e direito e validar o schema
      Como os componentes do pipeline podem compartilhar propriedades, também há código para encontrar propriedades comuns nos arquivos var e etc e definir propriedades dos componentes. Há muitas funções para manipular usuários, grupos, diretórios e FIFOs conforme requisitos de segurança. Ao configurar um pipeline, ele cria e aplica usuários, grupos, tipos SELinux e categorias MCS, e depois os mapeia para arquivos de serviço que iniciam os componentes, então também há muita manipulação de systemd
      O maior conjunto de chamadas provavelmente é o das funções que obtêm e configuram propriedades de componentes — na prática, propriedades de contêineres. Para cada propriedade, criei uma função de obtenção, uma função de validação e uma versão inline dentro do pipeline, para tornar a definição de contêineres orientada a dados o mais flexível possível
      Também há código que usa muitas referências do Bash para definir variáveis a partir de arquivos, variáveis de ambiente e linha de comando, o que permite testes rápidos. Ele oferece suporte a quatro níveis de usuários: mantenedores que lidam com o próprio código, desenvolvedores que criam definições de componentes, integradores que montam pipelines a partir de componentes e operadores que instalam pipelines; e consegue copiar e empacotar a si mesmo para exportação a usuários de cada nível
      Como o sistema de destino pode ser qualquer Linux, ele é empacotado e extraído com makeself. Por exemplo, quando um integrador cria uma definição de pipeline, é gerado um arquivo makeself; ao executá-lo no sistema de destino, ele cria todos os usuários, grupos, diretórios e FIFOs — ou seja, o IPC entre componentes —, aplica DAC/MAC, cria arquivos systemd, copia as imagens para cada usuário e então executa o pipeline. Com a opção de remoção, tudo isso também pode ser revertido
      Também há um pouco de seccomp, mas isso ficou pausado enquanto encontramos o equilíbrio entre listas de permissão e listas de bloqueio. Uso ShellCheck de forma realmente rigorosa
  • Já pensei em escrever o interpretador da minha linguagem de script Lil em Bash para maximizar a portabilidade, mas logo percebi que operações de ponto flutuante seriam extremamente dolorosas
    Também não dá para esperar que todo ambiente tenha bc/dc, e algumas das máquinas que eu tinha usavam versões antigas do Bash, com suporte muito limitado a arrays associativos. Como compromisso, escolhi AWK como alvo; AWK é uma linguagem de uso geral muito mais agradável do que a maioria dos shells e está presente em qualquer ambiente POSIX: https://beyondloom.com/blog/lila.html
    • Eu também estava criando uma linguagem tendo shell como alvo e descobri na prática que não dá para esperar bc/dc em todos os ambientes

Fiquei bastante surpreso ao perceber que a instalação do Ubuntu no WSL2 aparentemente não vinha com bc/dc. Para cálculos de ponto flutuante, uso AWK, mas simplesmente chamando-o como um processo externo.

  • Como alguém que escreveu e manteve grandes programas em Perl várias vezes ao longo da carreira, há um motivo para as pessoas fazerem isso
    Linguagens como Java ou Python se encaixam bem quando as interfaces e os formatos estão definidos e há pouca interação com o SO. Se você usa JSON/XML/YAML ou se comunica com bancos de dados e outros programas via HTTP(S), cria-se a situação ideal em que essas linguagens brilham
    Mas, ao lidar com grandes volumes de texto e interação com o SO, Java e Python viram um grande sofrimento. Por outro lado, Shell/Perl parecem muito mais fáceis para esse tipo de tarefa
    Quase todo trabalho de automação, interfaces confusas e não padronizadas, arquivos de texto/logs, formatos de dados não estruturados ou insuficientemente estruturados entram nessa categoria. Some a isso a compatibilidade retroativa do Perl, sua ampla base instalada e seu desempenho, e praticamente não há alternativa ao Perl para esse tipo de trabalho
    Há muito tempo venho achando que uma das grandes razões pelas quais grandes empresas hoje empregam milhares de pessoas em trabalho manual para fazer coisas trivialmente automatizáveis é o declínio do uso de Perl. Ao tentar fazer grandes automações em Python ou Java, as pessoas logo desistem, cansadas da verbosidade do código que precisam escrever e manter e da escala total do projeto

    • Não concordo muito com a ideia de que “é porque o Perl desapareceu”. Acho que a complexidade aumentou, que o trabalho da pessoa responsável por juntar scripts em Perl virou uma função em tempo integral, e que havia limites mesmo usando só Perl
      Por isso, agora provavelmente é necessário mais pessoal caro em regime integral. Se o usuário final está no Windows, já existe uma opção parecida com Perl no desktop. É o PowerShell, que cumpre um papel semelhante ao do Perl
    • Fiz grandes trabalhos de automação em código nativo. Nesses casos, eficiência é importante
      Bash+grep tende facilmente a cair no padrão de iniciar um novo processo para cada linha de texto. Para fazer isso de forma eficiente, é preciso minimizar o trabalho; para isso, é necessário processamento em lote e deduplicação. Isso significa lidar com os dados de forma com estado, acompanhando o contexto de deduplicação, o que é mais fácil em uma linguagem de programação de verdade
      Bash+grep é vantajoso para processamento de texto sem estado, então é fácil acumular muito trabalho duplicado. Outra forma de reduzir trabalho é fazer filtragem precisa, algo que é mais fácil expressar de forma imperativa e limpa em uma linguagem adequada. grep e expressões regulares não servem nem um pouco para esse uso
      Ao usar formatos linha a linha, o git adiciona escapes para tentar aceitar qualquer coisa, mas o suporte não é consistente, e é possível desativá-lo solicitando strings terminadas por nulo com a opção -z. Parece que o Bash não tem como lidar com isso, enquanto linguagens suficientemente de baixo nível tratam isso de forma natural. Também é possível fazer streaming incremental sem precisar iniciar um novo processo para cada linha de texto
      Como bônus, dá para usar uma única base de código para todas as tarefas, haja HTTP no meio ou qualquer outra coisa
    • Concordo. Minha linguagem favorita é Python, mas ela pode ser incômoda ou ineficiente para certas tarefas de SO de baixo nível. Foi por isso que criei https://www.oilshell.org e a página wiki vinculada
      Há alguns links para contexto. “Estamos reinventando o Perl?”: https://www.oilshell.org/blog/2021/01/why-a-new-shell.html#a...
      “O shell Unix deveria evoluir como o Perl 5, com uma opção de upgrade compatível, e não como um big bang ao estilo Perl 6/Raku”: https://www.oilshell.org/blog/2020/07/blog-roadmap.html#the-...
      Tour pelo YSH: https://www.oilshell.org/release/latest/doc/ysh-tour.html
    • Depois de perceber que Perl 5 vem instalado por padrão em muitos sistemas Linux e BSD, estou pensando seriamente em aprendê-lo. Pelo que sei, o OpenBSD também já vem com Perl instalado
      Isso pode não parecer uma grande vantagem até você trabalhar em um ambiente onde não dá para instalar coisas da internet, ou que nem sequer tem acesso à internet
  • O problema central ao escrever programas grandes como scripts Bash é que a linguagem de shell script, para começo de conversa, não foi projetada para complexidade
    Ela é excelente para coordenar pequenos comandos e conectar rapidamente ferramentas existentes de forma exploratória, mas, quando Bash começa a passar de algumas centenas de linhas, aparecem em sequência limitações que tornam a manutenção de longo prazo e a escalabilidade difíceis
    Primeiro, a legibilidade é um problema. A sintaxe do Bash pode ficar realmente obscura conforme cresce. As regras de escopo de variáveis são sutis, o tratamento de erros é primitivo e o tratamento de strings fica bagunçado rapidamente. No fim, mantenedores perdem tempo decifrando o que está acontecendo, e também fica difícil fazer alterações com confiança
    Em seguida vem a falta de ferramentas robustas. Linguagens mais maduras têm ferramentas de análise estática, linters e depuradores que ajudam a detectar erros comuns cedo. No Bash, essas coisas não existem ou são muito limitadas. Sem essas proteções, programas grandes em Bash ficam mais vulneráveis a erros silenciosos, regressões e bugs sutis
    Testes também são um problema. É possível testar scripts Bash, mas o processo costuma ser mais trabalhoso, e fica ainda mais complicado quando há lógica ou estruturas de dados complexas. Ao lidar com casos de borda, como espaços em nomes de arquivos ou condições de ambiente inesperadas, você acaba com muito código defensivo doloroso de validar
    Por fim, o próprio ecossistema não foi feito para desenvolvimento em Bash em grande escala. Perde-se modularização, gerenciamento de pacotes, tratamento padronizado de dependências e os padrões modernos de desenvolvimento que Python ou Go oferecem. Com o tempo, essas ausências se acumulam e reduzem a velocidade
    Usar Bash para tarefas pontuais ou automações simples é bom. É isso que o Bash faz bem. Mas, se você pretende construir algo grande, normalmente é melhor usar uma linguagem projetada para criar e manter aplicações complexas; mesmo que a curva de aprendizado inicial ou a configuração sejam um pouco maiores, isso economiza tempo no longo prazo

  • Usar o ShellCheck como linter ajuda a pegar muitas armadilhas comuns. Bash/shell têm mesmo muitas armadilhas e comportamentos inesperados, a ponto de até autores experientes de Bash poderem cair nelas
    Ainda assim, Bash/shell ocupam uma posição peculiar na hierarquia das linguagens. Estão em praticamente todo lugar e é bem provável que continuem existindo daqui a 30 anos. Se você quer um programa que rode em quase qualquer lugar e ainda rode daqui a 30 anos, shell/Bash é uma boa escolha

    • Estou passando exatamente por isso no trabalho atual. Estou destrinchando milhares de linhas de Bash
      Nem é um script escrito muito tempo atrás, então não sei por que escolheram Bash. O script funciona, mas dá a sensação de que alguma coisa vai quebrar só de olhar torto para o código
    • Bash/ksh têm o argumento -x para depuração/rastreamento
  • O maior programa shell escrito manualmente que eu usava regularmente no passado provavelmente era o abcde (A Better CD Encoder), com cerca de 5.500 linhas
    https://abcde.einval.com
    https://git.einval.com/cgi-bin/gitweb.cgi?p=abcde.git;a=blob...

    • Não diria que conheço bem, mas era uma das ferramentas recomendadas na antiga What.CD. Amigos me disseram que o Max também era recomendado junto: https://github.com/sbooth/Max
    • Já usei e funcionava muito bem, além de ser bem fácil de usar. Eu não fazia ideia de que era inteiro um enorme script shell
  • Muitos desses programas são verdadeiras joias. Por exemplo, o script rkhunter tem um código razoável, ainda tem espaço para melhorias, e também é um tesouro de informações
    Grande parte do tamanho do código desses scripts é usada para garantir, em várias plataformas, que os utilitários necessários existam e que se comportem como esperado com diferentes opções de linha de comando. Esse é o ponto mais doloroso para quem escreve scripts shell sérios, ainda mais difícil do que sinais e subprocessos
    Se o rkhunter tivesse sido escrito em uma linguagem de programação “de verdade”, acho que essas informações seriam menos transparentes. Poderiam ter sido empurradas para registros dentro de estruturas de dados e consultadas ali, ou operadas por várias funções sobre estruturas de dados aninhadas — ou, pior, por uma combinação de métodos e classes. Talvez os logs fossem fatiados em JSON, comprimidos em um banco de dados e acessados por outros métodos
    Como scripts shell não têm esse ferramental complexo, eles tendem, em vez disso, a expor diretamente o que está acontecendo. Por isso o rkhunter também serve como uma documentação razoável sobre vários exploits e rootkits, com menos necessidade de cavar de arquivo em arquivo, de estrutura em estrutura, de banco de dados em banco de dados

  • O cliente do FreeBSD Update tem cerca de 3.600 linhas de código sh
    Não é grande comparado a outros programas mencionados aqui, mas acho que o volume de funcionalidade de uma “ferramenta que atualiza o sistema operacional inteiro” é bem significativo. O código que constrói as atualizações fica dividido em vários arquivos, então somado deve dar ainda mais

  • São “apenas” 7,1 mil linhas, mas um dos meus favoritos é o script acme.sh, usado para emitir e renovar certificados no Let’s Encrypt
    https://github.com/acmesh-official/acme.sh/blob/master/acme....

  • Às vezes, o shell é a única coisa que dá para garantir que estará disponível, e há situações em que portabilidade é indispensável
    Mas, em geral, se você tem uma aplicação shell gigantesca, talvez seja hora de repensar suas escolhas de vida

    • O problema é “qual shell”. Bash está longe de ser universal
      Além disso, normalmente não dá para fazer muita coisa só com o shell; você precisa de comandos como find, grep, sed, cat, head, tail e cut. Esses comandos também têm seus próprios problemas de portabilidade
      Mirar no BusyBox pode ser a melhor opção, mas, no momento em que você sai de um sistema Linux comum, escrever scripts Bourne shell portáveis fica difícil ou quase impossível
    • Ouço esse tipo de argumento com bastante frequência, e fico genuinamente curioso sobre quantos casos existem, na prática, em que há shell, mas não há compilador C, ou em que não é possível instalar um compilador C pelo shell
      Com um compilador C, você pode sair do shell escrevendo programas em C para o script shell compor, ou instalar uma linguagem de script melhor, como Lua. Hoje em dia, os casos em que é obrigatório usar apenas shell parecem ser bem de nicho