Skip to content
אצלי
Go back

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

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

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