-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclear_kernel_module.py
More file actions
executable file
·184 lines (152 loc) · 5.64 KB
/
clear_kernel_module.py
File metadata and controls
executable file
·184 lines (152 loc) · 5.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/env python3
import os
import subprocess
import re
import sys
# === 配置区域 ===
# 无论如何都不能删除的内核版本关键词
PROTECTED_KEYWORDS = ["6.12.0-CXL"]
# 搜索内核模块的基础路径
MODULES_DIR = "/lib/modules"
# /boot 目录
BOOT_DIR = "/boot"
def get_current_kernel():
"""获取当前正在运行的内核版本"""
return subprocess.check_output(["uname", "-r"]).decode().strip()
def is_protected(version, current_version):
"""判断版本是否受到保护"""
# 1. 保护当前运行的内核
if version == current_version:
return True, "正在运行 (Active)"
# 2. 保护用户指定的白名单 (如 6.12.0-CXL)
for kw in PROTECTED_KEYWORDS:
if kw in version:
return True, f"白名单保护 ({kw})"
return False, ""
def scan_kernels():
"""扫描 /lib/modules 下的所有内核版本"""
if not os.path.exists(MODULES_DIR):
print(f"错误: 找不到 {MODULES_DIR},这不仅不合理,简直是荒谬。")
sys.exit(1)
# 获取所有目录名作为版本号
versions = [d for d in os.listdir(MODULES_DIR) if os.path.isdir(os.path.join(MODULES_DIR, d))]
versions.sort() # 排序,看着舒服点
return versions
def find_associated_files(version):
"""找到 /boot 下与该版本关联的所有文件"""
# 通配符模式匹配:vmlinuz-5.15.0-custom, initrd.img-5.15.0-custom 等
patterns = [
f"vmlinuz-{version}",
f"vmlinux-{version}",
f"initrd.img-{version}",
f"initramfs-{version}.img",
f"System.map-{version}",
f"config-{version}"
]
found_files = []
for f in os.listdir(BOOT_DIR):
# 精确匹配后缀,防止删除 vmlinuz-5.15.0-custom-2
# 虽然这种情况很少,但严谨是必须的
if f in patterns:
found_files.append(os.path.join(BOOT_DIR, f))
return found_files
def main():
# 检查 root 权限
if os.geteuid() != 0:
print("错误: 清理内核需要 root 权限。请使用 sudo 运行此脚本。")
sys.exit(1)
current_ver = get_current_kernel()
all_versions = scan_kernels()
print(f"\n=== Linux Kernel Cleaner (By Linus Torvalds' Spirit) ===")
print(f"当前内核: \033[1;32m{current_ver}\033[0m")
print("-" * 60)
# 构建菜单列表
menu_map = {}
valid_indices = []
for idx, ver in enumerate(all_versions):
protected, reason = is_protected(ver, current_ver)
status_str = ""
if protected:
status_str = f"\033[1;31m[PROTECTED - {reason}]\033[0m"
else:
status_str = "\033[1;36m[可删除]\033[0m"
valid_indices.append(str(idx))
print(f"[{idx}] {ver.ljust(30)} {status_str}")
menu_map[idx] = {'ver': ver, 'protected': protected}
print("-" * 60)
print("输入要删除的内核编号 (例如: 0, 或多个: 0 2 3)。")
print("受保护的内核即使被选中也会被跳过。")
user_input = input("请输入: ").strip()
if not user_input:
print("未输入,退出。")
return
# 解析输入
targets = []
try:
selection = re.split(r'[,\s]+', user_input)
for s in selection:
if not s: continue
idx = int(s)
if idx in menu_map:
targets.append(menu_map[idx])
else:
print(f"忽略无效索引: {idx}")
except ValueError:
print("输入格式错误,请输入数字。")
return
if not targets:
print("没有选中任何有效目标。")
return
# 确认阶段
ops_list = []
print("\n--- 即将执行以下删除操作 ---")
for item in targets:
ver = item['ver']
if item['protected']:
print(f"跳过: {ver} (受保护)")
continue
# 1. 模块目录
mod_path = os.path.join(MODULES_DIR, ver)
ops_list.append(mod_path)
print(f"\n[目标内核]: \033[1;33m{ver}\033[0m")
print(f" -> 将删除: {mod_path}")
# 2. Boot 文件
boot_files = find_associated_files(ver)
for f in boot_files:
ops_list.append(f)
print(f" -> 将删除: {f}")
if not ops_list:
print("\n没有什么可删的,收工。")
return
print("\n" + "!" * 40)
confirm = input("你确定要永久删除这些文件吗?此操作不可撤销![yes/N]: ")
if confirm.lower() != 'yes':
print("操作已取消。明智的选择。")
return
# 执行删除
print("\n正在执行清理...")
for path in ops_list:
try:
if os.path.isdir(path):
subprocess.run(['rm', '-rf', path], check=True)
else:
os.remove(path)
print(f"已删除: {path}")
except Exception as e:
print(f"删除失败 {path}: {e}")
# 更新 GRUB
print("\n正在刷新 GRUB 配置 (update-grub)...")
try:
# 兼容不同发行版的 grub 命令,主要是 update-grub 或 grub-mkconfig
if os.path.exists("/usr/sbin/update-grub"):
subprocess.run(['update-grub'], check=True)
else:
# RHEL/CentOS 系通常是 grub2-mkconfig
subprocess.run(['grub2-mkconfig', '-o', '/boot/grub2/grub.cfg'], check=True)
print("GRUB 更新完成。")
except subprocess.CalledProcessError as e:
print(f"GRUB 更新失败: {e}")
print("你可能需要手动运行 update-grub。")
print("\n完成。下次编译时记得用 LOCALVERSION")
if __name__ == "__main__":
main()