I have a Fedora system (A) where I have installed some packages over the time. Now I want to install Fedora on another computer (B) and I want to install the same packages on it.
In Debian terms I want to accomplish something like this:
$ dpkg --get-selections > pkg_sel_host_a # on host_a $ dpkg --set-selections < pkg_sel_host_a # on host_b
But to be honest, I really want a better method to select the same packages on the new Fedora 19 system (B): I just want to install the packages from system A that were explicitly mentioned on a dnf install (or yum install) command line – and not those that were installed as dependencies!
Why? Because perhaps dependencies have changed – and I don’t want to install outdated dependencies on the new system. Plus, when I remove packages I want to remove the (possibly) then unneeded automatically installed dependencies (i.e. orphans) as well.
I’ve found dnf list installed – but it does not display if a package was explicitly selected or just installed because of a dependency.
How do I get that information on Fedora?
What is the Fedora/dnf way to replicate package selections?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Since Fedora 26, the Dnf repoquery subcommand supports has a new option for listing all user-installed packages:
$ dnf repoquery --qf '%{name}' --userinstalled
| grep -v -- '-debuginfo$'
| grep -v '^(kernel-modules|kernel|kernel-core|kernel-devel)$' > pkgs_a.lst
In contrast to other methods, it also lists all debuginfo packages. The additional grep in the above example filters them out.
To install the list on host B:
$ < pkgs_a.lst xargs dnf -y install
Dnf API
With recent Dnf versions (e.g. Fedora >= 23), the package database can be queried for user installed package names via the Dnf Python API:
$ python3 -c 'import dnf; b = dnf.Base(); b.fill_sack();
l = sorted(set(x.name for x in b.iter_userinstalled()
if not x.name.endswith("-debuginfo")
and x.name not in
["kernel-modules", "kernel", "kernel-core", "kernel-devel"] ));
print("n".join(l)) ' > pkgs_a.lst
# dnf install $(cat pkgs_a.lst) # on host_b
By default, dnf install aborts if one or more packages aren’t available anymore. Alternatively, dnf can be forced to install all remaining ones:
# dnf install --setopt=strict=0 $(cat pkgs_a.lst) # on host_b
PS: Put the above code and more into user-installed.py that also supports other distributions.
history userinstalled
On Fedora 23 and later, Dnf provides the
# dnf history userinstalled
command that lists all user installed packages. As of 2016-11, its usefulness is limited because there is no way to control its output and it prints packages fully qualified (i.e. including version information).
userinstalled Limitations
Note that the marking of packages as user-installed has some limitations on some Fedora versions, for Fedora 23-ish era systems (from around 2015-11) the following issues are relevant):
- packages installed via the GUI are not included
- packages installed via the command-not-found handler are not included
- some packages installed by default (by anaconda) are included
Repoquery
On older Fedora systems, where Dnf, the Dnf API and dnf history userinstalled aren’t available, one can use repoquery instead, e.g.:
$ repoquery --installed
--qf '%{n} | %{yumdb_info.reason} | %{yumdb_info.installed_by}' --all
| awk -F'|' ' $2 ~ /user/ && ($3 != 4294967295) { print $1 }'
| sort -u > pkgs_a.lst
The second awk condition is used to exclude packages that were installed by the installer. The installer’s user-id was apparently stored as 4294967295 – alternatively you can write something like ($3 == 0 || $3 == your-user-id).
Note that this command works on Fedora up to release 21 – but e.g. not on release 23, because the command repoquery was replaced with dnf repoquery. And dnf repoquery does not understand the %{yumdb_info.reason} tag.
Method 2
The easiest way, and it’s worked for a long time is:
yum-debug-dump => gives file. yum-debug-restore <file-from-debug-dump>
…which works much like the get/set selections dpkg command, AIUI. Also note that if you are replaying history you can use:
yum history addon-info last saved_tx => gives file yum load-tx <file-from-addon-info>
…instead of having to parse it yourself.
Method 3
Inspired by slm‘s answer I’ve come up with following yum history based solution:
Get all detailed history on all yum install transactions (i.e. no upgrades), excluding those execited as part of initial installer actions (transactions 1 and 2 on my system, attributed to user ‘System’):
$ yum history list all | awk -F'|'
'$4 ~ /Install/ && $2 !~ /System/ {print $1}'
| xargs yum history info > yum_history
Filter explicitly installed packages and cut off version prefixes.
$ < yum_history grep '[^-]<Install>' |
awk '{ print $2 }'
| sed 's/(-[0-9]+:|-[0-9]+.[0-9]|-[0-9]+-|-[0-9]+git).+(.fc1[1-7].|.noarch).*$//'
| sort > hist_pkg_list
The ugly regular expression is needed such that all kinds of version suffixes are matched.
The results look quite fine on my system.
A comparison against the repoquery ansatz (on my system):
method # packages ――――――――――――――――――――――――― repoquery 569 repoquery-2nd 216 yum history 214
(I piped the repoquery results through sort -u)
Why are there differences? Because repoquery includes all the packages from transactions 1 and 2, i.e. all packages which were installed by the Fedora installer. This explains why repoquery includes the mentioned packages xorg-x11-
drv-mga and friends.
Comparing repoquery-2nd and yum-history shows that repoquery-2nd is more accurate – it does not include some already removed packages. In addition it includes a few (2 on my system) packages from ‘yum update’-operations, it seems.
Warning
The above history-based method only lists all explicitly installed packages over the complete lifetime of the system. It does not balance out those packages which were removed in a later transaction. Thus, this method needs some manual curating of the results and should only be used on systems were repoquery is not available.
Method 4
I have an older version of Fedora (14) so my yum includes a less feature rich version of yum, but you might want to take a look at the yum history feature. I believe you can get the info you’re looking for from that command.
history list
$ sudo yum history list Loaded plugins: langpacks, presto, refresh-packagekit Adding en_US to language list ID | Login user | Date and time | Action(s) | Altered ------------------------------------------------------------------------------- 862 | System <unset> | 2013-07-12 18:00 | Install | 1 861 | System <unset> | 2013-07-09 03:11 | Install | 1 860 | System <unset> | 2013-07-01 13:40 | Install | 1 859 | System <unset> | 2013-06-29 22:07 | Install | 1 858 | System <unset> | 2013-06-25 22:33 | Install | 1 P< 857 | System <unset> | 2013-06-23 22:28 | Update | 1 >E 856 | System <unset> | 2013-06-23 21:33 | Install | 1 ...
You can go back to the very first transaction by passing a list of numbers to yum history list:
$ sudo yum history list `seq 1 10`
Loaded plugins: langpacks, presto, refresh-packagekit
Adding en_US to language list
ID | Login user | Date and time | Action(s) | Altered
-------------------------------------------------------------------------------
10 | Sam M. (local) <saml> | 2010-12-18 23:23 | Install | 2
9 | Sam M. (local) <saml> | 2010-12-18 23:15 | Install | 38
8 | Sam M. (local) <saml> | 2010-12-18 23:12 | Install | 1
7 | Sam M. (local) <saml> | 2010-12-18 23:09 | Install | 1 <
6 | Sam M. (local) <saml> | 2010-12-18 22:37 | Install | 1 >
5 | Sam M. (local) <saml> | 2010-12-18 21:57 | Install | 1
4 | System <unset> | 2010-12-18 21:21 | Install | 5
3 | System <unset> | 2010-12-18 21:18 | Install | 4
2 | System <unset> | 2010-12-18 21:10 | Install | 3
1 | System <unset> | 2010-12-18 19:14 | Install | 1189
history info
The following will show you what was installed as part of the 1st yum transaction:
$ sudo yum history info 1 | less
Loaded plugins: langpacks, presto, refresh-packagekit
Adding en_US to language list
Transaction ID : 1
Begin time : Sat Dec 18 19:14:05 2010
Begin rpmdb : 0:da39a3ee5e6b4b0d3255bfef95601890afd80709
End time : 19:42:43 2010 (1718 seconds)
End rpmdb : 1189:8c21e9e377c3ebdee936916208f74232d5d6235f
User : System <unset>
Return-Code : Success
Transaction performed with:
Packages Altered:
Dep-Install ConsoleKit-0.4.2-3.fc14.x86_64
Dep-Install ConsoleKit-libs-0.4.2-3.fc14.x86_64
Dep-Install ConsoleKit-x11-0.4.2-3.fc14.x86_64
Dep-Install GConf2-2.31.91-1.fc14.x86_64
Dep-Install GConf2-gtk-2.31.91-1.fc14.x86_64
Dep-Install ModemManager-0.4-4.git20100720.fc14.x86_64
Install NetworkManager-1:0.8.1-10.git20100831.fc14.x86_64
Dep-Install NetworkManager-glib-1:0.8.1-10.git20100831.fc14.x86_64
Install NetworkManager-gnome-1:0.8.1-10.git20100831.fc14.x86_64
Install NetworkManager-openconnect-0.8.1-1.fc14.x86_64
Notice how yum reports whether a package was explicitly installed or installed because it was needed by a dependency. You could parse this info and get your list of packages that were explicitly installed.
Method 5
dnf repoquery --qf "%{name}" --userinstalled > userinstalled.txt
Method 6
To list packages you have installed, try this one-liner:
alias yum-userinstall="yumdb search command_line install* | grep command_line = | sort | uniq | sed -r -e 's/command_line = (.*)/yum 1/g'"
Result:
# yum-userinstall
yum install bind-utils
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install lsof
yum install nano
yum install nfs-utils libnfsidmap
yum install nmap-ncat
yum install openscap-scanner
yum install open-vm-tools
PS1: it doesn’t show dependencies
PS2: it is sorted alphabetically
PS3: it doesn’t show if you have removed the package later
Method 7
What I did (forgot the details, and I’m a lazy bum, so…
Get all installed packages: rpm -qa > file
Use sed(1) to get rid of version numbers and such (keep the architecture, if required). This required a few iterations to get it right, you want to replace the last stretch of -[0-9.]-[0-9].fc23 or similar by nothing, but there are funny version “numbers” too.
After installing as normal, do a yum -y install $(< file) (or dnf, as required).
You’ll get some fallout of packages that don’t exist anymore, or changed name, or were replaced by others.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0