Understanding RPM Directory Cleanup: Why Non-Empty Delivered Directories Persist After Uninstallation


2 views

When working with RPM packages, many developers encounter an unexpected behavior: directories created during installation aren't automatically removed during uninstallation, especially when they contain files. This creates what we call "RPM leftovers" - orphaned directories that persist after package removal.

RPM's package management maintains meticulous records of all files it installs, but directories require special consideration. The key points are:

  • RPM tracks individual files explicitly in its database
  • Empty directories are only removed if explicitly marked as such in the spec file
  • Non-empty directories are never removed automatically during uninstallation

To ensure proper cleanup, you need to modify your RPM spec file. Here's a comprehensive approach:

# Example spec file directives for proper cleanup
%files
%dir /opt/internal/com
/opt/internal/com/file1
/opt/internal/com/file2

%postun
if [ $1 -eq 0 ]; then
    # Only remove directories when completely uninstalling (not upgrading)
    rm -rf /opt/internal/com
fi

For more complex scenarios, consider these approaches:

# Method 1: Using %ghost for runtime-created files
%files
%dir /opt/internal/com
%ghost /opt/internal/com/temp/*

# Method 2: Explicit cleanup script
%posttrans
if [ "$1" -eq 0 ]; then
    find /opt/internal/com -type d -empty -delete
fi

# Method 3: Using RPM macros
%define _unpackaged_files_terminate_build 0

Based on extensive RPM packaging experience, I recommend:

  1. Always declare directories with %dir in your %files section
  2. Use %postun scripts for complex cleanup scenarios
  3. Consider runtime directory creation during application execution rather than installation
  4. Document your cleanup strategy in package specifications

When troubleshooting, these commands prove invaluable:

# Verify file ownership
rpm -qlv your-package-name

# Check what would be removed
rpm -e --test your-package-name

# Examine the RPM database
rpm -q --filesbypkg your-package-name

When dealing with RPM package management, many developers encounter a puzzling situation: directories created during installation aren't automatically removed during uninstallation, especially when they contain files. This behavior often leaves behind "garbage" in the filesystem, contrary to what one might expect from a package manager.

The root cause lies in how RPM handles directory ownership. While RPM tracks all files installed by the package, directories are treated differently. RPM will only remove empty directories during uninstallation by default. This is actually a safety feature to prevent accidental data loss.

The most straightforward solution is ensuring your %files section explicitly lists all directories you want RPM to manage:

%files
/opt/internal/com
/opt/internal/com/subdir1
/opt/internal/com/subdir2

However, this only works if the directories are empty during uninstall.

For non-empty directories, you need to handle cleanup in the %postun script:

%postun
if [ $1 -eq 0 ]; then
    rm -rf /opt/internal/com
fi

The $1 -eq 0 check ensures cleanup only happens during complete removal (not upgrades).

Another elegant solution is to use directory marker files:

%install
mkdir -p %{buildroot}/opt/internal/com
touch %{buildroot}/opt/internal/com/.rpmkeep

%files
/opt/internal/com/.rpmkeep

This makes RPM treat the directory as "owned" and will remove it during uninstall.

When implementing these solutions:

  • Always test uninstall scenarios in a VM first
  • Consider adding safety checks for user-created files
  • Document your cleanup behavior in the SPEC file
  • Use rpm -ql to verify what files RPM tracks

If directories still aren't being removed:

rpm -q --qf "[%-16{FILENAMES} %-9{FILEFLAGS:fflags}\n]" package-name | grep ^d

This shows all directories the package owns and their flags.