CommunityEscrita e Ediçãogithub.com

pwquint24/org-babel-shell

Guia completo para automação de sistemas, DevOps, execução remota e scripting de shell (Bash, Zsh, Fish, Dash, Sh) com Org Babel.

O que é org-babel-shell?

Esta skill fornece um guia abrangente para usar blocos de código Shell no Org Babel, transformando o Emacs Org Mode em um caderno interativo de DevOps e console de administração de sistemas. Ela cobre shells Unix e POSIX como Bash, Zsh, Fish, Dash, Sh e outros, suportando modos de execução isolada, sessão interativa e assíncrona (não bloqueante). A skill explica como especificar shells diferentes, usar argumentos de cabeçalho específicos como `:stdin`, `:cmdline` e `:shebang`, e executar comandos em servidores remotos via TRAMP (`:dir`). Inclui também práticas recomendadas de segurança, tratamento de armadilhas comuns e um exemplo completo de runbook DevOps, sendo útil para desenvolvedores e engenheiros de infraestrutura que desejam automatizar e documentar fluxos de trabalho diretamente no Emacs.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pwquint24/org-babel-agent-skills/tree/HEAD/skills/org-babel-shell

Installed? Explore more Escrita e Edição skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Blocos de Código Shell & Bash no Org Babel

O Org Babel oferece suporte abrangente a scripts de shell em shells Unix e POSIX: Bash, Zsh, Sh, Fish, Dash, Csh, Ksh e Ash.

Blocos de shell transformam o Org Mode em um caderno interativo de DevOps, runbook e console de administração de sistemas, capaz de execução local, processamento assíncrono em segundo plano e administração remota de servidores via SSH com TRAMP.


1. Requisitos e Configuração

1.1 Configuração do Emacs

Ao contrário de outras linguagens Babel que exigem módulos separados, todos os shells são governados por uma única biblioteca Babel (ob-shell). Você só precisa de (shell . t) em seu org-babel-load-languages:

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (shell      . t)))

(Nota: Antes do Org 8.2, isso era chamado de sh. Use shell em todas as versões modernas do Org).

1.2 Especificando o Shell

