45

Is there a way to download all dependencies with yumdownloader, even if they are already installed?

I'm trying to create a local repo and only want to include the packages we need.

Luke
  • 931

8 Answers8

36

You can use repotrack instead like this:

repotrack -a x86_64 -p /repos/Packages [packages]

Unfortunately there is a bug with the -a flag (arch). It will download i686 and x86_64.

Here's how to fix it:

if opts.arch:
    #archlist = []
    #archlist.extend(rpmUtils.arch.getArchList(opts.arch))
    archlist = opts.arch.split(',') # Change to this
else:
    archlist = rpmUtils.arch.getArchList()

You can use repoquery to get a list of group packages:

repoquery --qf=%{name} -g --list --grouppkgs=all [groups]

Which you can feed into repotrack:

repoquery --qf=%{name} -g --list --grouppkgs=all [groups] | xargs repotrack -a x86_64 -p /repos/Packages
Luke
  • 931
  • Updated to use repotrack instead. repoquery's --requires --resolve option doesn't work recursively for deps. – Luke Oct 13 '12 at 01:32
  • add the --recursive option to the repoquery command to get it work recursively. – ZaSter May 07 '13 at 22:40
  • Fixing repotrack the way suggested above did not work for me: no package was downloaded for x86_64 arch. Anyway +1 for a good tip: with repotrack one could download both i386 and x86_64 and filter out unnecessary part. – Alexander Vasiljev Jun 01 '14 at 07:51
  • @Luke how to use fix part... means where to execute if condition mentioned... and what if i need to check for only certain package in repoquery command. – AVJ Sep 14 '15 at 08:20
  • How do you invert this process and install the leaf package using the local dependencies? – bias Oct 16 '15 at 16:39
  • 2
    I wouldn't recommend to change the source code. If really, this is a bug, it should be filed into upstream yum-utils project. The reason why it downloads more packages than expected is because the function rpmUtils.arch.getArchList() returns all compatible architectures for the given one. It includes for example the noarch architecture which may be needed by x86_64 packages. You can check the source: http://yum.baseurl.org/gitweb?p=yum.git;a=blob;f=rpmUtils/arch.py;h=d63ec2545d13efe0883ca0a84ccf410ebc8d4f3b;hb=HEAD#l213 – Samuel Phan Aug 16 '16 at 16:13
  • How do we use the command? I tried putting the name of the package I'm downloading in place of name but it just says Error: no packages specified to parse. – Mike S Nov 22 '16 at 18:10
  • With the opts.arch fix the args should include -a x86_64,noarch otherwise noarch packages won't be included in the download list – bain Jul 24 '17 at 16:38
  • Using repoquery --grouppkgs=all will list every possible dependency (mandatory, optional, default) - note that these are not overlapping sets. Use --grouppkgs=mandatory for a minimal list. – bain Jul 25 '17 at 14:46
24

For everyone's information, yumdownloader does not do the job. For anyone with some experience in package management with `yum, it is natural to expect that the following command-line would recursively download a package RPM and all its dependencies:

yumdownloader --resolve <package>

But it does not. May be it prints first-level dependencies or those that are not already installed. I am not sure.

Here is one method that works on CentOS 6.5. Follow the steps to install the downloadonly plugin for yum as given by Red Hat. Basically, on CentOS 6.x, do:

$ sudo yum install yum-plugin-downloadonly.noarch

Then make use of the plugin in combination with the --installroot switch of yum. This prevents yum from resolving and then skipping dependencies that are already installed on the system.

sudo yum install \
  --installroot=</path/to/tmp_dir> \
  --downloadonly --downloaddir <rpm_dir> <package>

You would downloaded RPMs of the package, <package> and all its dependencies in the directory, <rpm_dir>. Example, with Git:

$ mkdir root rpms
$ sudo yum install --installroot=/home/roy/root \
  --downloadonly --downloaddir rpms/ git
Shrout1
  • 451
pdp
  • 717
8

Also try

repoquery -R --resolve --recursive <name> | xargs -r yumdownloader

e.g.:

repoquery -R --resolve --recursive firefox | xargs -r yumdownloader

Source: https://www.thegeekdiary.com/downloading-rpm-packages-with-dependencies-yumdownloader-vs-yum-downloadonly-vs-repoquery/

