Make package list from installed rpms.pl

From Alteeve Wiki
Jump to navigation Jump to search

 AN!Wiki :: How To :: Make package list from installed rpms.pl

This is used for taking a RPM-based machine's installed programs and generates a directory containing all the RPMs needed to reproduce the system.

Download the perl source: make_package_list_from_installed_rpms.pl.

#!/usr/bin/perl
#
# Scraped together by Digimer;
# - Jun. 13, 2010
# - digimer@alteeve.ca

use strict;
use warnings;
use IO::Handle;

my $src_dir="/mnt/loop/Packages";
my $dst_dir="/root/Packages";
my $get_all_from_repo=0;
my $purge_dest_dir=1;

if (not -d $dst_dir)
{
	die "Destination directory: [$dst_dir] not found, exiting.\n";
}
if ((not -d $src_dir) && (not $get_all_from_repo))
{
	die "Source directory: [$src_dir] not found, exiting.\n";
}

# Purge everything from the destination directory to ensure a clean slate.
if ($purge_dest_dir)
{
	print "Purging all files from: [$dst_dir] in five seconds. Press <ctrl>+C to abort.\n";
	sleep 5;
	my $shell_call="rm -f $dst_dir/* 2>&1 |";
	my $rm_call=IO::Handle->new();
	open ($rm_call, $shell_call) or die "Failed to call: [$shell_call], error: $!\n";
	while (<$rm_call>)
	{
	        chomp;
	        my $line=$_;
		print "Output: $line\n";
	}
	$rm_call->close();
}

# Get a list of source files.
my %source;
my $get_from_yum;
if (not $get_all_from_repo)
{
	my $shell_call="ls -lah $src_dir/ 2>&1 |";
	my $ls_call=IO::Handle->new();
	open ($ls_call, $shell_call) or die "Failed to call: [$shell_call], error: $!\n";
	while (<$ls_call>)
	{
		chomp;
		my $line=$_;
		next if $line =~ /^total \d/;
		next if $line =~ /TRANS\.TBL$/;
		next if $line =~ /\d \.{1,2}$/;
		my ($file_name)=($line=~/.*\s+(.*?)$/);
		my ($name, $ver, $arch)=($file_name=~/(.*?)-(\d.*)\.(.*?)\.rpm/);
		die "bad source line: [$line]!\n" if not $name;
		$source{$name}{$arch}{file}=$file_name;
		$source{$name}{$arch}{ver}=$ver;
		if ($line =~ /OpenIPMI/)
		{
			print "File: [$source{$name}{$arch}{file}]\n\t- Name: [$name]\n\t- Arch: [$arch]\n\t- Ver: [$source{$name}{$arch}{ver}]\n\t- Raw line: [$line]";
		}
	}
}

# Source the files now.
my $shell_call="yum list installed 2>&1 |";
my $yum_call=IO::Handle->new();
open ($yum_call, $shell_call) or die "Failed to call: [$shell_call], error: $!\n";
while (<$yum_call>)
{
	chomp;
	my $line=$_;
	
	# Skip headers
	next if $line =~ /^Loaded plugins/;
	next if $line =~ /^Installed Packages/;
	
	# Parse out all but the name.
	$line=~s/\s+.*$//;
	next if not $line;
	
	# Convert the name/arch to the proper filename.
	my ($name, $arch)=$line=~/\./ ? ($line=~/(.*)\.(.*?)$/) : ($line, "noarch");
	print "Name: [$name], arch: [$arch]\n";
	if ((exists $source{$name}{$arch}{file}) && (not $get_all_from_repo))
	{
		# Pull from the source.
		my $src_file=$source{$name}{$arch}{file};
		print "Pulling from source: [$src_file]\n";
		my $cp_cmd="cp $src_dir/$src_file $dst_dir/";
		print "Calling: [$cp_cmd]...\n";
		my $shell_call="$cp_cmd 2>&1 |";
		my $cp_call=IO::Handle->new();
		open ($cp_call, $shell_call) or die "Failed to call: [$shell_call], error: $!\n";
		while (<$cp_call>)
		{
			chomp;
			print "Output: $_\n";
		}
		$cp_call->close();
	}
	else
	{
		# Have to get the file from the repo.
		print "Queueing for repo pull: [$line]\n";
		$get_from_yum.="$line ";
	}
}
$yum_call->close();
# Get any queued files.
get_file_from_repo($get_from_yum) if $get_from_yum;

exit;


# Grap all the queued files from the repository.
sub get_file_from_repo
{
	my ($files)=@_;
	
	print "Downloading from yum:\n$files\n";
	my $yd_cmd="yumdownloader --destdir $dst_dir/ $files";
	print "Calling: [$yd_cmd]...\n";
	my $shell_call="$yd_cmd 2>&1 |";
	my $yd_call=IO::Handle->new();
	open ($yd_call, $shell_call) or die "Failed to call: [$shell_call], error: $!\n";
	while (<$yd_call>)
	{
		chomp;
		print "Output: $_\n";
	}
	$yd_call->close();
	
	return;
}

 

Any questions, feedback, advice, complaints or meanderings are welcome.
Alteeve's Niche! Enterprise Support:
Alteeve Support
Community Support
© Alteeve's Niche! Inc. 1997-2024   Anvil! "Intelligent Availability®" Platform
legal stuff: All info is provided "As-Is". Do not use anything here unless you are willing and able to take responsibility for your own actions.