Package management automation: apt, yum, dnf em scripts
1. Fundamentos do Gerenciamento de Pacotes em Scripts
1.1. Diferenças entre apt, yum e dnf: comandos equivalentes e sintaxe
Automatizar o gerenciamento de pacotes exige compreender as diferenças entre os principais gerenciadores. O apt é usado em distribuições baseadas em Debian (Ubuntu, Debian), enquanto yum (legado) e dnf (moderno) são usados em distribuições baseadas em Red Hat (CentOS, Fedora, RHEL).
Tabela de comandos equivalentes:
| Operação | apt | yum | dnf |
|---|---|---|---|
| Instalar | apt install -y |
yum install -y |
dnf install -y |
| Remover | apt remove --purge |
yum remove |
dnf remove |
| Atualizar cache | apt update |
yum makecache |
dnf makecache |
| Atualizar sistema | apt upgrade -y |
yum update -y |
dnf upgrade -y |
| Buscar pacote | apt-cache search |
yum search |
dnf search |
1.2. Verificação de presença do gerenciador (detecção automática da distribuição)
Para criar scripts portáveis, é essencial detectar automaticamente qual gerenciador está disponível:
#!/bin/bash
detect_package_manager() {
if command -v apt &> /dev/null; then
echo "apt"
elif command -v dnf &> /dev/null; then
echo "dnf"
elif command -v yum &> /dev/null; then
echo "yum"
else
echo "unknown"
fi
}
PM=$(detect_package_manager)
echo "Gerenciador detectado: $PM"
1.3. Estrutura básica de um script de instalação condicional
#!/bin/bash
install_package() {
local package=$1
local pm=$2
case $pm in
apt)
apt install -y "$package"
;;
dnf)
dnf install -y "$package"
;;
yum)
yum install -y "$package"
;;
*)
echo "Gerenciador não suportado: $pm"
return 1
;;
esac
}
PM=$(detect_package_manager)
install_package "curl" "$PM"
2. Instalação e Remoção Automatizada de Pacotes
2.1. Uso de apt install -y, yum install -y e dnf install -y em scripts
A flag -y (ou --assumeyes) é crucial para evitar prompts interativos:
#!/bin/bash
# Instalação silenciosa de múltiplos pacotes
PACOTES=("git" "vim" "htop" "wget")
for pkg in "${PACOTES[@]}"; do
echo "Instalando $pkg..."
case $PM in
apt) apt install -y "$pkg" ;;
dnf) dnf install -y "$pkg" ;;
yum) yum install -y "$pkg" ;;
esac
done
2.2. Remoção segura com apt remove --purge, yum remove, dnf remove
#!/bin/bash
remove_package() {
local package=$1
local pm=$2
case $pm in
apt)
apt remove --purge -y "$package"
apt autoremove -y
;;
dnf)
dnf remove -y "$package"
dnf autoremove -y
;;
yum)
yum remove -y "$package"
yum autoremove -y
;;
esac
}
2.3. Tratamento de dependências e pacotes não encontrados (exit codes e ||)
#!/bin/bash
install_or_fail() {
local package=$1
local pm=$2
if ! install_package "$package" "$pm"; then
echo "ERRO: Falha ao instalar $package" >&2
return 1
fi
echo "Sucesso: $package instalado"
}
install_or_fail "nginx" "$PM" || exit 1
3. Atualização e Upgrade do Sistema via Script
3.1. Comandos de atualização
#!/bin/bash
system_update() {
local pm=$1
case $pm in
apt)
apt update && apt upgrade -y
;;
dnf)
dnf upgrade -y
;;
yum)
yum update -y
;;
esac
}
3.2. Estratégias para evitar interatividade (env vars)
Para evitar prompts interativos em sistemas Debian/Ubuntu:
#!/bin/bash
export DEBIAN_FRONTEND=noninteractive
export NEEDRESTART_MODE=a
apt update && apt upgrade -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"
3.3. Verificação de pacotes retidos e necessidade de reboot
#!/bin/bash
check_reboot_needed() {
if [ -f /var/run/reboot-required ]; then
echo "ATENÇÃO: Reboot necessário após atualizações"
return 0
fi
# Verifica pacotes retidos (apt)
if command -v apt-mark &> /dev/null; then
local held=$(apt-mark showhold)
if [ -n "$held" ]; then
echo "Pacotes retidos: $held"
fi
fi
return 1
}
4. Busca e Consulta de Pacotes Programaticamente
4.1. Uso de apt-cache search, yum search e dnf search com grep
#!/bin/bash
search_package() {
local term=$1
local pm=$2
case $pm in
apt)
apt-cache search "$term" | grep -i "$term"
;;
dnf)
dnf search "$term" 2>/dev/null | grep -i "$term"
;;
yum)
yum search "$term" 2>/dev/null | grep -i "$term"
;;
esac
}
4.2. Consulta de versão instalada
#!/bin/bash
get_installed_version() {
local package=$1
local pm=$2
case $pm in
apt)
dpkg -l "$package" 2>/dev/null | awk '/^ii/ {print $3}'
;;
dnf|yum)
rpm -q "$package" 2>/dev/null
;;
esac
}
4.3. Validação de disponibilidade antes da instalação
#!/bin/bash
is_available() {
local package=$1
local pm=$2
case $pm in
apt)
apt-cache show "$package" &> /dev/null
;;
dnf)
dnf list available "$package" &> /dev/null
;;
yum)
yum list available "$package" &> /dev/null
;;
esac
}
if is_available "nginx" "$PM"; then
install_package "nginx" "$PM"
else
echo "Pacote nginx não encontrado nos repositórios"
fi
5. Instalação de Pacotes a Partir de Repositórios Customizados
5.1. Adição de repositórios via script
#!/bin/bash
add_repository() {
local repo=$1
local pm=$2
case $pm in
apt)
add-apt-repository -y "$repo"
apt update
;;
dnf)
dnf config-manager --add-repo "$repo"
dnf makecache
;;
yum)
yum-config-manager --add-repo "$repo"
yum makecache
;;
esac
}
5.2. Instalação de pacotes .deb e .rpm locais
#!/bin/bash
install_local_package() {
local file=$1
local pm=$2
case $pm in
apt)
dpkg -i "$file" || apt-get install -f -y
;;
dnf|yum)
rpm -ivh "$file"
;;
esac
}
5.3. Atualização de cache de repositórios após adição
#!/bin/bash
refresh_cache() {
local pm=$1
case $pm in
apt) apt update ;;
dnf) dnf makecache ;;
yum) yum makecache ;;
esac
}
6. Scripts Idempotentes e Tratamento de Erros
6.1. Verificação de pacote já instalado antes de instalar
#!/bin/bash
is_installed() {
local package=$1
local pm=$2
case $pm in
apt)
dpkg -s "$package" &> /dev/null
;;
dnf|yum)
rpm -q "$package" &> /dev/null
;;
esac
}
install_if_missing() {
local package=$1
local pm=$2
if ! is_installed "$package" "$pm"; then
install_package "$package" "$pm"
else
echo "$package já está instalado"
fi
}
6.2. Funções genéricas com case
#!/bin/bash
package_operation() {
local operation=$1
local package=$2
local pm=$3
case $pm:$operation in
apt:install) apt install -y "$package" ;;
dnf:install) dnf install -y "$package" ;;
yum:install) yum install -y "$package" ;;
apt:remove) apt remove --purge -y "$package" ;;
dnf:remove) dnf remove -y "$package" ;;
yum:remove) yum remove -y "$package" ;;
*) echo "Operação não suportada"; return 1 ;;
esac
}
6.3. Logging e captura de erros com trap
#!/bin/bash
LOG_FILE="/var/log/package-install.log"
exec 2>> "$LOG_FILE"
error_handler() {
local line=$1
local exit_code=$2
echo "Erro na linha $line (código $exit_code)" >> "$LOG_FILE"
}
trap 'error_handler $LINENO $?' ERR
safe_install() {
local package=$1
local pm=$2
if ! install_package "$package" "$pm" 2>&1 | tee -a "$LOG_FILE"; then
echo "Falha crítica ao instalar $package" >&2
return 1
fi
}
7. Boas Práticas e Exemplos Completos
7.1. Script de provisionamento multi-distribuição
#!/bin/bash
# Script de provisionamento universal
set -euo pipefail
detect_package_manager() {
if command -v apt &> /dev/null; then echo "apt"
elif command -v dnf &> /dev/null; then echo "dnf"
elif command -v yum &> /dev/null; then echo "yum"
else echo "unknown"; fi
}
PM=$(detect_package_manager)
[[ "$PM" == "unknown" ]] && { echo "Gerenciador não suportado"; exit 1; }
# Configurações específicas por distribuição
case $PM in
apt)
export DEBIAN_FRONTEND=noninteractive
apt update
apt install -y curl wget git vim htop
;;
dnf)
dnf install -y epel-release
dnf install -y curl wget git vim htop
;;
yum)
yum install -y epel-release
yum install -y curl wget git vim htop
;;
esac
echo "Provisionamento concluído com sucesso!"
7.2. Integração com variáveis de ambiente e argumentos
#!/bin/bash
# Uso: ./script.sh --packages "nginx,redis" --dry-run
DRY_RUN=false
PACKAGES=""
while [[ $# -gt 0 ]]; do
case $1 in
--packages) PACKAGES="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
*) echo "Argumento desconhecido: $1"; exit 1 ;;
esac
done
IFS=',' read -ra PKG_LIST <<< "$PACKAGES"
for pkg in "${PKG_LIST[@]}"; do
if $DRY_RUN; then
echo "[DRY-RUN] Instalaria: $pkg"
else
install_if_missing "$pkg" "$PM"
fi
done
7.3. Testes e validação pós-instalação
#!/bin/bash
validate_installation() {
local package=$1
local binary=$2
if command -v "$binary" &> /dev/null; then
echo "✓ $package instalado com sucesso ($binary disponível)"
return 0
else
echo "✗ $package: binário $binary não encontrado" >&2
return 1
fi
}
# Exemplo de uso
install_if_missing "nginx" "$PM"
validate_installation "nginx" "nginx"
install_if_missing "redis" "$PM"
validate_installation "redis" "redis-server"
Referências
- Documentação Oficial do APT — Guia completo do gerenciador de pacotes APT do Debian/Ubuntu
- Documentação do DNF — Manual oficial do DNF, o gerenciador de pacotes moderno do Fedora/RHEL
- YUM Documentation (Red Hat) — Guia de administração do YUM para RHEL/CentOS 7
- Advanced Bash-Scripting Guide - Package Management — Tutorial avançado de scripting bash com exemplos de gerenciamento de pacotes
- Shell Scripting for System Administration (Linux Foundation) — Curso gratuito da Linux Foundation sobre automação de tarefas administrativas
- Idempotent Scripts Best Practices — Artigo da Red Hat sobre criação de scripts idempotentes para gerenciamento de sistemas