Automating Debian Package Cleanup using a Python Script

If you’re using Debian as your operating system, you may have encountered the need to manage packages using the 'dpkg' command. Specifically, packages with the 'rc' (remove and configuration files) status can linger on your system, taking up space. Manually removing these packages can be time-consuming. In this blog post, I introduce a Python script that I developed to automate and simplify this process.

Background

In Debian, packages with the 'rc' status may occur when they have been previously removed but still leave configuration files on the system. To identify and remove such packages, the typical command used is:

dpkg -l | grep ^rc | awk {'print $2'} | xargs dpkg -P

This command filters out all packages with the 'rc' status from the list of installed packages and then removes them entirely.

The Python Script

The Python script I developed streamlines this process and provides some additional features. Here are the key functions of the script:

1. Lists packages with the „rc“ status

By calling the script without arguments or with the -l argument, you can display a list of packages with the 'rc' status:

./purgerc -l

The script shows all relevant packages that can be purged.

2. Removes packages with the „rc“ status

By calling the script with the -f argument, all packages with the 'rc' status are removed:

./purgerc -f

The script automatically executes the command

dpkg -l | grep ^rc | awk {'print $2'} | xargs dpkg -P

and removes the corresponding packages.

3. Summary of removed packages

After removal, the script provides an overview of the removed packages:

Packages removed successfully: 
package1
package2
...

4. Help message

By calling the script with the -h or -? argument, you receive a help message:

./purgerc -h

Usage and Security

To run the script, ensure that you have the necessary permissions to remove packages. This is typically achieved by using 'sudo'.

Please note that using 'shell=True' can pose certain security risks. In this case, since user input is not directly inserted into the command, it should be acceptable. If you still have concerns, consider alternative methods such as using 'subprocess.Popen' or breaking the command into separate calls.

With this Python script, the cleanup of Debian packages with the 'rc' status becomes more straightforward and user-friendly. It provides a structured way to view, remove packages, and receive a summary of the actions taken. Say goodbye to complex commands and automate this process with my helpful script.

The Script „purgerc“

#!/usr/bin/env python3
import subprocess
import sys
def list_rc_packages():
    try:
        # Run dpkg command to list packages with status "rc"
        result = subprocess.run(['dpkg', '-l'], capture_output=True, text=True, check=True)
        lines = result.stdout.split('\n')
        rc_packages = [line.split()[1] for line in lines if line.startswith('rc')]
        
        if rc_packages:
            print("These packages can be purged:")
            print('\n'.join(rc_packages))
        else:
            print("No packages available to be purged.")
    except subprocess.CalledProcessError as e:
        print(f"Error: {e}")
        sys.exit(1)
def remove_rc_packages():
    try:
        # Run dpkg command to list packages with status "rc" and remove them
        result = subprocess.run('dpkg -l | grep "^rc" | awk \'{print $2}\' | xargs dpkg -P', capture_output=True, text=True, shell=True, check=False)
        if result.returncode == 0:
            removed_packages = result.stdout.strip().split('\n')
            print("Packages removed successfully:")
            print('\n'.join(removed_packages))
        else:
            print("No packages available to be purged.")
    except subprocess.CalledProcessError as e:
        print(f"Error: {e}")
        sys.exit(1)
def print_usage():
    print("Usage:")
    print("  purgerc             : List packages with status 'rc'")
    print("  purgerc -l          : List packages with status 'rc'")
    print("  purgerc -f          : Purge packages with status 'rc'")
    print("  purgerc -h or -?    : Show this usage message")
def main():
    if len(sys.argv) == 1:
        list_rc_packages()
    elif len(sys.argv) == 2:
        if sys.argv[1] == '-l':
            list_rc_packages()
        elif sys.argv[1] == '-f':
            remove_rc_packages()
        elif sys.argv[1] in ['-h', '-?']:
            print_usage()
        else:
            print("Invalid argument. Use -h or -? for usage.")
            sys.exit(1)
    else:
        print("Invalid number of arguments. Use -h or -? for usage.")
        sys.exit(1)
if __name__ == "__main__":
    main()