A oficina reproduzível
Este capítulo transforma o terminal de uma tela intimidadora em uma oficina observável. O leitor distingue terminal, shell, comando, processo, argumento, fluxo, variável de ambiente, PATH, diretório atual e código de saída; executa exemplos seguros em PowerShell e Python; e aprende por que copiar comandos sem entender aspas e expansão pode causar dano. A segunda metade conecta ambientes isolados, manifestos, lockfiles, runtimes, configuração e segredos à reprodução de uma aplicação de manutenção. Diagnósticos de “comando não encontrado”, permissão, versão e caminho são tratados por evidência. Segurança de cadeia de suprimentos e promoção do mesmo artefato completam o modelo sem prometer que um lockfile congela o sistema inteiro.
A oficina reproduzível
Situação concreta: funciona no computador de quem criou
Uma automação importa ordens de serviço quando o desenvolvedor executa python importar.py, mas falha na máquina de homologação. O arquivo está em outra pasta, a versão do Python é diferente e uma variável de configuração existe somente no perfil pessoal do desenvolvedor. A frase “funciona na minha máquina” não encerra o diagnóstico; revela dependências que ainda não foram declaradas.
O terminal permite observar e controlar esse contexto. Ele não é um lugar mágico onde frases viram ações: uma linguagem de shell interpreta texto, localiza um programa, cria um processo e entrega argumentos, ambiente e fluxos. Conhecer essa cadeia dá autonomia e também mostra onde um comando perigoso pode atuar.
Pré-requisitos e objetivos
Você deve saber o que são processo, arquivo e caminho. Não precisa memorizar comandos. Ao final, deverá explicar cada parte de uma execução, reproduzir um ambiente mínimo e investigar falhas sem “tentar como administrador”.
Vocabulário essencial
- Terminal é a interface que exibe saída e captura entrada textual.
- Shell é o programa e linguagem que interpreta comandos, como PowerShell ou Bash.
- CLI, command-line interface, é a interface textual de um programa, como
python --version. - Comando é a instrução submetida ao shell; executável é o programa localizado.
- Argumento é um valor entregue ao programa. Espaços e aspas determinam seus limites.
- stdin, entrada padrão, fornece dados ao processo.
- stdout, saída padrão, carrega o resultado normal.
- stderr, saída de erro padrão, carrega diagnóstico.
- Código de saída é o número devolvido pelo processo; zero normalmente indica sucesso.
- Diretório atual é a base para caminhos relativos.
- PATH é a lista de diretórios onde o shell procura executáveis.
- Variável de ambiente é uma configuração textual herdada pelo processo.
- Runtime sustenta a execução, como Python ou Node.js.
- Manifesto declara dependências e metadados do projeto.
- Lockfile registra uma resolução específica de dependências.
- SBOM, software bill of materials, é uma lista de componentes de software do artefato.
Modelo mental: da linha digitada ao processo
Ler o fluxo em texto
- 1. Pessoa digita uma linha
- 2. Shell interpreta sintaxe
- 3. PATH localiza o executável
- 4. SO cria o processo
- 5. Processo recebe argumentos e ambiente
- 6. Programa lê stdin e arquivos
- 7. Programa escreve stdout e stderr
- 8. Shell recebe código de saída
O fluxo não captura todos os casos. Funções internas do shell podem não criar outro processo, pipelines acrescentam vários processos e PowerShell transporta objetos entre comandos até precisar de texto. Ainda assim, o modelo localiza as decisões principais.
Progressão 1 — comandos não são frases
Em python importar.py --limite 20, o shell separa o executável e três argumentos. Aspas preservam espaços: --arquivo "ordens abertas.json" entrega um caminho, não dois. Operadores como redirecionamento e pipeline pertencem ao shell, não ao programa.
Por isso, um exemplo de Bash não deve ser colado cegamente no PowerShell. Bash normalmente conecta bytes em pipelines; PowerShell costuma conectar objetos. Sintaxe de variáveis, aspas e código de retorno também muda. Documente qual shell e versão um script espera.
Copiar comando desconhecido é executar código. Expansões, substituições e redirecionamentos podem alterar o alcance. Antes de mover ou remover: resolva caminho absoluto, liste o alvo, confirme que está dentro do projeto e prefira operação reversível. Não use raiz, pasta pessoal ou variável ampla como alvo recursivo.
Progressão 2 — caminhos, PATH e processos
Um caminho relativo depende do diretório atual. O mesmo dados/ordens.json pode apontar para lugares diferentes. PATH não contém arquivos; contém diretórios pesquisados na ordem. “Comando não encontrado” pode significar programa ausente, instalação fora do PATH ou nome incorreto.
Ao executar, o shell cria um processo com seu próprio identificador. Alterar uma variável no terminal afeta processos iniciados depois, não retroativamente. Um processo filho herda uma cópia do ambiente e não consegue, de modo geral, alterar permanentemente o shell pai.
Progressão 3 — entrada, saídas e composição
Separar stdout e stderr permite encadear resultado sem misturar diagnóstico. Um pipeline usa a saída de um programa como entrada de outro, mas exige contrato estável. Se o primeiro falha e o segundo continua com entrada vazia, a automação pode produzir resultado enganoso. Verifique códigos de saída e configure o pipeline conforme o shell.
Ao chamar outro programa de Python, passe argumentos como lista, não como uma string de shell:
import subprocess
resultado = subprocess.run(
["python", "--version"],
check=True,
capture_output=True,
text=True,
timeout=10,
)
print("stdout:", resultado.stdout.strip())
print("stderr:", resultado.stderr.strip())
print("codigo:", resultado.returncode)check=True transforma retorno diferente de zero em exceção. timeout evita espera infinita; captura permite inspeção. Não use shell=True com entrada externa: a string voltaria a ser código interpretado pelo shell.
Progressão 4 — ambiente e configuração
Configuração varia entre ambientes; regras essenciais continuam versionadas. Variável de ambiente é adequada para endereço ou modo, mas não valida valor automaticamente. Uma variável ausente deve falhar com mensagem útil antes de iniciar trabalho parcial.
Segredo não deve estar no código, no manifesto, no histórico ou em logs. Variável de ambiente é melhor que versionar, mas pode aparecer em dump, processo filho ou falha. Em produção, use um gerenciador de segredos com identidade, escopo, rotação e auditoria. Um .env.example contém apenas nomes e valores inofensivos.
Desenvolvimento, integração, homologação e produção precisam de credenciais e dados separados. Ambiente de teste não deve ter poder de produção. Cópia de dados reais exige autorização, minimização e anonimização eficaz; dados sintéticos são preferíveis para muitos testes.
Progressão 5 — dependências e reprodução
Dependência é código ou ferramenta externa. O manifesto declara intenção; o lockfile registra a resolução, inclusive componentes transitivos. Um ambiente virtual Python separa pacotes entre projetos. Isso reduz interferência, mas não fixa kernel, compilador, locale ou serviço externo.
Reprodução possui camadas:
- código e manifesto;
- lockfile;
- runtime suportado;
- bibliotecas do sistema ou imagem;
- configuração declarada;
- serviços externos e dados de teste;
- comando de verificação.
“Instalação limpa” testa se dependências implícitas foram removidas. Recrie o ambiente a partir dos artefatos, rode formato, testes e build. Não atualize tudo automaticamente sem avaliação; também não congele vulnerabilidades para sempre. Faça mudanças pequenas, revise origem e changelog e execute verificações.
Antes e agora
Era comum instalar ferramentas globalmente e registrar passos num documento. Isso ainda atende casos simples, mas acumula diferenças. Hoje, ambientes virtuais, gerenciadores de versão, lockfiles, contêineres e integração contínua tornam o bootstrap executável. A recomendação não é “containerizar tudo”; é usar a menor camada que torna o resultado reproduzível e mensurável.
Na cadeia de suprimentos atual, pacote pode executar scripts durante instalação. Lockfile ajuda integridade da resolução, não prova que o pacote é confiável. Proveniência, SBOM, assinatura, scanner e revisão reduzem risco. Promova o mesmo artefato testado entre ambientes; recompilar para produção cria outro objeto.
Exemplo PowerShell, bloco a bloco
No PowerShell, execute numa pasta de laboratório:
$projectRoot = (Resolve-Path '.').Path
Write-Output "Projeto: $projectRoot"
Get-ChildItem -LiteralPath $projectRoot -Force
$env:APP_ENV = 'development'
python --version
if ($LASTEXITCODE -ne 0) { throw 'Python falhou' }Resolve-Path torna o alvo explícito. -LiteralPath impede interpretação de curingas. A variável APP_ENV vale para processos filhos desta sessão. $LASTEXITCODE contém retorno do executável nativo. Não reutilize nomes especiais como $HOME para outra finalidade.
Aplicação em manutenção e ERP
Um importador pode depender de Python 3.12, pacote fixado, URL da interface de programação de aplicações (API) do sistema de planejamento de recursos empresariais (ERP) e credencial de homologação. Documente cada dependência. O comando doctor diagnostica; verify valida código; run executa trabalho.
O job precisa de diretório, usuário, timeout, arquivo de entrada e destino de logs definidos. Não passe token na linha de comando, pois listas de processos e histórico podem expô-lo. Registre identificador de lote, não payload inteiro.
Falhas e diagnóstico
- comando não encontrado: registre shell, PATH e instalação; não reinstale aleatoriamente;
- versão errada: compare requerida e observada, depois escolha runtime correto;
- arquivo não encontrado: registre diretório atual e caminho absoluto;
- acesso negado: descubra usuário, alvo e permissão necessária; não eleve tudo;
- import ausente: confirme ambiente ativo e lockfile instalado;
- resultado divergente: compare locale, fuso, configuração, runtime e dados;
- processo travado: preserve comando sanitizado, PID, tempo e saída antes de encerrar.
Uma boa mensagem mostra esperado, observado e correção segura. Permission denied não autoriza administrador; pode revelar diretório errado.
Segurança, privacidade e custo
Trate comandos como código e argumentos como dados. Não concatene entrada do usuário em shell, SQL ou caminho destrutivo. Limite tempo e volume de saída de processos filhos. Use conta com menor privilégio e diretório temporário específico.
Ambientes duplicados ocupam disco e tempo, mas compartilhar ambiente global aumenta interferência. Limpe somente alvos resolvidos e recriáveis. Caches aceleram instalação, porém precisam de integridade e política de retenção.
Exercício guiado
Em duas pastas, execute o exemplo Python e o PowerShell. Registre shell, diretório, versão e código. Remova python do teste substituindo por um nome inexistente e observe a camada da falha. Depois defina APP_ENV, inicie um processo Python que a imprima e confirme herança.
Desafio e evidência
Escreva SETUP.md com pré-requisitos, bootstrap, doctor, verify, falhas conhecidas e limpeza segura. Outra pessoa deve reproduzir numa pasta nova.
Critérios de aceite:
- comandos indicam shell e versão esperada;
- caminhos destrutivos são absolutos, validados e restritos;
- instalação parte de ambiente isolado e lockfile;
- ausência de configuração falha antes de efeito parcial;
- transcript não contém segredo nem dump completo do ambiente;
- teste e build produzem código de saída verificável.
Conclusão e transição
Terminal é interface; shell interpreta; CLI recebe argumentos; processo herda ambiente e diretório. Reprodutibilidade exige declarar mais que pacotes: runtime, configuração e verificação. Feche o texto e explique manifesto versus lockfile, stdout versus stderr e por que variável de ambiente não é cofre. No laboratório, você construirá bootstrap e diagnóstico do zero.
Fontes oficiais
- Microsoft — PowerShell overview: conceitos e documentação da linguagem.
- GNU Bash Reference Manual: semântica do shell Bash.
- Python —
venv: criação de ambientes virtuais. - Python Packaging User Guide: instalação e ambientes.
- SLSA specification 1.2: níveis e ameaças de cadeia de suprimentos.
Comprove o que você aprendeu
Responda todas as questões. O gabarito comentado só aparece depois do envio.