fix bug
This commit is contained in:
292
dependency_checker.py
Normal file
292
dependency_checker.py
Normal file
@@ -0,0 +1,292 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
依赖检查模块
|
||||
检查系统是否安装了必要的文件系统工具和其他依赖
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import logging
|
||||
from typing import Dict, List, Tuple, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DependencyChecker:
|
||||
"""依赖检查器"""
|
||||
|
||||
# 定义依赖项及其检查命令
|
||||
DEPENDENCIES = {
|
||||
# 文件系统工具
|
||||
'ext4': {
|
||||
'name': 'ext4 文件系统支持',
|
||||
'commands': ['mkfs.ext4', 'fsck.ext4', 'resize2fs'],
|
||||
'package': {
|
||||
'centos': 'e2fsprogs',
|
||||
'arch': 'e2fsprogs',
|
||||
'ubuntu': 'e2fsprogs'
|
||||
}
|
||||
},
|
||||
'xfs': {
|
||||
'name': 'XFS 文件系统支持',
|
||||
'commands': ['mkfs.xfs', 'xfs_repair', 'xfs_growfs'],
|
||||
'package': {
|
||||
'centos': 'xfsprogs',
|
||||
'arch': 'xfsprogs',
|
||||
'ubuntu': 'xfsprogs'
|
||||
}
|
||||
},
|
||||
'ntfs': {
|
||||
'name': 'NTFS 文件系统支持',
|
||||
'commands': ['mkfs.ntfs', 'ntfsfix'],
|
||||
'package': {
|
||||
'centos': 'ntfs-3g',
|
||||
'arch': 'ntfs-3g',
|
||||
'ubuntu': 'ntfs-3g'
|
||||
}
|
||||
},
|
||||
'fat32': {
|
||||
'name': 'FAT32/VFAT 文件系统支持',
|
||||
'commands': ['mkfs.vfat', 'fsck.vfat'],
|
||||
'package': {
|
||||
'centos': 'dosfstools',
|
||||
'arch': 'dosfstools',
|
||||
'ubuntu': 'dosfstools'
|
||||
}
|
||||
},
|
||||
# 分区工具
|
||||
'parted': {
|
||||
'name': '分区工具',
|
||||
'commands': ['parted', 'partprobe'],
|
||||
'package': {
|
||||
'centos': 'parted',
|
||||
'arch': 'parted',
|
||||
'ubuntu': 'parted'
|
||||
}
|
||||
},
|
||||
# RAID 工具
|
||||
'mdadm': {
|
||||
'name': 'RAID 管理工具',
|
||||
'commands': ['mdadm'],
|
||||
'package': {
|
||||
'centos': 'mdadm',
|
||||
'arch': 'mdadm',
|
||||
'ubuntu': 'mdadm'
|
||||
}
|
||||
},
|
||||
# LVM 工具
|
||||
'lvm': {
|
||||
'name': 'LVM 逻辑卷管理',
|
||||
'commands': ['pvcreate', 'vgcreate', 'lvcreate', 'pvs', 'vgs', 'lvs'],
|
||||
'package': {
|
||||
'centos': 'lvm2',
|
||||
'arch': 'lvm2',
|
||||
'ubuntu': 'lvm2'
|
||||
}
|
||||
},
|
||||
# SMART 监控
|
||||
'smartctl': {
|
||||
'name': 'SMART 磁盘健康监控',
|
||||
'commands': ['smartctl'],
|
||||
'package': {
|
||||
'centos': 'smartmontools',
|
||||
'arch': 'smartmontools',
|
||||
'ubuntu': 'smartmontools'
|
||||
},
|
||||
'optional': True
|
||||
},
|
||||
# 其他工具
|
||||
'lsof': {
|
||||
'name': '进程占用查询',
|
||||
'commands': ['lsof', 'fuser'],
|
||||
'package': {
|
||||
'centos': 'lsof, psmisc',
|
||||
'arch': 'lsof, psmisc',
|
||||
'ubuntu': 'lsof, psmisc'
|
||||
},
|
||||
'optional': True
|
||||
},
|
||||
'sfdisk': {
|
||||
'name': '分区表备份/恢复',
|
||||
'commands': ['sfdisk'],
|
||||
'package': {
|
||||
'centos': 'util-linux',
|
||||
'arch': 'util-linux',
|
||||
'ubuntu': 'util-linux'
|
||||
},
|
||||
'optional': True
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
self._os_type = self._detect_os()
|
||||
|
||||
def _detect_os(self) -> str:
|
||||
"""检测操作系统类型"""
|
||||
try:
|
||||
with open('/etc/os-release', 'r') as f:
|
||||
content = f.read().lower()
|
||||
if 'centos' in content or 'rhel' in content or 'fedora' in content:
|
||||
return 'centos'
|
||||
elif 'arch' in content:
|
||||
return 'arch'
|
||||
elif 'ubuntu' in content or 'debian' in content:
|
||||
return 'ubuntu'
|
||||
except Exception:
|
||||
pass
|
||||
return 'centos' # 默认
|
||||
|
||||
def _command_exists(self, cmd: str) -> bool:
|
||||
"""检查命令是否存在"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['which', cmd],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
check=False
|
||||
)
|
||||
return result.returncode == 0
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def check_dependency(self, key: str) -> Tuple[bool, List[str], List[str]]:
|
||||
"""
|
||||
检查单个依赖项
|
||||
返回: (是否全部安装, 已安装的命令列表, 未安装的命令列表)
|
||||
"""
|
||||
if key in self._cache:
|
||||
return self._cache[key]
|
||||
|
||||
dep = self.DEPENDENCIES.get(key)
|
||||
if not dep:
|
||||
return False, [], []
|
||||
|
||||
installed = []
|
||||
missing = []
|
||||
|
||||
for cmd in dep['commands']:
|
||||
if self._command_exists(cmd):
|
||||
installed.append(cmd)
|
||||
else:
|
||||
missing.append(cmd)
|
||||
|
||||
result = (len(missing) == 0, installed, missing)
|
||||
self._cache[key] = result
|
||||
return result
|
||||
|
||||
def check_all(self) -> Dict[str, dict]:
|
||||
"""
|
||||
检查所有依赖项
|
||||
返回: 依赖项状态字典
|
||||
"""
|
||||
results = {}
|
||||
for key, dep in self.DEPENDENCIES.items():
|
||||
is_complete, installed, missing = self.check_dependency(key)
|
||||
results[key] = {
|
||||
'name': dep['name'],
|
||||
'is_complete': is_complete,
|
||||
'installed': installed,
|
||||
'missing': missing,
|
||||
'package': dep['package'].get(self._os_type, dep['package']['centos']),
|
||||
'optional': dep.get('optional', False),
|
||||
'commands': dep['commands']
|
||||
}
|
||||
return results
|
||||
|
||||
def get_install_commands(self, results: Dict[str, dict] = None) -> Dict[str, List[str]]:
|
||||
"""
|
||||
获取安装命令
|
||||
返回: {包名: [依赖项名称列表]}
|
||||
"""
|
||||
if results is None:
|
||||
results = self.check_all()
|
||||
|
||||
packages = {}
|
||||
for key, status in results.items():
|
||||
if not status['is_complete'] and not status['optional']:
|
||||
pkg = status['package']
|
||||
if pkg not in packages:
|
||||
packages[pkg] = []
|
||||
packages[pkg].append(status['name'])
|
||||
|
||||
return packages
|
||||
|
||||
def get_summary(self) -> Dict[str, any]:
|
||||
"""
|
||||
获取依赖检查摘要
|
||||
"""
|
||||
results = self.check_all()
|
||||
|
||||
total = len(results)
|
||||
complete = sum(1 for r in results.values() if r['is_complete'])
|
||||
optional_missing = sum(1 for r in results.values() if not r['is_complete'] and r['optional'])
|
||||
required_missing = sum(1 for r in results.values() if not r['is_complete'] and not r['optional'])
|
||||
|
||||
# 按类别分组
|
||||
categories = {
|
||||
'filesystem': ['ext4', 'xfs', 'ntfs', 'fat32'],
|
||||
'partition': ['parted'],
|
||||
'raid': ['mdadm'],
|
||||
'lvm': ['lvm'],
|
||||
'other': ['smartctl', 'lsof', 'sfdisk']
|
||||
}
|
||||
|
||||
category_status = {}
|
||||
for cat, keys in categories.items():
|
||||
cat_results = {k: results[k] for k in keys if k in results}
|
||||
category_status[cat] = cat_results
|
||||
|
||||
return {
|
||||
'total': total,
|
||||
'complete': complete,
|
||||
'optional_missing': optional_missing,
|
||||
'required_missing': required_missing,
|
||||
'results': results,
|
||||
'categories': category_status,
|
||||
'install_commands': self.get_install_commands(results),
|
||||
'os_type': self._os_type
|
||||
}
|
||||
|
||||
|
||||
# 全局实例
|
||||
_checker = None
|
||||
|
||||
def get_dependency_checker() -> DependencyChecker:
|
||||
"""获取全局依赖检查器实例"""
|
||||
global _checker
|
||||
if _checker is None:
|
||||
_checker = DependencyChecker()
|
||||
return _checker
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 测试
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
checker = get_dependency_checker()
|
||||
summary = checker.get_summary()
|
||||
|
||||
print("=" * 60)
|
||||
print("依赖检查报告")
|
||||
print("=" * 60)
|
||||
print(f"操作系统: {summary['os_type']}")
|
||||
print(f"总依赖项: {summary['total']}")
|
||||
print(f"已安装: {summary['complete']}")
|
||||
print(f"必需但缺失: {summary['required_missing']}")
|
||||
print(f"可选缺失: {summary['optional_missing']}")
|
||||
print()
|
||||
|
||||
for key, status in summary['results'].items():
|
||||
icon = "✓" if status['is_complete'] else "○" if status['optional'] else "✗"
|
||||
print(f"{icon} {status['name']}")
|
||||
if not status['is_complete']:
|
||||
print(f" 缺失命令: {', '.join(status['missing'])}")
|
||||
print(f" 安装包: {status['package']}")
|
||||
|
||||
print()
|
||||
print("安装命令:")
|
||||
if summary['install_commands']:
|
||||
for pkg, names in summary['install_commands'].items():
|
||||
print(f" {pkg} # {', '.join(names)}")
|
||||
else:
|
||||
print(" 所有必需依赖已安装")
|
||||
Reference in New Issue
Block a user