$ portaldoshell guia grátis

ensaio · 7 min de leitura

O script que pede crachá ao comando

Perguntar a versão é a forma mais educada de adiar o teste.

$ whoami
Julio Cezar Neves

Na guarita envidraçada de uma fábrica antiga, uma vigia jovem de tranças, quepe e uniforme cinza examina com uma lupa enorme o crachá de um caranguejo laranja de capacete amarelo e macacão, que espera com uma caixa de ferramentas aos pés. Atrás do vidro, as máquinas da fábrica soltam fumaça, engrenagens rolam pelo chão e um operário de bigode acena desesperado pedindo socorro.

Script bem escrito testa o que o comando faz e deixa para o RH a pergunta sobre quem ele é. Na quinta-feira, 15 de outubro, essa diferença sai da conversa de corredor e vira prova prática, porque o Ubuntu 26.10 chega com as ferramentas básicas do sistema inteiramente reescritas em Rust. Quem programou contra o comportamento vai atravessar a troca sem perceber que ela aconteceu. Quem programou contra o crachá vai descobrir, do pior jeito, que o crachá mudou.

As notas de lançamento do Ubuntu 26.10 contam a novidade com a secura habitual de documento técnico. Os utilitários padrão passam a rodar sobre o uutils, uma reimplementação em Rust, e os últimos programas GNU que ainda resistiam foram migrados, entre eles o rm, sempre tratado com o respeito devido a quem apaga sem pedir licença. A data de lançamento está no cronograma oficial da versão, e a troca vinha em andamento desde o 25.10.

No resumo do Ubuntu 26.04 para usuários de LTS, a própria Canonical admitia que as ferramentas em Rust ainda guardavam incompatibilidades com as originais, motivo pelo qual o pacote GNU continuou disponível e o rm, ao lado do cp e do mv, ficou na versão GNU por mais um tempo. Gosto dessa franqueza. Distribuição que confessa a incompatibilidade antes do usuário tropeçar nela merece mais confiança que a que promete equivalência perfeita no material de divulgação.

Para quem digita no terminal, a troca passa praticamente despercebida. O ls continua listando e o rm continua apagando com a mesma ausência de remorso. O problema mora em outro lugar, dentro de um tipo de script que todo mundo já escreveu ou já herdou de alguém, aquele que precisa rodar tanto no Linux quanto no macOS e resolve a diferença entre os dois perguntando o nome do comando antes de usá-lo.

O exemplo clássico é calcular a data de amanhã. O date do GNU aceita -d tomorrow, e o date dos sistemas BSD, que inclui o do macOS, usa -v+1d para a mesma tarefa. A solução que mais aparece em repositório por aí confere a primeira linha da versão e escolhe o caminho a partir dela:

if date --version 2>/dev/null | grep -q GNU; then
  amanha=$(date -d tomorrow +%F)
else
  amanha=$(date -v+1d +%F)
fi
echo "$amanha"

Na máquina onde testei, com o Bash 5.2.21 e o date do GNU coreutils 9.4, o script devolveu 2026-10-14 sem reclamar. Depois coloquei no PATH um date que repassava todo o trabalho ao original e mudava só a apresentação, trocando o nome GNU por outro na resposta ao --version. O grep falhou e o script concluiu que estava num BSD. Mandou então o -v+1d para um date que entende -d tomorrow perfeitamente, e a resposta veio seca, com o aviso de opção inválida apontando para o -v.

A parte mais grave veio em seguida. A variável amanha ficou vazia, o echo imprimiu uma linha em branco e o script terminou com código de retorno zero, feliz da vida. Em produção, esse vazio segue adiante para o nome de um arquivo de backup ou para uma consulta ao banco, e alguém só descobre o estrago semanas depois. O script obedeceu à lógica com uma lealdade comovente, e a lógica estava errada desde o primeiro if.

O comando trabalhou direito o tempo todo. Quem falhou foi a pergunta, porque o script quis saber o sobrenome do date quando precisava saber se ele aceitava a opção -d. Perguntar a versão é a forma mais educada de adiar o teste. A pergunta certa cabe numa linha e dispensa qualquer conhecimento sobre a origem do programa:

