Skip to main content

Ba-bash-ka: Exorcizando a Gambiarra dos Scripts Bash com o Poder do Lisp

·1144 words·6 mins·
Table of Contents

Por que decidi usar um dialeto Lisp nos meus scripts de infra?
#

No meu primeiro post aqui no blog, contei sobre como migrei para o Doom Emacs. O que era para ser só uma troca de editor virou uma porta de entrada para um mundo novo. O estalo veio quando saquei que o Emacs é feito de Elisp, uma linguagem que te deixa modificar o editor enquanto você o usa. É quase uma metaprogramação em tempo real.

Até então, eu via linguagem funcional como algo puramente acadêmico e distante. Eu estava acostumado com o arroz com feijão do mercado: o paradigma Imperativo (focado no passo a passo de estados) e o Orientado a Objetos. Sair disso para o funcional foi um choque cultural. Lembro de ter lido o John Carmack comentando que queria ter usado Lisp nos scripts dos jogos dele, e isso ficou na minha cabeça.

Comecei pelo Elisp fazendo o básico: uns atalhos para o Org-mode e ajustes no Doom. Mas eu não queria “quebrar” minha ferramenta principal de trabalho e estudo testando código mal feito, então decidi que precisava aprender um Lisp fora do Emacs.

O buraco do coelho: Qual Lisp escolher?
#

Lisp não é uma linguagem única, é uma família de dialetos. Entrei naquele rabbit hole de fóruns, Reddit e YouTube para decidir qual caminho seguir.

Nesse meio tempo, juntei dois hobbies: infraestrutura e desenvolvimento de games. Eu estava brincando com uma engine em C usando Raylib, e resolvi que usaria Lisp para a lógica dos scripts, deixando o C exclusivamente para a performance bruta da engine.

Descobri que a integração de dialetos Lisp com C é extremamente poderosa por meio de FFI (Foreign Function Interface). Foi aí que achei o Fennel. Ele é um Lisp que compila direto para Lua. Como o Lua tem essa integração quase nativa e de baixíssima latência com C via FFI, o Fennel encaixou como uma luva. Isso permite expor funções da engine diretamente para o script. Ali eu vi o poder real da ferramenta: o hot-reload. Eu alterava uma linha no Fennel e o jogo atualizava na hora, sem precisar de um ciclo de recompilação do C. Parece magia.

A chegada na Infra: Cansado do Python?
#

Na infra, o padrão é Bash, Python e às vezes Go (que eu acho manual demais para scripts rápidos). Bash e Python sempre deram conta do recado, mas eu já estava meio de saco cheio de Python. Talvez seja trauma da faculdade ou apenas saturação da área de desenvolvimento, mas o fato é que eu queria algo que me desse prazer em escrever código novamente.

Nessa busca, passei pelo Common Lisp e pelo Scheme, até cair no Clojure. Ele entrega o poder do Lisp rodando no ecossistema do Java, mas sem a chatice e a verbosidade tradicional do Java. Estudando Clojure, encontrei o “santo graal” da automação: o Babashka.

O que diabos é o Babashka?
#

O grande problema do Clojure para scripts rápidos é o tempo que a JVM (Java Virtual Machine) demora para subir. Para um serviço de backend, não há problema. Para um script que precisa rodar instantaneamente no terminal, é inviável.

O Babashka (ou apenas bb) resolve isso. Ele é um binário nativo compilado com GraalVM. Por baixo dos panos, ele usa o SCI (Small Clojure Interpreter). Em vez de compilar tudo para bytecode Java em tempo de execução, ele interpreta o Clojure usando um subconjunto pré-compilado. O resultado? O startup time é de milissegundos, igual ao do Bash, mas com superpoderes.

Ele já vem “batteries included” para o que precisamos na infra:

  • JSON, YAML e EDN: Parsing nativo sem sofrimento.
  • Shell: Executa comandos do sistema diretamente.
  • HTTP: Cliente embutido para fazer requisições em APIs e Webhooks.
  • File System: Manipulação simples de arquivos e diretórios.

O canivete suíço: Pods, Tasks e Namespaces
#

Já que citei que o Babashka vem com “baterias inclusas”, vale destacar algumas funcionalidades exclusivas do ecossistema dele que mostram por que ele brilha tanto na infraestrutura:

  • Babashka Tasks (Suas “Recipes” nativas): Sabe aquele Makefile gigantesco ou aquele Justfile que você usa para mapear comandos de deploy e automações do dia a dia? O Babashka tem um task runner nativo. Você cria um arquivo bb.edn na raiz do seu diretório e define suas tasks (receitas) e as dependências entre elas. É como um make moderno, integrado e escrito na mesma linguagem dos seus scripts.
  • Babashka Pods: E se as “baterias inclusas” não forem suficientes? Imagine que você precisa conectar direto em um banco PostgreSQL ou usar uma biblioteca super específica escrita em Go ou Rust. Você não precisa voltar para a JVM pesada para isso. Os Pods são binários externos que o Babashka executa e gerencia, comunicando-se com eles via RPC (Remote Procedure Call). No seu código, você chama a função do banco de dados como se fosse uma função nativa do Clojure, mas, por baixo dos panos, o trabalho pesado está sendo feito por um Pod otimizado em Go.
  • Namespaces para Infra: Diferente do Bash, onde dividir o código em múltiplos arquivos geralmente vira uma bagunça de source com vazamento de variáveis globais, o Babashka utiliza o sistema robusto de namespaces do Clojure. Você pode criar um arquivo k8s.clj com funções isoladas do Kubernetes, outro docker.clj e importá-los de forma limpa e modular no seu script principal. Seus scripts de infra ganham arquitetura de software real.

Saindo da teoria: Uso real no trampo
#

A linguagem usa notação polonesa (os operadores vêm antes, como em (+ 1 2) em vez de 1 + 2). Assusta no começo, mas logo você se acostuma. Minha primeira ferramenta foi um script para o meu homelab que lia um JSON com IPs e portas e estabelecia conexões SSH.

Mas o teste real foi no meu trabalho como SysAdmin/SRE Linux. Usei o bb para tarefas que salvaram meu tempo:

  1. Orquestração de Inventário: Criei um script para listar e organizar o acesso SSH a centenas de servidores. Manipular essas listas com as macros do Clojure (como o ->>) é muito mais limpo do que criar um emaranhado de jq, awk e sed.
  2. Tratamento de Dados em Containers: Organizei e formatei dados extraídos de um MySQL rodando em Docker.

Como o Lisp trata dados como código, você não fica brigando com dicionários e loops infinitos como no Python. Você cria um pipeline de transformações e o dado sai do outro lado exatamente do jeito que você precisa. O código fica imutável e extremamente robusto.

Colocando para rodar
#

Se bateu a curiosidade para testar, a instalação é muito direta.

Instalar Runtime no terminal Linux para executar seus scripts:

bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)

Onde estudar?
#

Como não é uma tecnologia “mainstream”, você não vai encontrar milhares de cursos convencionais. O aprendizado é na base da curiosidade e leitura de documentação. Estes foram os links de referência que usei:

Tchau, obrigado.

ScriptJohn_
Author
ScriptJohn_
Apenas um cara que sofre de ‘pcismo’ e gosta de cybersegurança