Skip to main content

Command Palette

Search for a command to run...

sysup: um comando para atualizar todas as suas máquinas em qualquer distro

escrevendo functions no zsh para não precisar reinventar a roda

Updated
5 min read
sysup: um comando para atualizar todas as suas máquinas em qualquer distro
E

Linux power user since 2003. IT Manager, DevOps/SRE, Systems Administrator, and teacher. Bass player, Krav Maga practitioner, and sport shooter.

https://esli.blog || https://esli.cafe

Quem mantém mais de uma distribuição Linux sabe a dor: dnf update aqui, pacman -Syu ali, apt upgrade acolá. Multiplica isso por cinco máquinas — dois laptops com Omarchy e EndeavourOS (Arch), outro com Ubuntu 25.04, um desktop com Fedora 43 e um home server com Debian (sem contar os Raspberries, porque esses a gente finge que não precisa atualizar) — e a tarefa de “rodar um update” vira um exercício de memória muscular para dedos que já não são tão jovens.

A solução? Uma zsh function que detecta o package manager e faz tudo com um único comando: sysup.

Mas antes de chegar nela, vale entender como o Zsh organiza esse tipo de extensão.

A estrutura ~/.zsh/

O Zsh permite organizar customizações em diretórios dedicados. Uma convenção comum (e que uso nos meus dotfiles):

~/.zsh/
├── functions/     # Funções carregadas sob demanda (autoload)
├── completions/   # Scripts de completion customizados (_comando)

functions/

Cada arquivo é uma função. O nome do arquivo = nome da função. Sem extensão, sem shebang. O Zsh carrega o conteúdo do arquivo como corpo da função quando ela é chamada pela primeira vez — isso é o autoload.

completions/

Segue a mesma lógica, mas para funções de completion (_nome). Se você escreve um CLI próprio e quer tab-completion, é aqui que o script de completion fica.

As 4 linhas no ~/.zshrc

