I need to replace the existing binary during rpm upgrade but I do not want to change the permission/ownership which is set already.
In my case, after the binary installation (not upgrade), ownership/permissions are set properly by rpm. But after the rpm installation, permissions/ownership of the file are modified by admin to allow another process to run this binary. Owner/group of the another process is different from this process. But when the rpm is upgraded it resets the permissions/ownership and another process is now not able to execute it.
Looking for a solution on how to retain the existing ownership/permissions but replace the binary only.
Any type of help/pointers are appreciated. Let me know if you have any questions.
Read the state of the file in %pre and restore it in %posttrans for more informations see https://fedoraproject.org/wiki/Packaging:Scriptlets#Saving_state_between_scriptlets
Related
Our company produces an rpm on red-hat Linux and there is a thought that we should redistribute as little 3rd party code as possible in our package. We are using log4j.jar and want to stop including it in our rpm, but instead have the log4j rpm installed at the client site. However, that means that my java program needs to know where the file is located so that I can import the file. Without knowing where the client installed the file, in case they installed it in a non-standard location, I cannot be sure it is on the classpath. Is there a standard way to determine that? Do rpm or yum have a command so that I can see where a specific file was installed or do I need our customer to tell me where it is so I can set the classpath value correctly? I can't just use the find command on their system to search their files. Any suggestions would be appreciated.
Thanks
I develop a software which is distributed and installed via rpm. During install, I copy some binaries to a destination directory.
When performing rpm upgrade, I'd like the old binaries not to be deleted, and that the new ones will be added as is.
Is there an rpm built-in way to do so? I'd really like to avoid scripting in order to resolve that...
EDIT:
The above binaries were listed in #files section.
If you are manually copying the files to some directory (in %post for example) then yum/rpm doesn't know anything about them and can't remove them.
If you have them listed in the %files section (i.e. copying them to the right place under buildroot during `%install) then no, I do not believe you can have rpm leave files not listed by the new package on the system after upgrading to a newer version of the package which does not contain those files.
It might be possible to play with marking them as %config files and then "modifying" them so that rpm won't remove them but it might still rename them and I don't know if this will actually work.
I wonder, if there is a way to do the following:
I have rpmA-v1 installed on the system. It has a lot of config files which user can edit for their purposes. Then, I want to install new version of rpmA, say, rpmA-v2 and before installing it I want to back up those config files, which were edited, not to edit config files one more time.
Is there any way to know which files were edited in such a situation?
If you are talking about config files related to given package, rpm already has pretty robust mechanism for this known as .rpmnew/.rpmsave.
If package is being upgraded, at the discretion of package creator/maintainer there are 2 possible actions that may be taken by rpm:
Old config is preserved intact say at /etc/myprog/config, and new one is installed right next to it as /etc/myprog/config.rpmnew. Presence of *.rpmnew file typically means that old config was NOT edited.
Old config is renamed to /etc/myprog/config.rpmsave, and new one is installed as/etc/myprog/config (replacing old one). New config may be completely fresh (vanilla) or it may incorporate settings inherited from old, .rpmsave'd version. Presence of *.rpmsave files is pretty robust sign that config files were actually edited by rpm.
Typically, after upgrading of one or more packages (or the whole system) it is recommended to search for all .rpmnew/.rpmsave files using command like
find /etc -name "*.rpmsave" -or -name "*.rpmnew"
and carefuly inspect all configs against their .rpmnew/.rpmsave versions (if they are around) to make sure that settings are correct. You can use diff -u to see text diffs or meld for graphical diff/merge.
#mvp has provided a good way to determine changed config files - provided they are marked as such.
If they aren't, you can/should verify the installed package with rpm -V packagename in order to display any changed files.
I'm currently developing my first Linux RPM package for release. During the %post hook, I want to ensure that a particular file is resident on the target system. If this file is present, I'd like the install to proceed. If this file is missing, I'd like RPM to abort the install and report an error code.
Conditional logic in the .spec file works fine, but adding "return 1" in the error case causes RPM to throw an error (and, ironically, RPM does return with an error code in that case). But what is the "right" way to tell RPM that an install has failed and to exit gracefully?
Thank you!
That particular file is part of the RPM? If not, the correct place to do this check is in the %pre section. If it is, you can use the %verify for verification. When the %post run, the package is installed already, so it cannot be "failed"
Either put the check in the %pre section, or add it to the Requires field to make rpm itself check for you.
what is the "right" way to tell RPM that an install has failed and to
exit gracefully?
Best practice would say that the RPM installation should not fail if all the listed dependencies are met.
It does sound very much like the file is a dependency, in which case it should be listed as Requires:/path/to/file.
If it's a site-specific file for which you control deployment, then the RPM should deploy its own good default, which you can specify under %files with %config(noreplace). This will ensure that any existing config is not overwritten, and the default is written as /path/to/file.rpmnew.
If you want to replace an existing config, you would use %config without the (noreplace) option, which causes the existing file to be moved aside to /path/to/file.rpmsave
I have a debian package that I built that contains a tar ball of the files, a control file, and a postinst file. Its built using dpkg-deb and it installs properly using dpkg.
The modification I would like to make is to have the installation directory of the files be determined at runtime based on an environment variable that will be set when dpkg -i is run on the deb file. I echo out the environment variable in the postinst script and I can see that its set properly.
My questions:
1) Is it possible to dynamically determine the installation directory at runtime?
2) If its possible how would I go about this? I have read about the rules file and the mypackage.install files but I don't know if either of these would allow me to accomplish this.
I could hack it by copying the files to the target location in the posinst script but I would prefer to do it the right way if possible.
Thanks in advance!
So this is what I found out about this problem over the past couple of weeks.
With prepackaged binaries you can't build a debian package with a destination directory dynamicall determined at runtime. I believe that this might be possible if installing a package that is built from source where you can set the install directory using configure. But in this case since these are embedded Ubuntu machines they don't have make so I didn't pursue such an option. I did work out a non traditional method (hack) for installing that did work. Since debian packages simply contain a tar ball relative to / simply build your package relative to a directory under /tmp. In the postinst script you can then determine where to copy the files from the archive into a permanent location.
I expected that after rebooting and the automatic deletion of the subdirectory under /tmp that dpkg might not know that the file package existed. This wasn't a problem. When I ran 'dpkg -l myapp' it showed as still installed. Updating the package using dpkg/apt-get also worked without a hitch.
What I did find is that if you attempted to remove the package using 'dpkg -r myapp' that dpkg would try and remove /tmp which wasn't good. However /tmp isn't easily removed so it never succeeded. Plus in our situation we never remove packages but instead simply upgrade them.
I eventually had to abandon the universal package due to code differences in the sources resulting in having to recompile per platform but I would have left it this way and it did work.
I tried using --instdir to change the install directory of the package and it does relocate the files but dpkg fails since the dpkg file can't be found relative to the new instdir. Using --instdir is sort of like a chroot. I also tried --admindir and --root in various combinations to see if I could use the dpkg system relative to / but install relocate the files but they didn't work. I guess rpm has a relocate option that works but not Ubuntu.
You can also write a script that runs dpkg-deb with a different environment for 6 times, generating 6 different packages. When you make a modification, you simply have to run your script, and all 6 packages gets generated and you can install them on your machines avoiding postinst hacking!
Why not install to a standard location, and simply use a postinst script to create symbolic links to the desired location? This is much cleaner, and shouldn't break anything in dpk -I.