xiaowei-system/skills/devops/devops-umbrella/references/linux-desktop-cleanup.md

5.7 KiB
Executable File
Raw Blame History

Linux 桌面残留清理

记录 Linux 上清理流氓软件残留的实战经验。以 CC Switch 为例。

核心教训

流氓软件(尤其 Windows 软件的 Linux 移植版)卸载后会在多处留下残留,需要系统性清理。

CC Switch 残留清单

路径 类型 清理方式
~/.config/autostart/*.desktop 自启动项 rm
~/.local/share/applications/*.desktop 应用入口 rm
~/.config/mimeapps.list MIME 类型关联 编辑器移除 x-scheme-handler/ccswitch
~/.config/deepin/dde-desktop/dde-desktop.conf Deepin 桌面配置 Python configparser 移除含 cc 的项
~/.config/deepin/dde-launchpad/item-arrangement.ini Deepin 启动器配置 编辑器移除 CC Switch.desktop
~/.local/share/deepin/ApplicationManager/storage.json Deepin 应用商店记录 Python JSON 移除对应 key
~/.cc-switch/ 用户数据 rm -rf
~/.config/com.ccswitch.desktop/ 独立配置目录 rm -rf
~/.local/share/com.ccswitch.desktop/ 独立数据目录 rm -rf
/usr/share/applications/CC Switch.desktop 系统级桌面入口 需要 sudo
~/Desktop/CC Switch.desktop 桌面软链接 rm

深度清理脚本

import configparser
import json
import os
import shutil

HOME = os.path.expanduser("~")

def remove_cc_switch():
    # 1. Desktop 软链接
    desktop_link = f"{HOME}/Desktop/CC Switch.desktop"
    if os.path.islink(desktop_link) or os.path.exists(desktop_link):
        os.remove(desktop_link)
        print(f"Removed: {desktop_link}")

    # 2. autostart
    autostart = f"{HOME}/.config/autostart/CC Switch.desktop"
    if os.path.exists(autostart):
        os.remove(autostart)
        print(f"Removed: {autostart}")

    # 3. user apps
    user_app = f"{HOME}/.local/share/applications/cc-switch-handler.desktop"
    if os.path.exists(user_app):
        os.remove(user_app)
        print(f"Removed: {user_app}")

    # 4. mimeapps.list — 移除 x-scheme-handler/ccswitch
    mimeapps = f"{HOME}/.config/mimeapps.list"
    if os.path.exists(mimeapps):
        content = open(mimeapps).read()
        if "ccswitch" in content:
            lines = [l for l in content.split("\n") if "ccswitch" not in l.lower()]
            open(mimeapps, "w").write("\n".join(lines))
            print(f"Cleaned: {mimeapps}")

    # 5. Deepin ApplicationManager storage.json需要 sudo 但先试用户可写路径)
    app_storage = f"{HOME}/.local/share/deepin/ApplicationManager/storage.json"
    if os.path.exists(app_storage):
        try:
            with open(app_storage) as f:
                d = json.load(f)
            keys = [k for k in d.keys() if "cc" in k.lower() or "switch" in k.lower()]
            for k in keys:
                del d[k]
            with open(app_storage, "w") as f:
                json.dump(d, f, indent=2)
            print(f"Cleaned: {app_storage}")
        except PermissionError:
            # 需要 sudo
            print(f"Need sudo for: {app_storage}")
            print(f"  python3 -c \"import json; path='{app_storage}'; ...")

    # 6. Deepin dde-desktop.conf
    conf = f"{HOME}/.config/deepin/dde-desktop/dde-desktop.conf"
    if os.path.exists(conf):
        try:
            c = configparser.ConfigParser()
            c.read(conf)
            for s in c.sections():
                for k in list(c.options(s)):
                    if "cc" in k.lower():
                        c.remove_option(s, k)
            c.write(open(conf, "w"))
            print(f"Cleaned: {conf}")
        except Exception as e:
            print(f"Error cleaning {conf}: {e}")

    # 7. Deepin launchpad item-arrangement.ini
    ini = f"{HOME}/.config/deepin/dde-launchpad/item-arrangement.ini"
    if os.path.exists(ini):
        content = open(ini).read()
        if "CC Switch" in content:
            content = content.replace("CC Switch.desktop,", "").replace(", CC Switch.desktop", "")
            open(ini, "w").write(content)
            print(f"Cleaned: {ini}")

    # 8. 用户数据目录
    for d in [f"{HOME}/.cc-switch",
              f"{HOME}/.config/com.ccswitch.desktop",
              f"{HOME}/.local/share/com.ccswitch.desktop"]:
        if os.path.exists(d):
            shutil.rmtree(d)
            print(f"Removed: {d}")

    # 9. 系统级 desktop 文件(需要 sudo
    sys_desktop = "/usr/share/applications/CC Switch.desktop"
    if os.path.exists(sys_desktop):
        print(f"Need sudo to remove: {sys_desktop}")
        print(f"  sudo rm \"{sys_desktop}\"")

if __name__ == "__main__":
    remove_cc_switch()
    print("Done. Log out and back in or restart desktop to fully生效.")

Deepin ApplicationManager storage.json 清理Sudo 版)

import json
path = '/home/muc/.local/share/deepin/ApplicationManager/storage.json'
with open(path) as f:
    d = json.load(f)
keys = [k for k in d.keys() if 'cc' in k.lower() or 'switch' in k.lower()]
for k in keys:
    del d[k]
with open(path, 'w') as f:
    json.dump(d, f, indent=2)
print('Done')

关键发现

  1. Deepin 有自己独立的应用管理器storage.json 路径:~/.local/share/deepin/ApplicationManager/storage.json(不是 /root/ 下)
  2. MIME 类型不止 mimeapps.listWM_CLASS 也需要清理(StartupWMClass=cc-switch 在 .desktop 文件中)
  3. 桌面入口不只在 applications 目录Deepin 还会在 ~/.config/deepin/dde-desktop/~/.config/deepin/dde-launchpad/ 中记录
  4. 系统级 desktop 文件必须 sudo 才能删

清理完成验证

# 确认所有残留消失
find ~ -maxdepth 4 -name "*ccswitch*" -o -name "*cc-switch*" 2>/dev/null | grep -v "\.git\|\.cache\|Trash"
grep -ri "ccswitch" ~/.config/ 2>/dev/null | grep -v "Network Persistent State"