I created a new script to install a few local packages on CentOS 7 without internet. I want script exits upon any error

set -e
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
rpm --import ./RPM-GPG-KEY-mysql
rpm -ivh ./epel-release-7-11.noarch.rpm
rpm -ivh ./okay-release-1-1.noarch.rpm
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-OKAY

The problem is that when a package is already installed, rpm will create issue an error code.

package epel-release-7-11.noarch is already installed
echo $?

This causes the script exits.

Is these any way to fix it without using if cases?

Note: I just want to avoid exit code 1 upon already installed packages. I do not want to use --force which is aggressive upon conflict. I also do not want to use ||true or removing set -e.

  • 1
    tbh, your question is bascially "How do i catch that error, but i dont want to catch it?" The easiest method would be to just do || true or check if the package is installed before you install with rpm -i --test ... && rpm -i ... Why don't you want to use || or set -e or if cases in the first place?
    – Malik
    Commented Aug 31, 2022 at 9:15

2 Answers 2


Use dnf: dnf localinstall file.rpm


Slight necro-bump... but I had a similar requirement when trying to incorporate the installation of multiple packages (ffmpeg and its dependencies) via an ansible playbook using rpm, and this post is one of the few places I ended up when looking for an answer, so I thought I'd add my alternative solution here too in case it helps someone else.

This fitted my requirements. ymmv:

rpm --replacepkgs -i package.rpm

This has the benefit of:

  1. Ensuring that the packages get installed if they aren't already.
  2. Not returning a "non-zero" exit code if any of the packages are already installed, avoiding my ansible playbook (or a script that exits on errors) from exiting, but allowing for other types of errors to return "non-zero" and be handled.
  3. Not requiring the installation of "dnf" if it isn't already installed (as used by the accepted answer).

But it has the downside of not being idempotent (it will "change" things even though they don't need to be changed), and using cycles to perform a task that isn't necessary.

For me, in my particular situation, this was an acceptable trade-off, as I needed to install a bunch of packages, some of which might already be installed, but the packages were are quite small and it didn't take long to install or "re-install" them. And I can key off the existence of the ffmpeg binary to decide whether to run the rpm command or not, meaning it shouldn't really run unnecessarily.


  • Try to install "normally". rpm reports packages "already installed", ffmpeg package doesn't install, exit code is "16" (equal to the number of "errors" encountered, I believe. i.e. the number of packages "already installed"):
[root@app ffmpeg-rpms]# rpm -i *.rpm ; echo $?
        package libogg-1.1.3-1.2.i386 is already installed
        (... snip - multiple packages listed here as "already installed" ...)
        package faad2-libs-2.6.1-5.el5.i386 is already installed

[root@app ffmpeg-rpms]# which ffmpeg
/usr/bin/which: no ffmpeg in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin)
  • Try again with "--replacepkgs" - ffmpeg package installs, and exit code is "0":
[root@app ffmpeg-rpms]# rpm --replacepkgs -i *.rpm ; echo $?

[root@app ffmpeg-rpms]# which ffmpeg

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .