Mình đã cài Ubuntu Server 22.04 trên hơn 20 con VPS và quy trình này là cách mình luôn làm đầu tiên — kiểm tra package integrity trước khi làm bất cứ điều gì khác. Lý do đơn giản: một lần mình bỏ qua bước này, chạy thẳng apt upgrade trên server đang còn PPA cũ từ Ubuntu 20.04, kết quả là apt bị treo hoàn toàn, phải restore từ snapshot. Mất 2 tiếng. Không vui chút nào.
Bối cảnh: Khi nào Broken Packages xảy ra và tại sao fix generic không đủ
Câu lệnh apt --fix-broken install là thứ đầu tiên Google gợi ý và nó giải quyết được khoảng 60% trường hợp đơn giản. Nhưng khi xung đột đến từ PPA — đặc biệt PPA cũ không còn được maintain — thì câu lệnh đó chỉ báo lỗi mà không làm được gì thêm. Lúc này bạn cần hiểu tại sao xung đột xảy ra trước khi nghĩ đến việc fix.
Ba tình huống mình gặp nhiều nhất:
- PPA conflict sau dist-upgrade: Upgrade Ubuntu lên version mới, PPA cũ cung cấp package version cao hơn official repo nhưng dependency không match với hệ thống mới.
- Half-installed package: Mất điện hoặc Ctrl+C giữa chừng khi đang cài, dpkg để lại trạng thái half-installed hoặc half-configured.
- Dependency hell: Hai PPA khác nhau cùng cung cấp version khác nhau của một shared library như
libsslhaylibc.
Với PPA conflict, apt thuần túy thường chỉ báo:
E: Unable to correct problems, you have held broken packages.
Không có thêm thông tin gì hữu ích. Đây là lúc aptitude vào cuộc.
Cài đặt aptitude và ppa-purge
aptitude là package manager thay thế cho apt, có khả năng phân tích dependency conflict chi tiết hơn và đề xuất nhiều phương án giải quyết thay vì chỉ báo lỗi. ppa-purge thì chuyên xử lý việc gỡ PPA và downgrade tất cả package từ PPA đó về version trong official repo — làm 2 việc cùng một lệnh.
sudo apt install aptitude
sudo apt install ppa-purge
Nếu apt install chính nó cũng bị kẹt vì broken packages, thử reset dpkg trước:
sudo dpkg --configure -a
sudo apt-get install -f
sudo apt install aptitude ppa-purge
Debug với aptitude: Tìm nguồn gốc xung đột
Xem full dependency tree và đề xuất giải quyết
Giả sử bạn thấy lỗi liên quan đến python3-apt. Thay vì dùng apt, chạy với aptitude:
sudo aptitude install python3-apt
Khác với apt, aptitude không dừng lại ở “cannot install” mà hiển thị nhiều phương án, ví dụ:
The following actions will resolve these dependencies:
Keep the following packages at their current version:
1) python3-apt [0.9.3.5ubuntu3 (now)]
Downgrade the following packages:
2) python3 [3.11.2-1 (now, ppa:deadsnakes/ppa) -> 3.10.12-1 (jammy)]
Ở đây aptitude đang gợi ý hai hướng: giữ nguyên python3-apt ở version cũ, hoặc downgrade python3 từ PPA về version official. Đây là thông tin quan trọng mà apt không cung cấp — bạn biết chính xác package nào từ PPA nào đang gây ra vấn đề.
Dùng aptitude TUI để navigate nhiều conflict
Khi hệ thống có nhiều conflict cùng lúc, aptitude TUI giúp kiểm tra từng cái một:
sudo aptitude
Trong TUI: nhấn U để update package list, u để xem upgrade candidates, aptitude sẽ highlight các conflict và cho phép chọn phương án giải quyết bằng phím e (examine solution). Nhấn q để thoát.
Hoặc dùng flag -f để aptitude tự động chọn phương án ít phá vỡ nhất:
sudo aptitude -f install
Kiểm tra package đang bị hold
Một nguyên nhân hay bị bỏ qua: package bị “hold” — tức là bị ghim version. Khi package bị hold, apt từ chối upgrade hoặc cài dependency mới cho nó, gây ra broken chain.
# Xem tất cả package đang bị hold
apt-mark showhold
# Bỏ hold nếu cần
sudo apt-mark unhold <package-name>
Xử lý xung đột PPA với ppa-purge
Xác định PPA nào đang gây xung đột
Liệt kê tất cả PPA đang active trên hệ thống:
# Xem file sources trong sources.list.d
ls /etc/apt/sources.list.d/
# Lọc chỉ PPA từ Launchpad
grep -r "^deb " /etc/apt/sources.list /etc/apt/sources.list.d/ | grep "ppa.launchpad"
Để biết package cụ thể đang được cài từ PPA nào thay vì official repo:
apt-cache policy <package-name>
Output sẽ rõ ràng như này:
python3:
Installed: 3.11.2-1~ubuntu22.04
Candidate: 3.11.2-1~ubuntu22.04
Version table:
*** 3.11.2-1~ubuntu22.04 500
500 http://ppa.launchpad.net/deadsnakes/ppa/ubuntu jammy/main amd64
3.10.12-1 500
500 http://archive.ubuntu.com/ubuntu jammy/main amd64
Thấy ngay: python3 đang dùng version từ PPA deadsnakes/ppa, không phải Ubuntu official.
Purge PPA và downgrade về official version
Khi đã biết PPA nào gây lỗi, ppa-purge làm 2 việc cùng lúc: xóa PPA khỏi sources.list.d và downgrade tất cả package từ PPA đó về version trong official repo.
sudo ppa-purge ppa:deadsnakes/ppa
Sau khi ppa-purge chạy xong:
sudo apt update
sudo apt upgrade
sudo apt --fix-broken install
Mình hay gặp trường hợp ppa-purge xong vẫn còn vài package lơ lửng chưa về đúng version. Kiểm tra bằng:
# Tìm package không đến từ official Ubuntu repo
apt list --installed 2>/dev/null | grep -v "/ubuntu " | grep -v "Listing"
Manual downgrade khi ppa-purge không đủ
Đôi khi PPA đã bị xóa khỏi Launchpad nhưng package vẫn còn trên máy. ppa-purge không xử lý được trường hợp này vì không còn remote source để compare. Phải downgrade tay:
# Xem các version có sẵn của package trong repo hiện tại
apt-cache showpkg <package-name>
# Hoặc dùng madison để xem gọn hơn
apt-cache madison <package-name>
# Downgrade về version cụ thể
sudo apt install <package-name>=<version>
Kiểm tra & Monitoring sau khi fix
Verify hệ thống sạch
# Kiểm tra dpkg không có package lỗi
sudo dpkg --audit
# Kiểm tra apt database consistency
sudo apt-get check
# Full upgrade để đảm bảo mọi thứ đồng bộ
sudo apt update && sudo apt full-upgrade
Nếu dpkg --audit không ra output → không còn broken packages. Nếu apt-get check trả về exit code 0 → apt database nhất quán. Đây là 2 check mình luôn chạy trước khi kết luận xong việc.
Script kiểm tra định kỳ
Sau khi fix, mình thêm một script check nhanh vào cron để phát hiện sớm trước khi thành vấn đề lớn:
#!/bin/bash
# /usr/local/bin/check-pkg-health.sh
echo "=== Package Health Check: $(date) ==="
echo "--- Broken/unconfigured packages ---"
sudo dpkg --audit
echo "--- Packages from non-official sources ---"
apt list --installed 2>/dev/null | grep -v "/ubuntu " | grep -v "Listing" | head -20
echo "--- Held packages ---"
apt-mark showhold
echo "--- Active PPAs ---"
ls /etc/apt/sources.list.d/ | grep -v ".save" | grep -v ".bak"
# Thêm quyền thực thi
sudo chmod +x /usr/local/bin/check-pkg-health.sh
# Chạy weekly vào sáng thứ Hai
sudo crontab -e
# Thêm dòng:
0 9 * * 1 /usr/local/bin/check-pkg-health.sh >> /var/log/pkg-health.log 2>&1
Xử lý nhanh các lỗi phổ biến
Lỗi: “dpkg was interrupted, you must manually run…”
sudo dpkg --configure -a
Lỗi: “The following packages have unmet dependencies”
sudo aptitude install <package> # aptitude sẽ đề xuất phương án cụ thể
Lỗi: apt bị lock hoàn toàn (thường do process trước bị kill)
sudo rm /var/lib/dpkg/lock-frontend
sudo rm /var/lib/apt/lists/lock
sudo dpkg --configure -a
Điều mình rút ra sau bao lần debug kiểu này: đừng thêm PPA bừa bãi. Mỗi PPA là một nguồn package nằm ngoài kiểm soát của Ubuntu, và nó có thể conflict với system package bất cứ lúc nào — đặc biệt sau dist-upgrade. Nếu cần software version mới hơn, cân nhắc dùng snap, flatpak, hoặc binary release trực tiếp từ vendor thay vì PPA. Ít nhất, document lại mỗi PPA bạn thêm vào server và lý do tại sao — future you sẽ biết ơn điều đó.

