Skip to content

Instantly share code, notes, and snippets.

@yuceltoluyag
Last active September 3, 2024 21:18
Show Gist options
  • Save yuceltoluyag/b02924ee284888e8e346b819d2d57761 to your computer and use it in GitHub Desktop.
Save yuceltoluyag/b02924ee284888e8e346b819d2d57761 to your computer and use it in GitHub Desktop.
A package detection script to help rebuild the local database. Deleted /var/lib/pacman =)
#!/bin/bash
set -euo pipefail
#------------------------------------------------------------------------------#
# Configuration #
#------------------------------------------------------------------------------#
# Default values for command-line arguments.
REPOS=(core extra community)
DATE="2024/09/02/"
ROOT="/"
SYNC_DB_DIR="/var/lib/pacman/sync/"
MATCH_THRESHOLD=50
QUIET=false
VERBOSE=true
#------------------------------------------------------------------------------#
# Root Kullanıcı Kontrolü #
#------------------------------------------------------------------------------#
if [[ $EUID -ne 0 ]]; then
printf "Error: This script must be run as root. Please use 'sudo' or log in as root.\n" >&2
exit 1
fi
#------------------------------------------------------------------------------#
# Dependency Check #
#------------------------------------------------------------------------------#
missing_deps=()
for cmd in bc bsdtar wget; do
if ! command -v "$cmd" &> /dev/null; then
missing_deps+=("$cmd")
fi
done
if [[ ${#missing_deps[@]} -ne 0 ]]; then
printf "Eksik bağımlılıklar bulunuyor: %s\n" "${missing_deps[*]}"
# Eksik paketleri yükleme
printf "Eksik paketler yükleniyor...\n"
if ! pacman -Sy --noconfirm --overwrite "*" "${missing_deps[@]}"; then
printf "Hata: Eksik bağımlılıkları yükleyemedim. Lütfen manuel olarak yükleyin.\n" >&2
exit 1
fi
printf "Eksik bağımlılıklar başarıyla yüklendi.\n"
fi
#------------------------------------------------------------------------------#
# Functions #
#------------------------------------------------------------------------------#
function check_files_db()
{
local files_db=$1
local entry
local pkg
local pkgname
bsdtar -tf "$files_db" | while read entry
do
if [[ $entry =~ /files$ ]]
then
pkg=${entry%/*}
pkgname=${pkg%-*-*}
# Invoke bsdtar in a subshell so that we can update a path counter outside
# of the loop.
local match=0
local number=0
local path
local pct
while read path
do
# Skip directories.
if [[ $path =~ /$ ]]
then
continue
fi
((number+=1))
if [[ -e ${ROOT%/}/$path ]]
then
((match+=1))
fi
done < <(bsdtar -Oxf "$files_db" "$entry")
if [[ $match -gt 0 ]]
then
pct=$(bc -l <<< "scale=0; 100 * $match / $number")
if [[ $pct -gt $MATCH_THRESHOLD ]]
then
if $QUIET
then
printf "%s\n" "$pkgname"
else
printf "%s %s%%\n" "$pkg" "$pct"
fi
fi
fi
fi
done
}
# Usage: get_files_db <repo> [<yyyy/mm/dd>]
function get_files_db()
{
local repo=$1
local date=${2:-$DATE}
local arch=$(uname -m)
local file_path="${repo}.files"
local url="https://archive.archlinux.org/repos/$date/$repo/os/$arch/$file_path"
# Eğer dosya mevcutsa ve güncelse indirmeyi atla
if [[ -f "$file_path" ]]; then
local file_date
file_date=$(date -r "$file_path" +"%Y/%m/%d")
if [[ "$file_date" == "${date%/}" ]]; then
if $VERBOSE; then
printf "Skipping download: %s is already up-to-date.\n" "$file_path"
fi
return 0
fi
fi
# Geçici dosya ismi
local temp_file=$(mktemp /tmp/${repo}.files.XXXXXX)
if $VERBOSE; then
printf "Downloading %s files database for %s on %s\n" "$repo" "$arch" "$date"
fi
# Beklenen dosya boyutunu HTTP başlıklarından al (mevcutsa)
local expected_size
expected_size=$(wget --spider "$url" 2>&1 | grep -i "Length:" | awk '{print $2}' || echo "")
# Dosyayı indir
if ! wget -O "$temp_file" "$url"; then
printf "Error: Failed to download %s files database for %s on %s\n" "$repo" "$arch" "$date" >&2
rm -f "$temp_file"
return 1
fi
# Beklenen dosya boyutunu karşılaştır (eğer biliniyorsa)
if [[ -n "$expected_size" ]]; then
local actual_size
actual_size=$(stat -c%s "$temp_file")
if [[ "$actual_size" -ne "$expected_size" ]]; then
printf "Warning: Downloaded file size does not match expected size. The download may be corrupted.\n" >&2
fi
fi
# Geçici dosyayı gerçek dosya ismiyle değiştir
mv "$temp_file" "$file_path"
}
function display_help()
{
cat <<HELP
ABOUT
This is a tool to help recover the local pacman database. It will check
installed files against paths in the pacman file databases to estimate which
package are probably installed on the system. The matches are based entirely on
matching file paths.
For each package, the percent of matching files is calculated. If it meets the
threshold, the package is printed to stdout.
The list of matching packages is only a starting point for
recovering the local database. Some packages include the same paths so the user
will have to determine which of the matches, if any, are likely to be installed
on the system. Also note that no information about the install reason can be
determined by matching paths. It is up to the user to figure out which packages
were installed explicitly and which were installed as dependencies.
Also note that if the installed version of a package does not match the version
in the file database, then all paths that contain the version number
(e.g. /usr/lib/foo-xx.xx/...) will fail to match. It is therefore important to
determine which file database matches the installed files.
Local file databases in the sync directory (/var/lib/pacman/sync by default)
will be consulted first if they exist as they are likely to correspond to the
installed version if everything was synchronized together (pacman -Syu; pacman
-Fy). This can be disabled by passing an empty path to the "-s" option.
If the local file databases do not exist, or the check is disabled, an attempt
will be made to download the file database from the Arch Linux Archive
(https://archive.archlinux.org/repos/). A date may be given in the format
yyyy/mm/dd to select a specific date, otherwise the current date will be used.
If you know the date of your last system upgrade (even approximately), pass it
with the "-d" option.
USAGE
${0} [options] [repo repo ...]
If no repos are given, the following will be checked: ${REPOS[@]}
OPTIONS
-d yyyy/mm/dd
Set the date for retrieving databases from the Arch Linux Archive.
Default: $DATE
Example: -d 2024/09/02
-r /path/to/root
The system root in which to match packages.
Default: "/".
Example: -r /mnt/chroot
-s /path/to/sync_db/dir
The path to the pacman sync database directory to query local file
databases. These are normally downloaded with "pacman -Fy". See the notes
above about matching database package versions to installed versions. To
disable local checks, set this to an empty string.
Default: /var/lib/pacman/sync
-t <percent>
The percent of files per package that must exist on the local system for the
package to match.
Default: 50
-q
Only print package names. This can be used to create an install list that
can be piped to pacman. E.g.
${0} -q | pacman -S -
-h
Display this help message.
HELP
exit "$1"
}
#------------------------------------------------------------------------------#
# Main #
#------------------------------------------------------------------------------#
while getopts 'hd:r:s:t:q' flag
do
case "$flag" in
d) DATE=$OPTARG ;;
r) ROOT=$OPTARG ;;
s) SYNC_DB_DIR=$OPTARG ;;
t) MATCH_THRESHOLD=$OPTARG ;;
q) QUIET=true ;;
h) display_help 0 ;;
*) display_help 1 ;;
esac
done
shift $((OPTIND - 1))
if [[ $# -gt 0 ]]
then
REPOS=("$@")
fi
# Create the sync database directory if it doesn't exist
mkdir -p "$SYNC_DB_DIR"
# Cleanup temporary files on exit or interrupt
trap 'rm -f ${REPOS[@]/%/.files}' EXIT INT TERM
for repo in "${REPOS[@]}"
do
files_db=
if [[ -n $SYNC_DB_DIR ]]
then
# Check for local file databases first.
files_db=${SYNC_DB_DIR%/}/${repo}.files
fi
if [[ -z $files_db || ! -e $files_db ]]
then
get_files_db "$repo" "$DATE"
files_db=${repo}.files
fi
if $QUIET
then
check_files_db "$files_db"
else
date -r "$files_db" +"$files_db %F %R %Z"
echo '--------------------'
check_files_db "$files_db"
echo ''
fi
done
@yuceltoluyag
Copy link
Author

yuceltoluyag commented Sep 3, 2024

Table of Contents | İçindekiler

English

  1. About
  2. Features
  3. Requirements
  4. Installation and Usage
  5. Notes
  6. Example Usage
  7. License

Türkçe

  1. Hakkında
  2. Özellikler
  3. Gereksinimler
  4. Kurulum ve Kullanım
  5. Notlar
  6. Örnek Kullanım
  7. Lisans

Pacman Backup & Recovery Script

About

This script is designed to identify the packages installed on your Arch Linux system by comparing them with pacman file databases. It helps you recreate the list of installed packages on your system if the pacman database is lost.

Features

  • Downloads .files from the Arch Linux Archive for a specified date and compares them with existing files.
  • Scans the core, extra, and community repositories by default.
  • Reports matched packages and the percentage of matches.
  • Provides information on packages that are not installed or partially matched.
  • Cleans up downloaded temporary files.

Requirements

The following commands must be installed on your system for the script to work:

  • bc
  • bsdtar
  • wget

You can check if these commands are installed on your system with:

command -v bc bsdtar wget

If any of these commands are missing, you can install the necessary package using:

sudo pacman -S bc bsdtar wget

Installation and Usage

Download and Make the Script Executable

First, download the script and make it executable:

chmod +x pacbac.sh

Run the Script with Root Privileges

The script needs to be run with root privileges as it requires access to pacman databases on your system:

sudo ./pacbac.sh

Manual Date Entry

The script is configured to download .files for a specified date. You need to manually set the correct date by updating the DATE variable. For example:

DATE="2024/09/02/"

Running Options

You can run the script in different modes:

  • Help Message: Use the -h option to learn how to use the script:

    ./pacbac.sh -h
  • Quiet Mode: To output only the package names, use the -q option:

    sudo ./pacbac.sh -q
  • Match Threshold: To set the required percentage for file matches, use the -t option:

    sudo ./pacbac.sh -t 75

Notes

  • The date specified for downloading .files from the Arch Linux Archive must be correct. If an incorrect date is chosen, the system's packages may not be accurately identified.
  • The script automatically cleans up downloaded temporary files at the end of its run.

Example Usage

To identify the packages installed from the core, extra, and community repositories:

sudo ./pacbac.sh

To run the script in quiet mode and only get the package names:

sudo ./pacbac.sh -q

To set the match threshold to 60%:

sudo ./pacbac.sh -t 60

License

This script is licensed under the WTFPL (Do What The Fuck You Want To Public License). For more information:

             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
                    Version 2, December 2004

 Copyright (C) 2004 Sam Hocevar <[email protected]>

 Everyone is permitted to copy and distribute verbatim or modified
 copies of this license document, and changing it is allowed as long
 as the name is changed.

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. You just DO WHAT THE FUCK YOU WANT TO.

Türkçe

Pacman Backup & Recovery Script

Hakkinda

Bu script, Arch Linux sisteminde yüklü olan paketleri pacman dosya veritabanları ile karşılaştırarak, sistemde hangi paketlerin yüklü olduğunu tespit etmeye yarar. Bu, pacman veritabanının kaybolması durumunda yerel sistemde yüklü paketleri yeniden oluşturmanıza yardımcı olabilir.

Ozellikler

  • Belirli bir tarihteki .files dosyalarını Arch Linux Arşivinden indirir ve mevcut dosyalarla karşılaştırır.
  • core, extra, ve community depolarını varsayılan olarak tarar.
  • Eşleşen paketleri ve eşleşme yüzdesini raporlar.
  • Yüklü olmayan veya kısmen eşleşen paketler hakkında bilgi verir.
  • İndirilen geçici dosyaları temizler.

Gereksinimler

Scriptin çalışması için aşağıdaki komutların sistemde yüklü olması gerekmektedir:

  • bc
  • bsdtar
  • wget

Bu komutların sisteminizde kurulu olup olmadığını kontrol edebilirsiniz:

command -v bc bsdtar wget

Eğer bu komutlardan biri eksikse, ilgili paketi yüklemek için şu komutu kullanabilirsiniz:

sudo pacman -S bc bsdtar wget

Kurulum ve Kullanim

Scriptin Indirimi ve Calistirilmasi

Öncelikle scripti indirin ve çalıştırılabilir hale getirin:

chmod +x pacbac.sh

Scriptin Root Yetkileriyle Calistirilmasi

Script, sistemdeki pacman veri tabanlarına erişim gerektirdiği için root yetkileriyle çalıştırılmalıdır:

sudo ./pacbac.sh

Manuel Tarih Girisi

Script, belirli bir tarihteki .files dosyalarını indirmek üzere yapılandırılmıştır. DATE değişkenini güncelleyerek manuel olarak uygun bir tarihi belirlemeniz gerekir. Örneğin:

DATE="2024/09/02/"

Calistirma Secenekleri

Scripti farklı modlarda çalıştırabilirsiniz:

  • Yardım Mesajı: Scriptin nasıl kullanılacağını öğrenmek için -h seçeneğini kullanın:

    ./pacbac.sh -h
  • Sessiz Mod: Yalnızca paket isimlerini çıktı olarak almak için -q seçeneğini kullanabilirsiniz:

    sudo ./pacbac.sh -q
  • Eşleşme Eşiği: Eşleşen dosyalar için gerekli yüzdeyi ayarlamak için -t seçeneğini kullanabilirsiniz:

    sudo ./pacbac.sh -t 75

Notlar

  • Script, Arch Linux Arşivinden .files dosyalarını indirirken belirtilen tarihin doğru olması gerekmektedir. Yanlış bir tarih seçilirse, sistemdeki paketlerin doğru tespiti yapılamaz.
  • Scriptin sonunda indirilen geçici dosyalar otomatik olarak temizlenir.

Ornek Kullanim

Sistemde yüklü olan ve core, extra, community depolarındaki paketleri tespit etmek için:

sudo ./pacbac.sh

Sessiz modda çalıştırmak ve yalnızca paket isimlerini almak için:

sudo ./pacbac.sh -q

Eşleşme eşiğini %60 olarak ayarlamak için:

sudo ./pacbac.sh -t 60

Lisans

Bu script wtfpl Lisansı ile

lisanslanmıştır. Daha fazla bilgi için:

             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
                    Version 2, December 2004

 Copyright (C) 2004 Sam Hocevar <[email protected]>

 Everyone is permitted to copy and distribute verbatim or modified
 copies of this license document, and changing it is allowed as long
 as the name is changed.

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. You just DO WHAT THE FUCK YOU WANT TO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment