Skip to content
אצלי
Go back

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

Tela de computador exibindo linhas de código
Foto de Daniil Komov na Unsplash

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:

Detecção com command -v

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

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.


Share this post on:

Previous Post
How to get rid of ads everywhere
Next Post
Não caia no hype anti-AI