Especifique o nome exato do binário do shell como a tag de linguagem do bloco (#+BEGIN_SRC <shell>):

# Bash:
#+BEGIN_SRC bash
  echo "Executando em $BASH_VERSION"
#+END_SRC

# Zsh:
#+BEGIN_SRC zsh
  echo "Executando em Zsh $ZSH_VERSION"
#+END_SRC

# POSIX / Dash (execução mais rápida e leve):
#+BEGIN_SRC dash
  echo "Executando em dash"
#+END_SRC

# Fish shell:
#+BEGIN_SRC fish
  set greeting "Olá do fish"
  echo $greeting
#+END_SRC

O binário do shell especificado deve estar acessível em seu $PATH do sistema.


2. Modos de Execução: Isolado, Sessão e Assíncrono

2.1 Subshell Isolado (Padrão, :session none)

Cada bloco executa em um novo processo subshell temporário. Variáveis de ambiente e diretórios de trabalho não são preservados:

#+BEGIN_SRC bash :results output
  echo "PID: $$"
  export WORKSPACE="/tmp/build"
#+END_SRC

#+BEGIN_SRC bash :results output
  # $WORKSPACE está vazio aqui porque isso executa em um novo processo subshell:
  echo "PID: $$, WORKSPACE: $WORKSPACE"
#+END_SRC

2.2 Sessões Interativas (:session <nome>)

Executa dentro de um buffer comint persistente do Emacs (ex.: *dev-session*). Variáveis, funções e diretórios de trabalho persistem entre vários blocos:

#+BEGIN_SRC bash :session *dev-session* :results output
  export CLUSTER_ID="prod-east-01"
  cd /var/log
#+END_SRC

#+BEGIN_SRC bash :session *dev-session* :results output
  # Usa o estado definido no bloco anterior:
  echo "Implementando em $CLUSTER_ID a partir de $(pwd)"
#+END_SRC

#+RESULTS:
: Implementando em prod-east-01 a partir de /var/log

2.3 Execução Assíncrona Não Bloqueante (:async yes)

Scripts de longa duração (backups, compilações de contêineres, treinamento de modelos) congelam o Emacs quando executados de forma síncrona. Adicione :async yes para executá-los em segundo plano sem travar o editor!

Regras:

  1. :async requer :session <nome>.
  2. Durante a execução, o Babel insere um token UUID temporário no bloco #+RESULTS:.
  3. Quando a execução termina em segundo plano, o UUID é automaticamente substituído pela saída padrão do comando.
#+BEGIN_SRC bash :session *bg-job* :async yes :results output
  echo "Iniciando backup pesado do banco de dados em $(date)..."
  sleep 5
  echo "Backup concluído com sucesso em $(date)!"
#+END_SRC

#+RESULTS:
: Iniciando backup pesado do banco de dados em Sun May 18 14:00:00 UTC 2025...
: Backup concluído com sucesso em Sun May 18 14:00:05 UTC 2025!

Para executar de forma síncrona em uma sessão, use :async no.


3. Argumentos de Cabeçalho Específicos para Shell

O Org Babel fornece três argumentos de cabeçalho exclusivos, adaptados especificamente para operações de shell:

3.1 :stdin <nome-do-elemento> (Entrada Padrão)

Envia elementos nomeados do Org (tabelas, texto bruto ou resultados de outros blocos de código) para o stdin do comando shell:

# Entrada de texto bruto:
#+NAME: raw_server_payload
{"node": "alpha", "cores": 8, "status": "active"}

# Envia o payload diretamente para o jq:
#+BEGIN_SRC bash :stdin raw_server_payload :results output
  jq -r '.node + " has " + (.cores|tostring) + " cores"'
#+END_SRC

#+RESULTS:
: alpha has 8 cores

(Nota: Blocos usando :stdin são avaliados em um subshell temporário, ignorando :session).

3.2 :cmdline <args> (Argumentos de Linha de Comando)

Passa argumentos posicionais ($1, $2, $@) para o corpo do script:

#+BEGIN_SRC bash :cmdline "staging" 8080 :results output
  ENV="$1"
  PORT="$2"
  echo "Iniciando servidor na porta $PORT no modo $ENV..."
#+END_SRC

#+RESULTS:
: Iniciando servidor na porta 8080 no modo staging...

⚠️ Aviso de Segurança: Argumentos :cmdline são expandidos diretamente pelo shell hospedeiro. Não passe strings não confiáveis ou sem escape para evitar injeção de comando.

3.3 :shebang <diretiva> (Scripts Independentes e Saída Limpa)

Força o bloco a ser escrito em um arquivo executável temporário e executado via sua diretiva shebang:

#+BEGIN_SRC bash :shebang "#!/usr/bin/env bash" :results output
  for i in {1..3}; do
      echo "Passo $i"
  done
#+END_SRC

Por que :shebang é essencial: Em blocos :session de várias linhas sem um shebang, as linhas são enviadas linha por linha para o shell interativo, o que pode produzir prompts indesejados (ex.: bash-5.1$ ) nos resultados. Especificar :shebang ou executar sem uma sessão produz uma saída completamente limpa.


4. Administração Remota de Servidores via TRAMP (:dir)

Você pode executar comandos em servidores remotos, máquinas virtuais ou contêineres Docker especificando um caminho TRAMP em :dir:

:dir /ssh:<usuário>@<host>:<caminho-remoto>
:dir /docker:<id-do-contêiner>:<caminho>
:dir /sudo::/etc

Exemplo: Fluxo de Trabalho de Sysadmin Remoto

# Verifica uso de disco e memória em um servidor remoto:
#+BEGIN_SRC bash :dir /ssh:[email protected]:/tmp :results output
  hostname
  uptime
  df -h / | awk 'NR==2 {print "Uso do Disco Raiz: " $5}'
#+END_SRC

#+RESULTS:
: bastion.example.com
: 14:22:05 up 42 days,  3:18,  1 user,  load average: 0.12, 0.08, 0.05
: Uso do Disco Raiz: 48%

Sessões Remotas

Combine :dir com :session para manter uma conexão SSH ativa em vários blocos sem reconectar a cada etapa:

#+BEGIN_SRC bash :dir /ssh:[email protected]:/home/admin :session *remote-bastion* :results output
  WORKDIR=$(mktemp -d)
  cd "$WORKDIR"
  pwd
#+END_SRC

5. Formatos de Resultado e Extração de Dados Tabulares

5.1 Saída Delimitada por Tabulação para Tabela Org (:results output table)

Quando comandos shell emitem saída tabular separada por tabulações ou estruturada, o Babel os analisa em tabelas Org nativas:

#+BEGIN_SRC bash :results output table
  printf "PID\tUser\tCommand\n"
  printf "101\troot\tsystemd\n"
  printf "405\tpostgres\tpostgres\n"
  printf "892\tnginx\tnginx: worker\n"
#+END_SRC

#+RESULTS:
| PID | User     | Command       |
|-----+----------+---------------|
| 101 | root     | systemd       |
| 405 | postgres | postgres      |
| 892 | nginx    | nginx: worker |

5.2 Direcionando a Saída para um Link de Arquivo (:results file :file <caminho>)

#+BEGIN_SRC bash :results file :file reports/sysinfo.txt
  uname -a > reports/sysinfo.txt
  cat /etc/os-release >> reports/sysinfo.txt
#+END_SRC

#+RESULTS:
[[file:reports/sysinfo.txt]]

6. Passando Variáveis e Arrays Bash (:var)

6.1 Escalares e Strings

#+BEGIN_SRC bash :var port=8000 host="localhost" :results output
  echo "Conectando a $host na porta $port..."
#+END_SRC

6.2 Arrays 1D do Bash

O Bash suporta parâmetros de array 1D definidos com sintaxe de lista:

#+BEGIN_SRC bash :results output :var servers='("web-01" "web-02" "db-01")'
  echo "Total de servidores: ${#servers[@]}"
  for s in "${servers[@]}"; do
      echo "Pingando $s..."
  done
#+END_SRC

#+RESULTS:
: Total de servidores: 3
: Pingando web-01...
: Pingando web-02...
: Pingando db-01...

7. Armadilhas Comuns e Melhores Práticas de Segurança

ArmadilhaCausaSolução
Emacs trava em comando SSH ou ffmpegComando tenta ler stdin do subshellRedirecione stdin explicitamente (</dev/null) ou use ssh -n.
Caracteres de prompt bash-5.1$ indesejados nos resultadosEco linha por linha interativo em :sessionAdicione :shebang #!/usr/bin/env bash ou avalie fora da sessão.
Expansão inadvertida de variáveis em heredocsUsar <<EOF permite que o shell expanda $VARS prematuramenteUse delimitador com aspas <<"EOF" para manter o texto literal e evitar expansão precoce.
Sintaxe não-POSIX falhando em blocos sh#+BEGIN_SRC sh mapeia para /bin/sh (geralmente dash no Debian/Ubuntu)Use #+BEGIN_SRC bash se seu script usar bashismos ([[, ((, arrays).
Injeção de comando via :cmdlineArgumentos do shell avaliados literalmenteCite os argumentos com cuidado ou passe dados via :stdin ou :var.
Saída de bloco assíncrono não aparecendo:async yes requer uma :session ativaSempre forneça um :session <nome> ao usar :async yes.

8. Exemplo Completo de Runbook DevOps

#+TITLE: Runbook de Saúde do Serviço de Produção
#+PROPERTY: header-args:bash :session *runbook* :results output

* Etapa 1: Configuração de Verificação de Saúde
#+NAME: cluster_nodes
| Hostname        | Função    |
|-----------------+-----------|
| prod-app-01.lan | backend   |
| prod-app-02.lan | backend   |
| prod-db-01.lan  | armazenamento |

* Etapa 2: Sondar Nós do Cluster
#+BEGIN_SRC bash :var nodes=cluster_nodes :colnames yes :results output table
  printf "Host\tFunção\tStatus\n"
  for row in "${nodes[@]}"; do
      # Analisa os dados da linha separados por tabulação/espaço:
      host=$(echo "$row" | awk '{print $1}')
      role=$(echo "$row" | awk '{print $2}')
      
      # Sonda rápida de ping:
      if ping -c 1 -W 1 "$host" > /dev/null 2>&1; then
          status="ONLINE"
      else
          status="OFFLINE"
      fi
      printf "%s\t%s\t%s\n" "$host" "$role" "$status"
  done
#+END_SRC

#+RESULTS:
| Host            | Função         | Status |
|-----------------+-----------------+--------|
| prod-app-01.lan | backend         | ONLINE |
| prod-app-02.lan | backend         | ONLINE |
| prod-db-01.lan  | armazenamento   | ONLINE |

* Etapa 3: Executar Manutenção de Serviço Assincronamente
#+BEGIN_SRC bash :session *runbook* :async yes
  echo "Iniciando purga de cache em rotação nos nós..."
  sleep 4
  echo "Purga de cache concluída com sucesso."
#+END_SRC

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Habilidades Relacionadas