2

Good afternoon all! long time lurker, first time poster here.

I am trying to use a script to remove an rpm remotely (foo). There are too many hosts to efficiently do this manually.

There are multiple versions of this *.rpm installed across the environment. So hardcoding the name in will not work. My solution, before, was to have a script that scp's a "removefoo.sh" to the remote host, with the following two bits inside:

INSTALL=$(rpm -qa | grep -i foo)
rpm -e $INSTALL

And that worked... but this is not ideal as we would prefer to have one script "Do it all".

Obviously, putting that solution in this new script with will break as the script is ran from the management server, and it will attempt to remove the $INSTALL it gets from the management server, which doesn't even run this rpm...

The following did not help:

ssh -q $serverIP 'rpm -qa | grep -i foo ; rpm -e'

Anyone have a clue? I'm on RHEL 6 and 7 and everything else is fine (e.g. able to connect to hosts, etc.)

Thank you!

  • 2
    What's wrong with yum remove <packagename>? – Ignacio Vazquez-Abrams Nov 6 '17 at 19:56
  • 1
    I'm actually just starting to pick up RHEL, and my understanding was that rpm was preferred to yum (e.g. apt preference over dpkg) - foolish to overlook trying it, but I guess that's why I'm "picking up RHEL" hahaha. Anyway, it worked! I added in the y option as it is a remote deployment: ssh -q $serverIP 'yum -y remove foo' Thank you so much! – kilrainebc Nov 6 '17 at 20:08
  • Just out of curiosity - why doesn't rpm work in this instance, and would there be a method that would work for it? – kilrainebc Nov 6 '17 at 20:11
  • rpm could work, but then yum will complain that the rpmdb was modified outside of yum. – Ignacio Vazquez-Abrams Nov 6 '17 at 20:12
  • 1
    Maybe you should start using a configration management system. Ansible is a good start as it can use OpenSSH for transport. – Vikelidis Kostas Nov 6 '17 at 21:01
1

The suggestion in the comments to use yum is the right answer, but I want to address your question; Why doesn't this work?

Let's break down your command;

ssh -q $serverIP 'rpm -qa | grep -i foo ; rpm -e'

This is saying to execute rpm -qa | grep -i foo ; rpm -e on remote host $serviceIP, right? First, does it work locally? Troubleshoot in an interactive shell on a remote host before trying to orchestrate it.

Your command is actually two commands chained by the semi-colon. The first rpm -qa | grep -i foo is only looking for the presence of foo on the system. Incidentally, you could save a pipe by simply rpm -q foo. This will be measurably faster than enumerating the entire rpm database. (Unless foo is only part of the package name, in which case that should be made clear and this answer will have to change.)

Next, you are attempting to execute rpm -e. If you try this in your shell, you should see the error;

# rpm -e
rpm: no packages given for erase

You need to tell it to erase something. You already know what you want to erase foo, so include foo in your command here: rpm -e foo.

Last, it looks like what you were trying to do is only erase foo if it is installed. Instead of chaining commands with the semi-colon, make rpm -e foo conditional if rpm -q foo exits "true."

rpm -q foo && rpm -e foo

Example:

[root@laptop ~]# rpm -q nmap && rpm -e nmap
nmap-7.40-1.fc25.x86_64

Output above is from the rpm -q command. You can suppress this. rpm -q --quiet foo.

[root@laptop ~]# rpm -q nmap
package nmap is not installed

Shows the package is no longer installed after rpm -e nmap. I did not have to specify the version; only the package name.


Edit: (based on the comments below)

If foo is only part of the package name, and you want to remove everything that matches you can use xargs. This command takes the output of one command and makes it an argument of another. As you have found you cannot pipe or chain commands to rpm -e.

rpm -qa | grep -i foo | xargs rpm -e

  • Thank you for your answer Aaron. I believe I had actually tried piping it as well, and when that failed I tried ; to no avail. Foo is only part of the package name (And the package name differs from server to server...). Basically I needed a way for the machine to pull: "foo-#.#.##-X##X###X####.x86_64" from "rpm -qa | grep -i foo" and then pass it to rpm -e. As a note - I wasn't trying to conditionally remove foo if and only if it was found in the rpmdb. But thank you for pointing out the properties of && as I'm sure it'll be useful to others who may find this question. – kilrainebc Nov 13 '17 at 16:13
  • Foo is the package name, then. What you are describing is the filename. Or, part of the filename format. You only need to know the package name. If it's really foobar-3.14-159.x86_64 it's a different story. – Aaron Copley Nov 13 '17 at 18:25
  • Edited to be clear about matching partial package names and provide an example. – Aaron Copley Nov 13 '17 at 18:33
  • Aaron - thank you for your clear answers and your assistance. Ultimately, all of it informed my understanding of the system more so I just wanted to say thanks. I'm going to use xargs - and I believe that to be the most correct answer - but I obviously have more to learn. Thank you! – kilrainebc Nov 13 '17 at 18:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.