fpath=(~/.zsh/functions $fpath)
autoload -Uz ~/.zsh/functions/*(N:t)
autoload -Uz compinit && compinit
autoload -Uz promptinit && promptinit

Linha 1: fpath=(~/.zsh/functions $fpath)

Adiciona ~/.zsh/functions/ ao fpath (function path) — o equivalente do $PATH, mas para funções do Zsh. O Zsh só encontra funções via autoload se elas estiverem em algum diretório listado no $fpath. Ao prepend (~/.zsh/functions antes de $fpath), suas funções têm prioridade sobre as do sistema.

Se tiver um diretório completions/, adicionaria da mesma forma:

fpath=(~/.zsh/completions ~/.zsh/functions $fpath)

Linha 2: autoload -Uz ~/.zsh/functions/*(N:t)

Registra todas as funções do diretório para autoload.

Dissecando:

ComponenteFunção
autoloadMarca uma função para carregamento sob demanda (lazy load)
-USuprime alias expansion — evita conflitos
-zForça estilo Zsh (vs. Ksh)
*(N:t)Glob com qualificadores: N = nullglob (não dá erro se vazio), :t = tail (extrai só o nome do arquivo, sem o path)

O :t é essencial. Sem ele, o autoload receberia /home/user/.zsh/functions/sysup em vez de apenas sysup.

A função não é carregada em memória nesse momento. O Zsh apenas registra que, quando sysup for chamado, deve buscar e carregar o arquivo correspondente. Lazy loading puro.

Linha 3: autoload -Uz compinit && compinit

Carrega e inicializa o sistema de completion do Zsh. O compinit escaneia o $fpath procurando arquivos _* (prefixo underscore) e os registra como funções de completion. Sem isso, nenhum tab-completion customizado funciona.

Linha 4: autoload -Uz promptinit && promptinit

Carrega o sistema de temas de prompt. Permite usar prompt -l para listar temas disponíveis e prompt <tema> para aplicar. Útil se você usa temas de prompt distribuídos via $fpath, embora quem usa Starship ou p10k (meu caso) talvez nunca toque nisso.

O Sysup

Código completo: dotfiles/.zsh/functions/sysup

# Description: Dynamic package manager detection and global system update
# Usage: sysup

_sysup_log() {
  print -P "%F{blue}==>%f %B$1%b"
}

# 1. Universal Package Managers (Sandboxed)
if command -v flatpak &>/dev/null; then
  _sysup_log "Updating Flatpaks..."
  flatpak update -y
fi

if command -v snap &>/dev/null; then
  _sysup_log "Refreshing Snaps..."
  sudo snap refresh
fi

# 2. Native System Package Managers
if command -v dnf &>/dev/null; then
  _sysup_log "Running DNF Update..."
  sudo dnf update -y
elif command -v yay &>/dev/null; then
  _sysup_log "Running Yay (AUR/Pacman)..."
  yay -Syu --noconfirm
elif command -v pacman &>/dev/null; then
  _sysup_log "Running Pacman..."
  sudo pacman -Syu --noconfirm
elif command -v apt &>/dev/null; then
  _sysup_log "Running APT..."
  sudo apt update && sudo apt upgrade -y
elif command -v yum &>/dev/null; then
  _sysup_log "Running YUM..."
  sudo yum update -y
elif command -v zypper &>/dev/null; then
  _sysup_log "Running Zypper..."
  sudo zypper patch
fi

_sysup_log "System update completed."

Lógica

O script faz detecção dinâmica de package manager via command -v e executa o update apropriado.

Divide em duas categorias:

1. Package managers universais (sandboxed) — sempre executados se presentes:

if command -v flatpak &>/dev/null; then
  _sysup_log "Updating Flatpaks..."
  flatpak update -y
fi
if command -v snap &>/dev/null; then
  _sysup_log "Refreshing Snaps..."
  sudo snap refresh
fi

Flatpak e Snap coexistem com o gerenciador nativo, então ambos rodam independentemente (blocos if paralelos, não elif).

2. Package manager nativo — mutuamente exclusivo:

if command -v dnf &>/dev/null; then
  sudo dnf update -y
elif command -v yay &>/dev/null; then
  yay -Syu --noconfirm
elif command -v pacman &>/dev/null; then
  sudo pacman -Syu --noconfirm
elif command -v apt &>/dev/null; then
  sudo apt update && sudo apt upgrade -y
elif command -v yum &>/dev/null; then
  sudo yum update -y
elif command -v zypper &>/dev/null; then
  sudo zypper patch
fi

A cadeia elif garante que apenas um gerenciador nativo execute. A ordem importa:

  • yay antes de pacman: se yay está instalado, é preferível porque já cobre AUR + repositórios oficiais

  • dnf antes de yum: em distros modernas baseadas em Red Hat, dnf é o padrão

  • apt cobre Debian/Ubuntu

Detecção com command -v

O command -v é preferível a which porque:

  • É um builtin do shell (não depende de binário externo)

  • Retorna 0/1 de forma confiável

  • which tem comportamentos inconsistentes entre distros

O redirecionamento &>/dev/null suprime stdout e stderr — queremos apenas o exit code.

Usando…

Só chamar o sysup

Só… Simples, rápido, fácil… sem reinventar a roda, sem precisar de milhares de validações, variáveis e etc. Pois conheço meu ambiente.

Uma função, qualquer máquina. Os mesmos dotfiles sincronizados via Git em todas as máquinas, e cada uma executa o caminho correto automaticamente.

O código está disponível no repositório dotfiles — com o resto da minha configuração de Zsh.

Tech

Part 3 of 50

Technical topics. Code, Linux, Network... Exercising the Tech Writer and teacher in me. Articles covering topics from across the entire OSI layer. Artigos passando por assuntos de toda a camada OSI.

Up next

AI Coding com Agents Locais e Open Source

O Guia para SREs e DevOps levarem a AI ao próximo nível