amanha=$(date -d tomorrow +%F 2>/dev/null) || amanha=$(date -v+1d +%F)

O Shell tenta o jeito GNU e, se o comando devolver erro, parte para o jeito BSD. Rodei essa linha com o date original e com o impostor de nome trocado, e as duas vezes ela entregou 2026-10-14. A linha agora depende só do comportamento do comando, que é exatamente o que o script consome. Como bônus, ficou mais curta que a versão desconfiada, o que costuma acontecer quando o código para de fazer pergunta inútil.

O princípio tem nome antigo e vale muito além do date. Em portabilidade, testa-se a capacidade, e a origem do programa fica como assunto para quem gosta de genealogia. O mesmo raciocínio serve para saber se o sed aceita -i sem argumento, e serve também para descobrir se um comando existe no sistema, tarefa que o command -v resolve com muito mais dignidade que uma comparação de texto contra o nome da distribuição.

Quem esteve na criação de um Unix brasileiro, como foi o meu caso com o SOX, na Cobra Computadores, aprende cedo que o nome gravado na caixa interessa pouco ao programa que roda dentro dela. Um Unix escrito por outra equipe precisa se comportar como Unix, e o programa que roda em cima dele cobra resposta certa a cada chamada. A etiqueta do cabeçalho vale como enfeite, e o script bem escrito herda essa mesma exigência pragmática.

Existe uma vaidade discreta no hábito de checar o fornecedor. Ela dá ao autor do script a sensação de conhecer o terreno, porque ele sabe que no Linux é assim e no Mac é assado, e transforma esse conhecimento num if. Acontece que o terreno muda de dono sem consultar ninguém, e o conhecimento vira lenda urbana. A ferramenta que mais muda num sistema é sempre aquela que o script jurou conhecer de cor.

A mesma versão do Ubuntu traz outra lembrança do gênero. As notas registram a remoção do gerador que transformava em serviço, na hora da inicialização, os velhos scripts do /etc/init.d. Os pacotes do repositório que dependiam dele passaram a trazer um serviço do systemd ou saíram de cena por falta de quem os mantivesse. Quem tinha um script caseiro ali, contando com a gentileza do intermediário, vai precisar conversar com o systemd diretamente.

A Canonical documenta como voltar ao coreutils do GNU para quem precisar de tempo, e o uutils persegue a compatibilidade com o original de forma declarada. Quem escreve script há muitos anos encontra aqui uma verdade incômoda, porque a troca expõe o que já estava frágil antes dela. O Rust apenas acendeu a luz da sala onde o problema morava, e a linguagem nova leva a fama por ter apertado o interruptor.

Aprendi a desconfiar de duas frases em reunião técnica. A primeira é "isso sempre funcionou assim", que costuma anteceder o incidente. A segunda é "esse comando é igual em todo lugar", que costuma anteceder o incidente seguinte. Script que roda há dez anos sem alteração passa a impressão de solidez, e em muitos casos ele só teve a sorte de jamais encontrar um ambiente diferente daquele onde nasceu.

A boa prática custa pouco para adotar. Antes de atualizar uma máquina importante, vale procurar no repositório todo lugar onde um script lê a saída de --version para decidir o caminho, trocando cada um desses testes de identidade por um teste de capacidade. É trabalho de uma tarde, e ele protege contra esta troca e contra todas as próximas, inclusive as que alguém ainda vai anunciar.

PS: Antes de quinta-feira, vale descobrir quantos scripts seus ainda pedem crachá ao comando, e um grep -rn -- '--version' na pasta deles encontra boa parte. Conte nos comentários qual foi o teste de identidade mais criativo que apareceu por lá, e passe o texto adiante para quem cuida do script de deploy herdado. A vigia da portaria vai reclamar da falta de serviço, e o resto do sistema agradece.

$ tee # compartilhe este artigo WhatsApp Telegram LinkedIn

$ cat comentarios.log

lendo o log…

$ ./comentar.sh --artigo script-que-pede-cracha

* obrigatório. Todo comentário passa pelo root antes de entrar no log, e o root daqui é humano.