怎么用脚本获取系统模块——Python与Bash实战指南
📖 目录导读
- 什么是系统模块?为什么需要脚本获取?
- Python脚本获取系统模块的5种核心方法
- Bash脚本获取系统模块的4种高效技巧
- 常见问题与解答(FAQ)
- 性能与安全注意事项
- 实操案例:自动化获取模块并生成报告
什么是系统模块?为什么需要脚本获取?
系统模块指的是操作系统内核、动态链接库(.dll/.so)、内核模块(.ko)、Python/C#等语言的标准库与第三方包,在运维、开发、逆向工程或渗透测试中,经常需要快速获取系统已加载或可用的模块列表。

典型场景:
- 程序员排查依赖缺失(如
ImportError: No module named) - 运维人员查看Linux内核模块(
lsmod) - 安全工程师检测异常模块加载
- 自动化部署脚本环境检测
之所以要用脚本而非手动命令,是因为脚本可以实现:
- 批量服务器远程执行
- 结果结构化存储(JSON/CSV)
- 结合条件判断(如仅输出异常模块)
核心思路:不同语言脚本调用系统API或读取系统文件,再解析输出。
Python脚本获取系统模块的5种核心方法
方法1:sys.modules获取当前已导入模块(最轻量)
import sys
import pprint
def get_imported_modules():
"""返回当前Python进程已加载的所有模块名"""
return list(sys.modules.keys())
if __name__ == "__main__":
modules = get_imported_modules()
print(f"已导入模块总数: {len(modules)}")
pprint.pprint(modules[:10]) # 仅显示前10个
注意:只显示当前脚本中import过的模块,并非系统全部Python模块。
方法2:pkgutil扫描安装的Python包(标准库+第三方)
import pkgutil
def get_all_python_modules():
"""遍历所有可用的Python模块"""
modules = []
for module_info in pkgutil.iter_modules():
modules.append(module_info.name)
return modules
# 示例输出:['abc', 'ast', 'asyncio', 'numpy', 'requests', ...]
优点:返回当前Python环境中所有可导入的模块,无论是否已在代码中导入。
方法3:subprocess调用系统命令(Linux模块)
import subprocess
import re
def get_kernel_modules():
"""获取Linux内核模块(类似lsmod)"""
try:
result = subprocess.run(['lsmod'], capture_output=True, text=True, check=True)
modules = []
for line in result.stdout.strip().split('\n')[1:]: # 跳过标题行
parts = re.split(r'\s+', line)
if len(parts) >= 1:
modules.append(parts[0])
return modules
except Exception as e:
return [f"错误: {e}"]
# 输出示例:['usbcore', 'ext4', 'snd_hda_intel', ...]
方法4:ctypes调用Windows API(Windows DLL模块)
import ctypes
from ctypes import wintypes
def get_windows_modules():
"""获取当前进程加载的Windows DLL"""
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
# 这里简化演示:使用EnumProcessModules(需更完整实现)
# 实际建议使用psutil库更安全
return ["通过ctypes调用WinAPI(需管理员权限)"]
# 更推荐方式:使用psutil
def get_windows_modules_psutil():
import psutil
process = psutil.Process()
return [lib.path for lib in process.memory_maps() if lib.path.endswith('.dll')]
方法5:os.listdir直接扫描系统目录
import os
def get_system_libs_from_path(path="/usr/lib"):
"""获取指定目录下的动态库文件"""
if not os.path.isdir(path):
return [f"目录不存在: {path}"]
return [f for f in os.listdir(path) if f.endswith(('.so', '.dll'))]
# 注意:Linux下/lib、/usr/lib含大量系统库;Windows下为C:\Windows\System32
实际生产建议:方法2(pkgutil)最适合Python模块,方法3(subprocess+lsmod)最适合Linux内核模块,推荐组合使用。
3️⃣ Bash脚本获取系统模块的4种高效技巧
Bash脚本在获取系统级模块时,比Python更直接、性能更高(无需解释器开销)。
技巧1:lsmod + 文本处理
#!/bin/bash
# 获取当前内核模块名及大小
lsmod | awk 'NR>1 {print $1}' > /tmp/kernel_modules.txt
echo "共 $(wc -l < /tmp/kernel_modules.txt) 个内核模块"
技巧2:扫描共享库依赖
#!/bin/bash
# 列出所有可执行文件依赖的共享库
ldconfig -p | awk '{print $1}' | sort -u > all_shared_libs.txt
技巧3:使用module命令(环境模块系统)
某些高性能计算环境使用module load,脚本探测已加载模块:
#!/bin/bash
if command -v module &> /dev/null; then
module list 2>&1 | tail -n +3
else
echo "环境模块系统未安装"
fi
技巧4:find扫描+file识别
#!/bin/bash # 查找系统中所有的 .ko 内核模块文件 find /lib/modules/$(uname -r) -name '*.ko' -type f | wc -l echo "内核模块文件总数如上"
相较Python优势:Bash零依赖、执行速度极快、适合cron定时任务,缺点:跨平台性差(Windows需WSL)。
4️⃣ 常见问题与解答(FAQ)
Q1:为什么我的Python脚本跑在Windows上,但lsmod报错?
A:lsmod是Linux命令,Windows需使用tasklist /M或PowerShell的Get-Process -Module,跨平台建议使用platform.system()判断OS再切换代码。
Q2:sys.modules里只有十几个模块,但pip list显示有100个包?
A:sys.modules仅显示当前进程已加载的模块,许多包虽然安装了但未导入,使用pkgutil才能显示全部可导入模块。
Q3:脚本获取模块是否需要管理员权限?
A:仅获取用户态模块(如Python包)无需权限,但获取内核模块(lsmod)、进程加载的DLL(Windows)可能需root或管理员权限。
Q4:不同Linux发行版,模块存放路径一样吗?
A:内核模块路径固定为/lib/modules/$(uname -r)/,但系统库路径有差异(Debian用/usr/lib/x86_64-linux-gnu/,CentOS用/usr/lib64/),建议用ldconfig -p统一查询。
Q5:如何获取某个Python模块的版本号?
A:```python
import pkg_resources
for dist in pkg_resources.working_set:
print(f"{dist.project_name}=={dist.version}")
---
## 5️⃣ 性能与安全注意事项
### 性能优化
- **懒加载**:仅获取需要的模块类型(如仅获取内核模块,别扫所有目录)
- **缓存**:将结果写入文件,避免重复执行(如`lsmod > /tmp/cache.csv`)
- **限制范围**:使用`file`命令识别,避免扫描非模块文件
### 安全防范
- **避免eval/exec**:处理用户输入的模块名时,绝对不要用`eval()`
- **禁用危险模块**:某些模块(如`ctypes.windll`)可调用任意系统API,需限制调用者
- **日志脱敏**:模块路径中可能包含用户名(如`/home/user/.local/...`),输出时建议替换
**最佳实践**:使用`sha256sum`校验模块文件完整性,防止被篡改后再加载。
---
## 6️⃣ 实操案例:自动化获取系统模块并生成报告
以下是一个完整脚本,综合Python与系统命令,输出JSON格式报告:
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import sys
import platform
import pkgutil
import subprocess
def get_system_report():
report = {
"os": platform.system(),
"python_version": sys.version,
}
# 1. Python已安装的模块
try:
report["python_modules"] = [mod.name for mod in pkgutil.iter_modules()][:100]
except Exception as e:
report["python_error"] = str(e)
# 2. 系统动态库(Linux)
if platform.system() == "Linux":
try:
result = subprocess.run(['lsmod'], capture_output=True, text=True, check=True)
lines = result.stdout.strip().split('\n')[1:]
report["kernel_modules"] = [line.split()[0] for line in lines]
except Exception as e:
report["kernel_error"] = str(e)
# 3. Windows DLL(示例)
elif platform.system() == "Windows":
try:
import psutil
proc = psutil.Process()
report["loaded_dlls"] = [p.path for p in proc.memory_maps() if p.path and '.dll' in p.path][:50]
except ImportError:
report["dll_note"] = "请安装psutil: pip install psutil"
return report
if __name__ == "__main__":
report = get_system_report()
print(json.dumps(report, indent=2, ensure_ascii=False))
运行效果:
{
"os": "Linux",
"python_version": "3.11.5",
"python_modules": ["abc", "ast", "asyncio", ...],
"kernel_modules": ["usbcore", "ext4", "snd_hda_intel", ...]
}
扩展建议:
- 加入
socket.gethostname()记录主机名 - 用
datetime添加时间戳 - 输出到文件
report_$(date +%Y%m%d).json便于历史追溯
写在最后
通过Python和Bash两种脚本,你可以灵活获取从内核到用户空间的各类系统模块,生产环境中推荐结合两者:用Bash做快速系统级探测,用Python做结构化分析,务必注意跨平台兼容性与权限控制,避免在关键系统上误执行破坏性命令。
行动建议:现在就在你的开发机或服务器上运行上述脚本,对比实际输出,根据结果调整过滤逻辑,掌握“怎么用脚本获取系统模块”,将极大提升你排查环境问题、自动化部署的效率。