can.
  • 181
  • This one ended up being to only one that worked for me. repotrack kept finding packages that weren't available when I tried getting wine. Thanks! – Dan Jul 21 '20 at 18:44
  • This worked for me on Centos 8, but I had to do the following (for docker-ce): repoquery --required --resolve --recursive docker-ce | xargs -r yumdownloader . As @Dan stated nothing else worked for me once I had Docker-CE already installed on the machine I was trying to get the dependancies from. – james-see Mar 01 '21 at 02:52
  • Note: I don't believe this downloads the actual top-level package (e.g., firefox for this example), so you'll need another command for that. – sg_man May 27 '21 at 15:34
4

If you're from the future (Fedora 23+), where yum is getting replaced with dnf, you might find this bash script useful.

rpmDownloader:

#!/bin/sh
set -xev
rm -fr packages
#dnf download $1 --destdir packages
export PATH=.:$PATH
echo $PWD
DEPS=$(rpmResolver $1)
dnf download $DEPS --destdir packages
rm -fr ${1}-dependencies
mv packages ${1}-dependencies

rpmResolver:

#!/bin/sh
goal=$1
deps=$(rpm -q --qf '[%{REQUIRENAME}\n]'  $goal | egrep -v '^(rpmlib|rtld|config|/)')
goals=
while true; do
  subs=$(rpm -q --qf '%{NAME}\n' --whatprovides $deps | sort -u | tr '\n' ' ')
  if [ ."$subs" = ."$goals" ]; then
    echo -n "$goals "
    exit 0
  fi
  goals=$(echo $goals $subs | tr ' ' '\n' | sort -u | tr '\n' ' ')
  for sub in $subs; do
    subdeps=$(rpm -q --qf '[%{REQUIRENAME}\n]' $sub | egrep -v '^(rpmlib|rtld|config|/)')
    deps=$(echo $deps $subdeps | sort -u)
  done
done
klutt
  • 544
2

I found that in practice building a repo like this difficult to maintain. We built this repo because:

  • We wanted to pull packages from a local source for multiple servers.
  • Only allow trusted packages to be installed.

The issues we can across were:

  • Keeping packages up to date. Dependencies change. Some are added, others are removed.
  • Adding new packages that we wanted to install.
  • The above challenges lengthened the process of pushing critical updates.

In the end the better solution to our problem was to proxy the official repos and cache the packages we used. This works out well because:

  • Only packages we actually use are stored locally.
  • Old packages automatically expire.
  • When a package is first used it pulls from the official repo, but subsequent requests come from cache.
  • Trusting the official repo(s) was sufficient for trust. Our proxy mirror only pulls packages from trusted sources.

We used Nginx and the built-in proxy support.

Luke
  • 931
  • nginx proxy sounds like a great idea. Better long term support and picks up more packages. Would be helpful if you added abit more details, maybe a how to link or something – oden Mar 28 '17 at 11:30
1

I realize the thread is old, but in case anyone stumbles across this, you can use yum to accomplish the desired behavior.

First instally the downloadonly plugin(instructions for RHEL): (RHEL5)

$ yum install yum-downloadonly

(RHEL6)

$ yum install yum-plugin-downloadonly

Next run the command as follows:

$ yum install --downloadonly --downloaddir=/some/arbitrary/path [package]

If you ignore the --downloaddir yum will automatically download to /var/cache/yum

So unless you need to use yumdownloader specifically I think this would be the simplest way to accomplish the goal.

0

Building on Luke's answer and the comments...

As of this writing repotrack will match all of the following architectures when x86_64 is specified: x86_64, athlon, i686, i586, i486, i386, and noarch.

For my purposes I am only interested in x86_64 and noarch packages, and I know that my distribution doesn't have any athlon packages.

The following command gets a list of package URLs, filters out i?86 architectures, and prints out the names of the packages as they are downloaded:

repotrack --arch=x86_64 --urls gs1000-server \
    | sed '/\.i[3-6]86\.rpm$/d' \
    | xargs -I {} sh -c 'curl -s -O {}; echo {} | rev | cut -d '/' -f 1 | rev'

Note that repotrack does not warn you if it can't find a package that satisfies a dependency in your enabled repos. It silently skips it.

0

Yum's yumdownloader(1) refers installed packages information in the RPM database on the running environment as you know. It's very annoying.

I have a workaround that create .rpmmacro file to refer an empty RPM database.

$ mkdir home.dummy
$ echo %_dbpath $PWD/home.dummy/rpmdb >home.dummy/.rpmmacros
$ HOME=$PWD/home.dummy yumdownloader ...
$ rm -r home.dummy

DNF's yumdownloader(1) (is a symlink for dnf-utils) has no problem.

fumiyas
  • 101