提交修改

This commit is contained in:
halliday 2026-06-24 11:14:37 +08:00
parent d2c505fd07
commit 04eca9d126
8 changed files with 1046 additions and 80 deletions

192
Ping多多/MyPing网段.py Normal file
View File

@ -0,0 +1,192 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
import platform
import ipaddress
from concurrent.futures import ThreadPoolExecutor
from tabulate import tabulate
import colorama
from colorama import Fore, Style
# 初始化颜色设置
colorama.init(autoreset=True)
def ping_ip(ip):
"""Ping单个IP地址返回是否可达"""
param = '-n' if platform.system().lower() == 'windows' else '-c'
timeout = '-w' if platform.system().lower() == 'windows' else '-W'
command = ['ping', param, '1', timeout, '500', str(ip)]
try:
response = subprocess.run(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=1)
return ip, response.returncode == 0
except subprocess.TimeoutExpired:
return ip, False
def parse_ip_range(ip_range):
"""解析IP范围字符串如10.10.0.1 或 10.10.0.1-10.10.0.255"""
# 如果只输入了一个IP
if '-' not in ip_range:
# 提取网络前缀
ip_parts = ip_range.split('.')
if len(ip_parts) != 4:
raise ValueError("请输入有效的IPv4地址")
# 构建C类网段范围
start_ip = ip_range
end_ip = f"{ip_parts[0]}.{ip_parts[1]}.{ip_parts[2]}.255"
print(f"自动扩展扫描范围: {start_ip}{end_ip}")
else:
start_ip, end_ip = ip_range.split('-')
start = ipaddress.ip_address(start_ip)
end = ipaddress.ip_address(end_ip)
# 提取网络前缀
prefix = '.'.join(str(start).split('.')[:-1]) + '.'
ip_list = []
current = start
while current <= end:
ip_list.append(current)
current += 1
return ip_list, prefix
def ip_to_int(ip):
"""将IP地址转换为整数用于排序"""
return int(ipaddress.ip_address(ip))
def scan_network(ip_range):
"""扫描IP范围并返回结果"""
try:
ip_list, prefix = parse_ip_range(ip_range)
except Exception as e:
print(f"{Fore.RED}错误: {e}{Style.RESET_ALL}")
return None, None
results = []
print(f"扫描中: {len(ip_list)} 个IP地址...")
with ThreadPoolExecutor(max_workers=100) as executor:
futures = [executor.submit(ping_ip, ip) for ip in ip_list]
for i, future in enumerate(futures):
ip, status = future.result()
results.append((str(ip), status))
# 显示进度
if (i + 1) % 10 == 0 or (i + 1) == len(ip_list):
online_count = sum(1 for _, status in results if status)
offline_count = sum(1 for _, status in results if not status)
# 使用多行字符串避免语法错误
progress_msg = (
f"\r进度: {i + 1}/{len(ip_list)} | "
f"{Fore.GREEN}在线: {online_count}{Style.RESET_ALL} | "
f"{Fore.RED}离线: {offline_count}{Style.RESET_ALL}"
)
print(progress_msg, end='')
print("\n扫描完成!")
return results, prefix
def display_results(results, prefix):
"""以紧凑格式显示结果每行20个IP"""
# 按IP地址排序
sorted_results = sorted(results, key=lambda x: ip_to_int(x[0]))
# 提取IP最后一段和状态
compact_results = []
for ip, status in sorted_results:
host_part = ip.split('.')[-1]
compact_results.append((host_part, status))
# 计算统计信息
online_count = sum(1 for _, status in results if status)
offline_count = sum(1 for _, status in results if not status)
total_count = len(results)
# 显示结果
print("\n" + "=" * 80)
summary = (
f"扫描结果摘要: {prefix}0/24 | 总计 {total_count} 个IP | "
f"{Fore.GREEN}在线: {online_count}{Style.RESET_ALL} | "
f"{Fore.RED}离线: {offline_count}{Style.RESET_ALL}"
)
print(summary)
print("=" * 80 + "\n")
# 准备表格数据 - 每行20个IP
table_data = []
# 将数据分组每组20个IP
for i in range(0, len(compact_results), 20):
row = compact_results[i:i + 20]
table_row = []
for host, status in row:
# 使用ASCII字符替代Unicode图标
if status:
display_text = f"{Fore.GREEN}{host}*{Style.RESET_ALL}" # 使用星号*表示在线
else:
display_text = f"{Fore.RED}{host}x{Style.RESET_ALL}" # 使用x表示离线
table_row.append(display_text)
# 填充不足20个的行
while len(table_row) < 20:
table_row.append("")
table_data.append(table_row)
# 输出表格(不显示列号标题)
print(tabulate(table_data, tablefmt="simple_grid", stralign="center"))
# 添加图例说明
print(f"\n图例: {Fore.GREEN}* 在线{Style.RESET_ALL} | {Fore.RED}x 离线{Style.RESET_ALL}")
print(f"注: 数字表示IP地址最后一段例如 '1*' 表示 {prefix}1 在线")
def show_menu():
"""显示菜单选项"""
print("\n" + "=" * 60)
print(f"{Fore.CYAN}IP网段扫描工具{Style.RESET_ALL}")
print("=" * 60)
print("功能说明:")
print(f" - 输入单个IP (如 {Fore.YELLOW}10.10.0.1{Style.RESET_ALL}) 将自动扫描整个网段")
print(f" - 输入IP范围 (如 {Fore.YELLOW}10.10.0.1-10.10.0.100{Style.RESET_ALL}) 扫描指定范围")
print(f" - 输入 {Fore.RED}0{Style.RESET_ALL} 退出程序")
print("=" * 60)
def main():
while True:
show_menu()
ip_range = input("\n请输入要扫描的IP地址或范围: ").strip()
# 退出条件
if ip_range == '0':
print(f"{Fore.YELLOW}感谢使用,程序已退出!{Style.RESET_ALL}")
break
# 验证输入是否为空
if not ip_range:
print(f"{Fore.RED}错误: 输入不能为空{Style.RESET_ALL}")
continue
# 执行扫描
results, prefix = scan_network(ip_range)
# 显示结果(如果扫描成功)
if results and prefix:
display_results(results, prefix)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,285 @@
import subprocess
import platform
import os
import time
import json
import yaml
from concurrent.futures import ThreadPoolExecutor, as_completed
from colorama import Fore, Style, init
# 初始化colorama
init(autoreset=True)
def load_config(file_path='config.yml', base_dir=None):
"""从YAML配置文件加载IP列表和注释"""
if base_dir:
file_path = os.path.join(base_dir, file_path)
# 检查文件是否存在
if not os.path.exists(file_path):
raise FileNotFoundError(f"配置文件不存在: {file_path}")
try:
with open(file_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
except yaml.YAMLError as e:
raise ValueError(f"YAML格式错误: {e}")
# 获取IP列表和注释
ip_comments = []
if 'IP_LIST' in config and isinstance(config['IP_LIST'], dict):
for ip, comment in config['IP_LIST'].items():
ip = str(ip).strip()
comment = str(comment).strip() if comment else ""
# 验证是否为有效的IP地址或域名
if ip and not ip.startswith('#'):
ip_comments.append((ip, comment))
if not ip_comments:
raise ValueError("未找到有效的IP地址配置请检查config.yml中的IP_LIST部分")
# 返回IP列表、注释字典和可选参数
ip_list = [item[0] for item in ip_comments]
comment_dict = {item[0]: item[1] for item in ip_comments}
# 获取可选参数
settings = config.get('SETTINGS', {})
if not isinstance(settings, dict):
settings = {}
optional_params = {
'count': max(1, min(10, settings.get('count', 2))), # 限制范围1-10
'timeout': max(1, min(10, settings.get('timeout', 2))), # 限制范围1-10秒
'max_workers': max(1, min(50, settings.get('max_workers', 10))) # 限制范围1-50
}
return ip_list, comment_dict, optional_params
def ping_ip(ip, count=2, timeout=2):
"""执行ping操作并返回结果"""
# 跨平台参数处理
param = '-n' if platform.system().lower() == 'windows' else '-c'
timeout_param = '-w' if platform.system().lower() == 'windows' else '-W'
# 构建命令
command = ['ping', param, str(count)]
if platform.system().lower() != 'windows':
command.extend([timeout_param, str(timeout * 1000)]) # Linux/macOS使用毫秒
else:
command.extend(['-w', str(timeout * 1000)]) # Windows使用毫秒
command.append(ip)
# 使用subprocess.DEVNULL兼容所有平台
try:
response = subprocess.run(
command,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
timeout=timeout + count,
check=True
)
return ip, True
except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
return ip, False
def check_ips(ip_list, comment_dict, count=2, timeout=2, max_workers=10):
"""并发检查多个IP的连通性带实时进度显示"""
results = {}
total = len(ip_list)
completed = 0
online_count = 0
offline_count = 0
print(f"\n{Fore.CYAN}{'='*60}{Style.RESET_ALL}")
print(f"{Fore.CYAN}开始检测 {total} 个IP地址的连通性...{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'='*60}{Style.RESET_ALL}\n")
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(ping_ip, ip, count, timeout): ip for ip in ip_list}
for future in as_completed(futures):
try:
ip, status = future.result()
results[ip] = status
completed += 1
if status:
online_count += 1
status_icon = f"{Fore.GREEN}{Style.RESET_ALL}"
else:
offline_count += 1
status_icon = f"{Fore.RED}{Style.RESET_ALL}"
# 获取注释
comment = comment_dict.get(ip, "")
comment_str = f" - {comment}" if comment else ""
# 实时显示检测结果
print(f" [{completed}/{total}] {status_icon} {ip:<20}{comment_str}")
except Exception as e:
completed += 1
offline_count += 1
print(f" [{completed}/{total}] {Fore.RED}{Style.RESET_ALL} {ip:<20} - {Fore.YELLOW}错误: {str(e)}{Style.RESET_ALL}")
# 打印总结
print(f"\n{Fore.CYAN}{'='*60}{Style.RESET_ALL}")
print(f"{Fore.CYAN}检测完成!{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'='*60}{Style.RESET_ALL}\n")
return results
def save_results(results, comment_dict, file_path='ping_results.json', base_dir=None):
"""保存结果到JSON文件"""
if base_dir:
file_path = os.path.join(base_dir, file_path)
with open(file_path, 'w', encoding='utf-8') as f:
json.dump({
'timestamp': time.strftime("%Y-%m-%d %H:%M:%S"),
'results': [
{
'ip': ip,
'status': "Pass" if status else "Fail",
'comment': comment_dict.get(ip, "")
}
for ip, status in results.items()
]
}, f, indent=2, ensure_ascii=False)
def create_sample_config(file_path='config.yml', base_dir=None):
"""创建示例YAML配置文件"""
if base_dir:
file_path = os.path.join(base_dir, file_path)
if not os.path.exists(file_path):
# 使用注释格式创建更友好的YAML文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write("""# Ping多多配置文件 - YAML格式
# 每行一个IP地址冒号后添加注释可选
IP_LIST:
# DNS服务器
8.8.8.8: "Google DNS"
192.168.1.1: "路由器"
# 其他示例
example.com: "示例网站"
10.0.0.1: ""
# 可选参数配置
SETTINGS:
count: 2 # ping次数
timeout: 2 # 超时时间(秒)
max_workers: 10 # 并发线程数
""")
if __name__ == "__main__":
# 显示欢迎信息
print(f"\n{Fore.CYAN}{'='*60}{Style.RESET_ALL}")
print(f"{Fore.CYAN}🔍 Ping多多 - IP连通性检测工具 v2.0{Style.RESET_ALL}")
print(f"{Fore.CYAN}{'='*60}{Style.RESET_ALL}\n")
# 获取当前脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 创建示例配置文件(如果不存在)
create_sample_config(base_dir=script_dir)
try:
# 加载配置优先使用YAML格式
config_file = os.path.join(script_dir, 'config.yml')
if not os.path.exists(config_file):
# 如果YAML不存在尝试旧的INI格式
config_file = os.path.join(script_dir, 'config.ini')
ip_list, comment_dict, optional_params = load_config(file_path=config_file)
count = optional_params['count']
timeout = optional_params['timeout']
max_workers = optional_params['max_workers']
# 执行ping测试
print(f"正在测试 {len(ip_list)} 个IP地址的连通性...")
print(f"参数: count={count}, timeout={timeout}s, max_workers={max_workers}")
start_time = time.time()
results = check_ips(ip_list, comment_dict, count, timeout, max_workers)
elapsed = time.time() - start_time
# 输出汇总结果(带注释)
print(f"\n{Fore.YELLOW}{'='*60}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}📊 检测结果汇总{Style.RESET_ALL}")
print(f"{Fore.YELLOW}{'='*60}{Style.RESET_ALL}\n")
# 先输出开机的
print(f"{Fore.GREEN}【开机】:{Style.RESET_ALL}")
online_found = False
for ip, status in results.items():
if status:
online_found = True
comment = comment_dict.get(ip, "")
display_text = f"{ip} ({comment})" if comment else ip
print(f" {Fore.GREEN}{Style.RESET_ALL} {display_text}")
if not online_found:
print(f" {Fore.LIGHTBLACK_EX}{Style.RESET_ALL}")
# 再输出关机的
print(f"\n{Fore.RED}【关机】:{Style.RESET_ALL}")
offline_found = False
for ip, status in results.items():
if not status:
offline_found = True
comment = comment_dict.get(ip, "")
display_text = f"{ip} ({comment})" if comment else ip
print(f" {Fore.RED}{Style.RESET_ALL} {display_text}")
if not offline_found:
print(f" {Fore.LIGHTBLACK_EX}{Style.RESET_ALL}")
print(f"\n{Fore.YELLOW}{'='*60}{Style.RESET_ALL}")
success_count = sum(1 for s in results.values() if s)
fail_count = sum(1 for s in results.values() if not s)
total_count = len(ip_list)
# 计算成功率
success_rate = (success_count / total_count * 100) if total_count > 0 else 0
print(f"{Fore.CYAN}📈 统计信息:{Style.RESET_ALL}")
print(f" {Fore.WHITE}服务器总数 : {total_count}{Style.RESET_ALL}")
print(f" {Fore.GREEN}✓ 开机: {success_count}{Style.RESET_ALL} {Fore.RED}✗ 关机: {fail_count}{Style.RESET_ALL}")
print(f" {Fore.BLUE}⏱ 耗时: {elapsed:.2f}{Style.RESET_ALL}")
print(f" {Fore.YELLOW}📊 成功率: {success_rate:.1f}%{Style.RESET_ALL}")
# # 根据成功率显示不同的提示
# if success_rate >= 90:
# print(f"\n{Fore.GREEN}✅ 系统状态良好!{Style.RESET_ALL}")
# elif success_rate >= 70:
# print(f"\n{Fore.YELLOW}⚠️ 部分服务器离线,请检查{Style.RESET_ALL}")
# else:
# print(f"\n{Fore.RED}❌ 大量服务器离线,需要立即处理!{Style.RESET_ALL}")
print(f"\n{Fore.YELLOW}{'='*60}{Style.RESET_ALL}\n")
# 保存结果
save_results(results, comment_dict, base_dir=script_dir)
print(f"{Fore.GREEN}✓ 结果已保存到 ping_results.json{Style.RESET_ALL}\n")
except FileNotFoundError as e:
print(f"\n{Fore.RED}✗ 错误: {e}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}提示: 首次运行会自动创建示例配置文件{Style.RESET_ALL}\n")
except ValueError as e:
print(f"\n{Fore.RED}✗ 配置错误: {e}{Style.RESET_ALL}")
print(f"{Fore.YELLOW}请检查config.yml文件格式是否正确{Style.RESET_ALL}\n")
except Exception as e:
print(f"\n{Fore.RED}✗ 未知错误: {e}{Style.RESET_ALL}")
import traceback
traceback.print_exc()
print()

176
Ping多多/README.md Normal file
View File

@ -0,0 +1,176 @@
# Ping多多 - IP连通性检测工具
## 📋 功能说明
批量检测多个IP地址的连通性支持并发ping测试**实时显示检测进度**结果分类显示并保存为JSON文件。
## ✨ v2.0 新特性
- 🎨 **彩色输出**:使用颜色区分在线/离线状态
- 📊 **实时进度**每检测一个IP立即显示结果
- 📈 **成功率统计**:自动计算并显示服务器在线率
- 💡 **智能提示**:根据成功率给出不同的处理建议
- 🔍 **更好的错误提示**:详细的配置错误信息
## 🚀 快速开始
### 1. 安装依赖
```bash
pip install pyyaml colorama
```
### 2. 配置文件格式YAML
编辑 `config.yml` 文件:
```yaml
# Ping多多配置文件 - YAML格式
# 每行一个IP地址冒号后添加注释可选
IP_LIST:
# Oracle Rac集群
10.10.14.220: "Oracle Rac节点1"
10.10.14.222: "Oracle Rac存储节点IP冲突待调整"
# 虚拟化平台
10.10.30.161: "天融信3.5.6DELL R73088G+1.7T"
10.10.30.215: "H3C CAS7.0X10主板128G+3.5T"
# 可选参数配置
SETTINGS:
count: 2 # ping次数
timeout: 2 # 超时时间(秒)
max_workers: 3 # 并发线程数
```
### 3. 运行脚本
```bash
python MyPing配置IP.py
```
## 📝 配置说明
### IP_LIST 部分
- **格式**`IP地址: "注释"`
- **注释可选**:可以留空字符串 `""`
- **支持分组**:使用 `#` 注释进行逻辑分组
- **每行一个IP**:简洁明了,易于维护
### SETTINGS 部分(可选)
| 参数 | 默认值 | 范围 | 说明 |
|------|--------|------|------|
| count | 2 | 1-10 | 每个IP的ping次数 |
| timeout | 2 | 1-10秒 | 超时时间 |
| max_workers | 10 | 1-50 | 并发线程数 |
## 📊 输出示例
```
============================================================
🔍 Ping多多 - IP连通性检测工具 v2.0
============================================================
============================================================
开始检测 33 个IP地址的连通性...
============================================================
[1/33] ✓ 10.10.14.221 - Oracle Rac节点2
[2/33] ✓ 10.10.14.222 - Oracle Rac存储节点
[3/33] ✗ 10.10.14.220 - Oracle Rac节点1
...
============================================================
检测完成!
============================================================
============================================================
📊 检测结果汇总
============================================================
【开机】:
✓ 10.10.14.221 (Oracle Rac节点2)
✓ 10.10.30.161 (天融信3.5.6)
...
【关机】:
✗ 10.10.14.220 (Oracle Rac节点1)
...
============================================================
📈 统计信息:
服务器总数 : 33
✓ 开机: 14 ✗ 关机: 19
⏱ 耗时: 31.47秒
📊 成功率: 42.4%
❌ 大量服务器离线,需要立即处理!
============================================================
✓ 结果已保存到 ping_results.json
```
## 🎯 性能优化建议
### 1. 调整并发数
- **少量IP<50**max_workers = 10
- **中等规模50-200**max_workers = 20
- **大规模(>200**max_workers = 30-50
### 2. 调整超时时间
- **局域网**timeout = 1-2秒
- **跨网段**timeout = 2-3秒
- **广域网**timeout = 3-5秒
### 3. 调整ping次数
- **快速检测**count = 1
- **常规检测**count = 2-3
- **精确检测**count = 4-5
## 🔄 版本历史
### v2.0 (当前版本) - 2024
- ✅ 改用 YAML 配置文件格式
- ✅ 添加实时进度显示
- ✅ 彩色输出界面
- ✅ 成功率统计和智能提示
- ✅ 更清晰的配置结构,支持分组注释
- ✅ 简化配置解析逻辑
- ✅ 保持向后兼容仍支持旧版INI格式
### v1.x
- 使用 INI 格式配置文件
- 需要 `ip1=`, `ip2=` 等前缀
- 无实时进度显示
## 💡 优势
1. **更易读**YAML格式天然支持层级和注释
2. **易维护**:添加/删除IP无需重新编号
3. **更灵活**:支持分组管理不同类型的服务器
4. **标准化**YAML是业界标准的配置格式
5. **可视化**:彩色输出和实时进度提升用户体验
6. **智能化**:自动分析系统健康状态
## ⚠️ 注意事项
- 首次运行时会自动创建示例配置文件
- 如果 `config.yml` 不存在,会尝试加载旧的 `config.ini`
- 建议在修改配置后备份原文件
- Windows环境下colorama可能需要管理员权限才能正常显示颜色
## 🛠️ 故障排除
### 问题1颜色不显示
**解决**确保安装了colorama库
```bash
pip install colorama
```
### 问题2配置文件加载失败
**解决**检查YAML格式是否正确可以使用在线YAML验证器
### 问题3检测速度慢
**解决**增加max_workers参数值但注意不要超过50

40
Ping多多/config.ini Normal file
View File

@ -0,0 +1,40 @@
[IP_LIST]
# 每行一个IP地址可选添加注释使用 # 或 , 分隔)
10.10.14.220 # Oracle Rac节点1
10.10.14.222 # Oracle Rac存储节点IP冲突待调整
10.10.14.221 # Oracle Rac节点2IP冲突待调整
10.10.30.161 # 天融信3.5.6DELL R73088G+1.7T
10.10.30.215 # H3C CAS7.0X10主板128G+3.5T
10.10.14.203 # Cache 2016X9主板32G+2.5T
10.10.13.80 # 云宏8.2.2DELL R710(64G+480GB SSD+11TB)
10.10.30.45 # 浪潮虚拟化DELL R710(112G+4TB+24T)
10.10.13.2 # Linux代理Super Server主板128G+14TB+64TB
10.10.30.218 # MinioX9主板32G+48T后期可考虑报废
10.10.30.230 # 黑方规格三695测试黑方128G+48T
10.10.30.87 # Win 2012 R2环境X9主板64G+2T
10.10.9.32 # H3C UIS8.0X10主板128G+15T
10.10.14.205 # LinuxX9主板64G+4T
10.10.30.20 # SmartX 5.1.4DELL 730XD155G+14T
10.10.5.98 # HPUX
10.10.13.30 # ESXi 6.5计划搭建OpenStack环境
10.10.13.31 # ESXi 7.0计划搭建OpenStack环境
10.10.13.32 # ESXi 7.0计划搭建OpenStack环境
10.10.13.33 # 云祺6.0.5
10.10.50.232 # Windows2012R2
10.10.5.60 # SPARC Solaris
10.10.5.31 # SPARC Solaris
10.10.13.101 # 曙光云Xstor分布式存储
10.10.13.102 # 曙光云本地存储环境
10.10.13.103 # 曙光云ceph分布式存储
10.10.13.20 # 曙光云ceph分布式存储
10.10.14.218 # 深信服桌面云5.4版本,可搭建其他环境
10.10.0.100 # 小机 AIX
10.10.30.21 # 黑方规格二SmartX 5.1.464G+14T
10.10.25.27 # 华为虚拟化DELL 710144G+11T
10.10.30.22 # SmartX 5.1.4版本DELL 710112G+14T
10.10.14.207 # 华为虚拟化8.3.0X10主板64G+13T
# 可选参数
count = 2
timeout = 2
max_workers = 3

54
Ping多多/config.yml Normal file
View File

@ -0,0 +1,54 @@
# Ping多多配置文件 - YAML格式
# 每行一个IP地址冒号后添加注释可选
IP_LIST:
# Oracle Rac集群
10.10.14.220: "Oracle Rac节点1"
10.10.14.222: "Oracle Rac存储节点IP冲突待调整"
10.10.14.221: "Oracle Rac节点2IP冲突待调整"
# 虚拟化平台
10.10.30.161: "天融信3.5.6DELL R73088G+1.7T"
10.10.30.215: "H3C CAS7.0X10主板128G+3.5T"
10.10.13.80: "云宏8.2.2DELL R710(64G+480GB SSD+11TB)"
10.10.30.45: "浪潮虚拟化DELL R710(112G+4TB+24T)"
10.10.9.32: "H3C UIS8.0X10主板128G+15T"
10.10.14.218: "深信服桌面云5.4版本,可搭建其他环境"
10.10.25.27: "华为虚拟化DELL 710144G+11T"
10.10.14.207: "华为虚拟化8.3.0X10主板64G+13T"
# 存储系统
10.10.14.203: "Cache 2016X9主板32G+2.5T"
10.10.13.2: "Linux代理Super Server主板128G+14TB+64TB"
10.10.30.218: "MinioX9主板32G+48T后期可考虑报废"
10.10.13.101: "曙光云Xstor分布式存储"
10.10.13.102: "曙光云本地存储环境"
10.10.13.103: "曙光云ceph分布式存储"
10.10.13.20: "曙光云ceph分布式存储"
# 测试环境
10.10.30.230: "黑方规格三695测试黑方128G+48T"
10.10.30.87: "Win 2012 R2环境X9主板64G+2T"
10.10.30.20: "SmartX 5.1.4DELL 730XD155G+14T"
10.10.30.21: "黑方规格二SmartX 5.1.464G+14T"
10.10.30.22: "SmartX 5.1.4版本DELL 710112G+14T"
10.10.14.205: "vastbase"
# ESXi环境
10.10.13.30: "ESXi 6.5计划搭建OpenStack环境"
10.10.13.31: "ESXi 7.0计划搭建OpenStack环境"
10.10.13.32: "ESXi 7.0计划搭建OpenStack环境"
# 其他系统
10.10.13.33: "云祺6.0.5"
10.10.50.232: "Windows2012R2"
10.10.5.98: "HPUX"
10.10.5.60: "SPARC Solaris"
10.10.5.31: "SPARC Solaris"
10.10.0.100: "小机 AIX"
# 可选参数配置
SETTINGS:
count: 2 # ping次数
timeout: 2 # 超时时间(秒)
max_workers: 3 # 并发线程数

View File

@ -0,0 +1,170 @@
{
"timestamp": "2026-06-18 16:34:14",
"results": [
{
"ip": "10.10.14.222",
"status": "Fail",
"comment": "Oracle Rac存储节点IP冲突待调整"
},
{
"ip": "10.10.14.221",
"status": "Fail",
"comment": "Oracle Rac节点2IP冲突待调整"
},
{
"ip": "10.10.14.220",
"status": "Fail",
"comment": "Oracle Rac节点1"
},
{
"ip": "10.10.30.215",
"status": "Pass",
"comment": "H3C CAS7.0X10主板128G+3.5T"
},
{
"ip": "10.10.30.161",
"status": "Fail",
"comment": "天融信3.5.6DELL R73088G+1.7T"
},
{
"ip": "10.10.13.80",
"status": "Fail",
"comment": "云宏8.2.2DELL R710(64G+480GB SSD+11TB)"
},
{
"ip": "10.10.9.32",
"status": "Pass",
"comment": "H3C UIS8.0X10主板128G+15T"
},
{
"ip": "10.10.30.45",
"status": "Fail",
"comment": "浪潮虚拟化DELL R710(112G+4TB+24T)"
},
{
"ip": "10.10.14.207",
"status": "Pass",
"comment": "华为虚拟化8.3.0X10主板64G+13T"
},
{
"ip": "10.10.14.218",
"status": "Fail",
"comment": "深信服桌面云5.4版本,可搭建其他环境"
},
{
"ip": "10.10.25.27",
"status": "Fail",
"comment": "华为虚拟化DELL 710144G+11T"
},
{
"ip": "10.10.14.203",
"status": "Fail",
"comment": "Cache 2016X9主板32G+2.5T"
},
{
"ip": "10.10.13.2",
"status": "Fail",
"comment": "Linux代理Super Server主板128G+14TB+64TB"
},
{
"ip": "10.10.30.218",
"status": "Fail",
"comment": "MinioX9主板32G+48T后期可考虑报废"
},
{
"ip": "10.10.13.101",
"status": "Fail",
"comment": "曙光云Xstor分布式存储"
},
{
"ip": "10.10.13.102",
"status": "Fail",
"comment": "曙光云本地存储环境"
},
{
"ip": "10.10.13.103",
"status": "Fail",
"comment": "曙光云ceph分布式存储"
},
{
"ip": "10.10.30.230",
"status": "Pass",
"comment": "黑方规格三695测试黑方128G+48T"
},
{
"ip": "10.10.13.20",
"status": "Fail",
"comment": "曙光云ceph分布式存储"
},
{
"ip": "10.10.30.87",
"status": "Fail",
"comment": "Win 2012 R2环境X9主板64G+2T"
},
{
"ip": "10.10.30.20",
"status": "Fail",
"comment": "SmartX 5.1.4DELL 730XD155G+14T"
},
{
"ip": "10.10.30.21",
"status": "Fail",
"comment": "黑方规格二SmartX 5.1.464G+14T"
},
{
"ip": "10.10.14.205",
"status": "Pass",
"comment": "vastbase"
},
{
"ip": "10.10.30.22",
"status": "Fail",
"comment": "SmartX 5.1.4版本DELL 710112G+14T"
},
{
"ip": "10.10.13.30",
"status": "Fail",
"comment": "ESXi 6.5计划搭建OpenStack环境"
},
{
"ip": "10.10.13.31",
"status": "Fail",
"comment": "ESXi 7.0计划搭建OpenStack环境"
},
{
"ip": "10.10.13.32",
"status": "Fail",
"comment": "ESXi 7.0计划搭建OpenStack环境"
},
{
"ip": "10.10.13.33",
"status": "Fail",
"comment": "云祺6.0.5"
},
{
"ip": "10.10.50.232",
"status": "Fail",
"comment": "Windows2012R2"
},
{
"ip": "10.10.5.98",
"status": "Fail",
"comment": "HPUX"
},
{
"ip": "10.10.5.60",
"status": "Fail",
"comment": "SPARC Solaris"
},
{
"ip": "10.10.5.31",
"status": "Fail",
"comment": "SPARC Solaris"
},
{
"ip": "10.10.0.100",
"status": "Fail",
"comment": "小机 AIX"
}
]
}

View File

@ -1,80 +0,0 @@
#encoding=utf-8
import shutil
import sys
from pathlib import Path
class FileCopier:
def __init__(self):
self.path = Path.cwd()
self.file_path = self.path / 'file.txt'
self.dir_list = list(range(1, 61))
def init_dir(self):
"""初始化目录"""
for dir_num in self.dir_list:
dir_path = self.path / str(dir_num)
if dir_path.exists():
shutil.rmtree(dir_path)
dir_path.mkdir()
print("目录初始化完成")
def _copy_files(self, file_list):
"""复制文件到目录中"""
if not self.file_path.exists():
raise FileNotFoundError(f"源文件 {self.file_path} 不存在")
file_dir_map = dict(zip(file_list, self.dir_list))
success_count = 0
for file_num, dir_num in file_dir_map.items():
new_name = f'file_{file_num}.txt'
target_path = self.path / str(dir_num) / new_name
try:
shutil.copyfile(self.file_path, target_path)
success_count += 1
except Exception as e:
print(f"复制文件 {file_num} 到目录 {dir_num} 失败: {e}")
print(f"成功复制 {success_count} 个文件")
def copy_odd(self):
"""复制奇数文件"""
file_list = list(range(1, 121, 2))
print(f"开始复制 {len(file_list)} 个奇数文件...")
self._copy_files(file_list)
def copy_even(self):
"""复制偶数文件"""
file_list = list(range(2, 121, 2))
print(f"开始复制 {len(file_list)} 个偶数文件...")
self._copy_files(file_list)
def main():
"""主函数"""
if len(sys.argv) != 2:
print("用法: python copy_files.py [init|js|os]")
print(" init - 初始化目录")
print(" js - 复制奇数文件")
print(" os - 复制偶数文件")
sys.exit(1)
command = sys.argv[1].lower()
copier = FileCopier()
try:
if command == 'init':
copier.init_dir()
elif command == 'js':
copier.copy_odd()
elif command == 'os':
copier.copy_even()
else:
print(f"错误: 未知命令 '{command}'")
print("请使用 init, js 或 os")
sys.exit(1)
except Exception as e:
print(f"执行失败: {e}")
sys.exit(1)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
"""
文件复制工具将源文件按奇/偶数编号复制到多个目录中
用法:
python copy_files.py init # 初始化目录
python copy_files.py odd # 复制奇数编号文件 (1,3,5,...,119)
python copy_files.py even # 复制偶数编号文件 (2,4,6,...,120)
python copy_files.py clean # 清理生成的目录和源文件
兼容旧命令: js(=odd) / os(=even)
"""
import argparse
import shutil
import sys
from pathlib import Path
# ===== 配置参数(可按需调整)=====
TOTAL_FILES = 120 # 文件总数 (1~120)
TOTAL_DIRS = 60 # 目标目录数 (1~60)
SOURCE_FILE = 'file.txt' # 源文件名
SOURCE_FILE_SIZE = 1*1024 * 1024 # 源文件不存在时自动生成的大小(字节,默认 1MB
class FileCopier:
def __init__(self, ensure_source=True):
self.path = Path.cwd()
self.file_path = self.path / SOURCE_FILE
self.dir_list = list(range(1, TOTAL_DIRS + 1))
# clean 等清理操作不需要生成源文件
if ensure_source:
self._ensure_source_file()
def _ensure_source_file(self):
"""确保源文件存在:不存在则自动生成一个指定大小的占位文件。"""
if self.file_path.exists():
return
with self.file_path.open('wb') as f:
# 一次性写入全零字节,速度快且兼容大文件场景
f.write(b'\0' * SOURCE_FILE_SIZE)
print(f"源文件不存在,已自动生成 {self.file_path.name}{SOURCE_FILE_SIZE // 1024}KB")
def init_dir(self):
"""初始化目录:删除已存在的同名目录后重新创建。"""
for dir_num in self.dir_list:
dir_path = self.path / str(dir_num)
if dir_path.exists():
shutil.rmtree(dir_path)
dir_path.mkdir(parents=True)
print(f"已初始化 {len(self.dir_list)} 个目录")
def clean(self):
"""清理删除所有生成的目录1~60及源文件。"""
removed_dirs = 0
for dir_num in self.dir_list:
dir_path = self.path / str(dir_num)
if dir_path.exists():
shutil.rmtree(dir_path)
removed_dirs += 1
# 删除源文件
if self.file_path.exists():
self.file_path.unlink()
print(f"已删除源文件 {self.file_path.name}")
print(f"已清理 {removed_dirs} 个目录")
def _copy_files(self, file_list):
"""将源文件复制到各目录,文件名格式为 file_<编号>.txt。"""
# 源文件已在 __init__ 时确保存在;此处再校验以防外部删除
if not self.file_path.exists():
raise FileNotFoundError(f"源文件 {self.file_path} 不存在")
# 按顺序将文件分配到目录file_list[i] -> dir_list[i]
file_dir_map = dict(zip(file_list, self.dir_list))
success_count = 0
for file_num, dir_num in file_dir_map.items():
target_path = self.path / str(dir_num) / f"file_{file_num}.txt"
try:
shutil.copyfile(self.file_path, target_path)
success_count += 1
except Exception as e:
print(f"复制文件 {file_num} 到目录 {dir_num} 失败: {e}")
print(f"成功复制 {success_count}/{len(file_list)} 个文件")
def copy_odd(self):
"""复制奇数编号文件 (1,3,5,...,119)。"""
file_list = list(range(1, TOTAL_FILES + 1, 2))
print(f"开始复制 {len(file_list)} 个奇数文件...")
self._copy_files(file_list)
def copy_even(self):
"""复制偶数编号文件 (2,4,6,...,120)。"""
file_list = list(range(2, TOTAL_FILES + 1, 2))
print(f"开始复制 {len(file_list)} 个偶数文件...")
self._copy_files(file_list)
def main():
parser = argparse.ArgumentParser(
description='文件复制工具:按奇/偶数编号复制源文件到多个目录',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="兼容旧命令: js(=odd 奇数) / os(=even 偶数)"
)
parser.add_argument(
'command',
choices=['init', 'odd', 'even', 'clean', 'js', 'os'],
help='init: 初始化目录; odd/js: 复制奇数文件; even/os: 复制偶数文件; clean: 清理目录和源文件'
)
args = parser.parse_args()
# clean 命令不需要自动生成源文件
copier = FileCopier(ensure_source=(args.command != 'clean'))
try:
if args.command == 'init':
copier.init_dir()
elif args.command in ('odd', 'js'):
copier.copy_odd()
elif args.command in ('even', 'os'):
copier.copy_even()
elif args.command == 'clean':
copier.clean()
except Exception as e:
print(f"执行失败: {e}")
sys.exit(1)
if __name__ == '__main__':
main()