Last active
September 3, 2024 21:18
-
-
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 =)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Table of Contents | İçindekiler
English
Türkçe
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 thepacman
database is lost.Features
.files
from the Arch Linux Archive for a specified date and compares them with existing files.core
,extra
, andcommunity
repositories by default.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:
Installation and Usage
Download and Make the Script Executable
First, download the script and make it executable:
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:Manual Date Entry
The script is configured to download
.files
for a specified date. You need to manually set the correct date by updating theDATE
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:Quiet Mode: To output only the package names, use the
-q
option:Match Threshold: To set the required percentage for file matches, use the
-t
option:Notes
.files
from the Arch Linux Archive must be correct. If an incorrect date is chosen, the system's packages may not be accurately identified.Example Usage
To identify the packages installed from the
core
,extra
, andcommunity
repositories:To run the script in quiet mode and only get the package names:
To set the match threshold to 60%:
License
This script is licensed under the WTFPL (Do What The Fuck You Want To Public License). For more information:
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
.files
dosyalarını Arch Linux Arşivinden indirir ve mevcut dosyalarla karşılaştırır.core
,extra
, vecommunity
depolarını varsayılan olarak tarar.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:
Kurulum ve Kullanim
Scriptin Indirimi ve Calistirilmasi
Öncelikle scripti indirin ve çalıştırılabilir hale getirin:
Scriptin Root Yetkileriyle Calistirilmasi
Script, sistemdeki
pacman
veri tabanlarına erişim gerektirdiği içinroot
yetkileriyle çalıştırılmalıdır: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:Sessiz Mod: Yalnızca paket isimlerini çıktı olarak almak için
-q
seçeneğini kullanabilirsiniz:Eşleşme Eşiği: Eşleşen dosyalar için gerekli yüzdeyi ayarlamak için
-t
seçeneğini kullanabilirsiniz:Notlar
.files
dosyalarını indirirken belirtilen tarihin doğru olması gerekmektedir. Yanlış bir tarih seçilirse, sistemdeki paketlerin doğru tespiti yapılamaz.Ornek Kullanim
Sistemde yüklü olan ve
core
,extra
,community
depolarındaki paketleri tespit etmek için:Sessiz modda çalıştırmak ve yalnızca paket isimlerini almak için:
Eşleşme eşiğini %60 olarak ayarlamak için:
Lisans
Bu script wtfpl Lisansı ile
lisanslanmıştır. Daha fazla bilgi için: