So, at work, someone (me) might’ve decided to go ahead and apply updates to a development system regardless of the vendor’s slowness in coming up with a patch support plan. This might’ve caused some (quickly remediated) destruction.
So I’m here to discuss the difference between the yum undo command and the sadly undocumented-in-the-man-page rpm -rollback functionality.
The yum application is built on top of the functionality provided by the rpm facility. It uses its own database (yumdb) in conjunction with the rpm database (rpmdb) to track package information. Because the yumdb is separate from, but interrelated with the rpmdb, yum will complain if you modify the rpmdb without using yum (say, through the standard rpm command). You might see this message: “Warning: RPMDB altered outside of yum.” Doing this can yield lessened yum functionality since it won’t be accurately recording these package modifications. It can’t simply consult the rpmdb for the information it needs, either (that’d be silly if that was all that was stored in the yumdb, right?) since the yumdb adds information that the rpmdb does not record. The information is not essential to yum’s operation, but it does enhance the user experience and provide some nice functionality (like the yum history command). Check out http://yum.baseurl.org/wiki/YumDB for more information on what exactly is stored.
Anyway, the point is that yum keeps a record of your package transactions and allows you to undo or “rollback” these transactions. In the context of yum, a “rollback” is simply a bulk undo operation. If I instruct my machine to “yum undo 40”, it will attempt to reverse the behavior of transaction 40. It’s very important to understand what this means: As far as I can tell (I could be wrong, but I don’t think I am), the undo command will perform the inverse of each operation listed in the transaction. If transaction 40 includes operations in which package A is installed, package B is erased, and package C is installed, you can expect the undo operation when applied to transaction 40 to erase packages A and C, and reinstall package B.
In the context of yum, a “rollback” operation applied to transaction 40 would attempt to undo every transaction between the current point in time and transaction 40, so be careful! This is not in any way equivalent with the rpm –rollback option we will be discussing below.
A thought occurs; this simplistic view of “undoing” what was done in that transaction is sometimes inadequate. For example, if I had modified the configuration files which came with package A, undoing transaction 40 is not going to get me my configuration file back. It’ll simply provide me with a freshly installed package containing the default configuration file. My precious changes are still gone.
While yum does not provide a true undo function in this sense, the rpm command does. Further,/etc/yum.conf can be modified to cause yum to ensure that its actions keep the system ready to perform these rpm rollbacks (which are not equivalent with the term “rollback” in the yum context!).
The rpm –rollback function (which is surprisingly absent from the rpm man page) allows a user to roll the system back to a previous point in time. Using the rpmdb database, rpm will inspect the package behavior which has occurred on the system and it will actually uninstall those packages which have been installed, replacing the contents of those rpm packages which were modified during those installation procedures.
So for example, considering our hypothetical transaction 40 above, we cannot use the rpm command to refer to it directly, since it is a construction of the yumdb (the rpmdb doesn’t know what a transaction is in the same sense that the yumdb defines the term). The rpmdb does, however, understand time. Let’s say that transaction 40 occurred a little less than 2 hours ago. I can literally write “rpm -Uhv –rollback ‘2 hours ago’ and the rpm command will consult the rpmdb for all package actions which occurred between then and now, and it will undo them. It’ll REALLY undo them! See below for the inevitable caveats, however.
But first we need to ensure that our environment is adequately prepared. This functionality relies on a process called “repackaging” in which new rpm packages are constructed based on the files which actually exist on the system at the time the repackaging process operates. Basically, the rpm manfiest is consulted and every file which belongs to the rpm package being removed is first recompiled into a new rpm package and stored (by default) in /var/spool/repackage. That means configuration files which were modified are now stored in that package with all the modifications intact. If you need to rollback a software update which includes new versions of configuration files that overwrite what was there, you can now do that by instructing the system (as shown in the rpm command above) to uninstall the current package and reinstall the repackaged package which contains all the modified content.
Sweet, right!? Now the caveats: If you are manually inserting files on which the application in question depends or adding content in any way outside of that content which is included in the rpm package, you won’t be able to gather that up with this process. The repackaging process will only gather those files which are specified in the original rpm package manifest. If you know enough about rpms to make your own package, you may be able to modify the manifest to include new content which you’d like collected during the repackaging process, but that’s outside of the scope of this article (hopefully a future article!).
Another issue to consider is that this operation will probably cause yum to complain about the database, and I’m not sure what sort of impact it will have on the yumdb’s history and whatnot. It seems obvious that you won’t have this operation listed as a yum transaction, but that might not be a big deal if you roll back to just the previous transaction in yum and then manually remove that yum transaction ID from the history.
Anyway, by default, yum does not automatically repackage rpms before erasing or updating them. The reason for this is that the repackaged rpms can take up some serious hard disk space, so you need to make sure that you keep an eye on your system if you intend to go this route (again, looking to /var/spool/repackage). If you’re sure you have the requisite space, you can instruct yum to repackage rpms before erasing or updating them by modifying /etc/yum.conf and inserting the following line:
Once that’s done, you can modify /etc/rpm/macros (create it if it doesn’t exist, but it should) so that it includes the following line:
That will cause the rpm command to operate roughly as the yum command has now been instructed to operate. Now, when you perform yum transactions, you will note that yum spends some time repackaging rpms.
As always, it’s important to carefully evaluate your intended changes prior to their application, but this functionality can really help you out, especially if you’re knowledgeable enough to create a custom package during the repackaging process which captures even additional files not included in the original package. Being able to roll back updates with confidence is important in many administrative environments, and this is a significant step towards accomplishing that goal in a rpm-based Linux environment.
Some additional resources:
-http://dailypackage.fedorabook.com/index.php?/archives/17-Wednesday-Why-Repackaging-and-Rollbacks.html – See more at: http://www.indiangnu.org/2011/yum-rollback-and-repackage/#sthash.P04dex3w.dpuf
-http://www.linuxjournal.com/article/7034?page=0,0 (old, but good)