exp操作错误 map : Permission Denied

解决Oracle安装后权限问题
本文详细阐述了在安装Oracle10.2.0后遇到的Unix权限问题,特别是ORACLE_HOME目录下文件和目录无法被除安装用户外的其他用户访问的问题。提供了解决方案,包括使用root用户修改权限,确保所有目录的权限正确设置,避免违反安全策略。
从应用服务器导出数据库服务器的数据库dump,提示错误:


map : Permission Denied
分段错误


查相关文档:
Unix permissions problem under ORACLE_HOME
Apparently this is a known Oracle bug, after installing Oracle 10.2.0 Unix permissions underORACLE_HOME are not set correctly, so directories and files are accessible to theinstallation user and group (i.e. oracle:dba) but not to the reset of the world (others). Ifyou get any of the following errors the problem may be caused by this permissions bug.$ sqlplus /ld.so.1: sqlplus: fatal: /apps/oracle/product/10.2.0/db_1/lib/libclntsh.so.10.1: PermissiondeniedDid you set the permissions on the whole directory or just that one library?$ sqlplus /Error 6 initializing SQL*PlusMessage file sp1<lang>.msb not foundSP2-0750: You may need to set ORACLE_HOME to your Oracle software directory$ sqlplus /SP2-1503: Unable to initialize Oracle call interfaceSP2-0152: ORACLE may not be functioning properlyOne way to fix this is to run:$ chmod -R o=g $ORACLE_HOMEHowever, make sure this doesn not violate your security policy.

所以使用root用户,执行#chmod -R o=g $ORACLE_HOME
V27960021@dg03podv27960021kj4p:~/存储/casio/24608/存储2$ python storage.py dual ./测试 ./对比 24608_report_dual.xlsx --is-os-project --upgrade-generations 2 --maintenance-generations 1 --reserve-per-generation 2.2 运行双机对比模式... 处理目录: ./测试 解析主分区文件: ./测试/18_system_ext.txt 解析主分区文件: ./测试/05_odm.txt 解析主分区文件: ./测试/14_data.txt 解析主分区文件: ./测试/17_vendor_dlkm.txt 解析主分区文件: ./测试/17_system_dlkm.txt 解析主分区文件: ./测试/10_my_company.txt 解析主分区文件: ./测试/11_my_carrier.txt 解析主分区文件: ./测试/15_my_bigball.txt 解析主分区文件: ./测试/09_my_heytap.txt 解析主分区文件: ./测试/04_product.txt 解析主分区文件: ./测试/02_system.txt 解析主分区文件: ./测试/17_cache.txt 解析主分区文件: ./测试/16_my_manifest.txt 解析主分区文件: ./测试/03_vendor.txt 解析主分区文件: ./测试/06_my_product.txt 解析主分区文件: ./测试/12_my_region.txt 解析主分区文件: ./测试/08_my_stock.txt 解析主分区文件: ./测试/07_my_engineering.txt 解析主分区文件: ./测试/13_my_preload.txt 处理目录: ./对比 解析主分区文件: ./对比/18_system_ext.txt 解析主分区文件: ./对比/05_odm.txt 解析主分区文件: ./对比/14_data.txt 解析主分区文件: ./对比/17_vendor_dlkm.txt 解析主分区文件: ./对比/17_system_dlkm.txt 解析主分区文件: ./对比/10_my_company.txt 解析主分区文件: ./对比/11_my_carrier.txt 解析主分区文件: ./对比/15_my_bigball.txt 解析主分区文件: ./对比/09_my_heytap.txt 解析主分区文件: ./对比/04_product.txt 解析主分区文件: ./对比/02_system.txt 解析主分区文件: ./对比/17_cache.txt 解析主分区文件: ./对比/16_my_manifest.txt 解析主分区文件: ./对比/03_vendor.txt 解析主分区文件: ./对比/06_my_product.txt 解析主分区文件: ./对比/12_my_region.txt 解析主分区文件: ./对比/08_my_stock.txt 解析主分区文件: ./对比/07_my_engineering.txt 解析主分区文件: ./对比/13_my_preload.txt 创建总览Sheet页(仅主分区文件) 写入总览页: system, 测试机大小: 929.00 MB, 对比机大小: 788.00 MB 写入总览页: vendor, 测试机大小: 1227.00 MB, 对比机大小: 1218.00 MB 写入总览页: product, 测试机大小: 2.00 MB, 对比机大小: 3.00 MB 写入总览页: odm, 测试机大小: 1777.00 MB, 对比机大小: 1749.00 MB 写入总览页: my_product, 测试机大小: 1203.00 MB, 对比机大小: 598.00 MB 写入总览页: my_engineering, 测试机大小: 0.00 MB, 对比机大小: 0.00 MB 写入总览页: my_stock, 测试机大小: 3856.00 MB, 对比机大小: 3671.00 MB 写入总览页: my_heytap, 测试机大小: 0.00 MB, 对比机大小: 0.00 MB 写入总览页: my_company, 测试机大小: 0.00 MB, 对比机大小: 0.00 MB 写入总览页: my_carrier, 测试机大小: 0.00 MB, 对比机大小: 0.00 MB 写入总览页: my_region, 测试机大小: 3.00 MB, 对比机大小: 3.00 MB 写入总览页: my_preload, 测试机大小: 1718.00 MB, 对比机大小: 1674.00 MB 写入总览页: my_bigball, 测试机大小: 0.00 MB, 对比机大小: 319.00 MB 写入总览页: my_manifest, 测试机大小: 0.00 MB, 对比机大小: 0.00 MB 写入总览页: cache, 测试机大小: 0.00 MB, 对比机大小: 0.00 MB 写入总览页: system_dlkm, 测试机大小: 6.00 MB, 对比机大小: 6.00 MB 写入总览页: vendor_dlkm, 测试机大小: 21.00 MB, 对比机大小: 18.00 MB 写入总览页: system_ext, 测试机大小: 1266.00 MB, 对比机大小: 1288.00 MB 创建文件Sheet页: 02_system 创建文件Sheet页: 02_system_apex 创建文件Sheet页: 02_system_app 创建文件Sheet页: 02_system_app_oat 创建文件Sheet页: 02_system_etc 创建文件Sheet页: 02_system_fonts 创建文件Sheet页: 02_system_framework 创建文件Sheet页: 02_system_lib 创建文件Sheet页: 02_system_lib64 创建文件Sheet页: 02_system_priv-app 创建文件Sheet页: 02_system_priv_app_oat 创建文件Sheet页: 02_system_product 创建文件Sheet页: 02_system_xiangxi 创建文件Sheet页: 03_vendor 创建文件Sheet页: 03_vendor_app 创建文件Sheet页: 03_vendor_bin 创建文件Sheet页: 03_vendor_etc 创建文件Sheet页: 03_vendor_etc_camera 创建文件Sheet页: 03_vendor_euclid 创建文件Sheet页: 03_vendor_firmware_mnt 创建文件Sheet页: 03_vendor_firmware_mnt_image 创建文件Sheet页: 03_vendor_lib 创建文件Sheet页: 03_vendor_lib64 创建文件Sheet页: 03_vendor_lib64_camera 创建文件Sheet页: 03_vendor_lib_camera 创建文件Sheet页: 03_vendor_xiangxi 创建文件Sheet页: 04_product 创建文件Sheet页: 04_product_app 创建文件Sheet页: 04_product_app_oat 创建文件Sheet页: 04_product_lib 创建文件Sheet页: 04_product_lib64 创建文件Sheet页: 04_product_priv_app 创建文件Sheet页: 04_product_priv_app_oat 创建文件Sheet页: 04_product_xiangxi 创建文件Sheet页: 05_odm 创建文件Sheet页: 05_odm_bin 创建文件Sheet页: 05_odm_etc 创建文件Sheet页: 05_odm_lib 创建文件Sheet页: 05_odm_lib64 创建文件Sheet页: 05_odm_product 创建文件Sheet页: 05_odm_product_lib 创建文件Sheet页: 05_odm_product_lib64 创建文件Sheet页: 05_odm_vendor 创建文件Sheet页: 05_odm_vendor_firmware 创建文件Sheet页: 05_odm_xiangxi 创建文件Sheet页: 06_my_product 创建文件Sheet页: 06_my_product_app 创建文件Sheet页: 06_my_product_decouping_wallpap 创建文件Sheet页: 06_my_product_etc 创建文件Sheet页: 06_my_product_media 创建文件Sheet页: 06_my_product_overlay 创建文件Sheet页: 06_my_product_priv_app 创建文件Sheet页: 06_my_product_res 创建文件Sheet页: 06_my_product_vendor 创建文件Sheet页: 06_my_product_xiangxi 创建文件Sheet页: 07_my_engineering 创建文件Sheet页: 07_my_engineering_app 创建文件Sheet页: 07_my_engineering_decouping_wal 创建文件Sheet页: 07_my_engineering_etc 创建文件Sheet页: 07_my_engineering_media 创建文件Sheet页: 07_my_engineering_overlay 创建文件Sheet页: 07_my_engineering_res 创建文件Sheet页: 07_my_engineering_vendor 创建文件Sheet页: 07_my_engineering_xiangxi 创建文件Sheet页: 08_my_stock 创建文件Sheet页: 08_my_stock_app 创建文件Sheet页: 08_my_stock_app_oat 创建文件Sheet页: 08_my_stock_del_app 创建文件Sheet页: 08_my_stock_del_app_oat 创建文件Sheet页: 08_my_stock_priv_app 创建文件Sheet页: 08_my_stock_priv_app_oat 创建文件Sheet页: 08_my_stock_xiangxi 创建文件Sheet页: 09_my_heytap 创建文件Sheet页: 09_my_heytap_app 创建文件Sheet页: 09_my_heytap_app_oat 创建文件Sheet页: 09_my_heytap_del_app 创建文件Sheet页: 09_my_heytap_del_app_oat 创建文件Sheet页: 09_my_heytap_priv_app 创建文件Sheet页: 09_my_heytap_priv_app_oat 创建文件Sheet页: 09_my_heytap_xiangxi 创建文件Sheet页: 10_my_company 创建文件Sheet页: 10_my_company_app 创建文件Sheet页: 10_my_company_etc 创建文件Sheet页: 10_my_company_xiangxi 创建文件Sheet页: 11_my_carrier 创建文件Sheet页: 11_my_carrier_app 创建文件Sheet页: 11_my_carrier_app_oat 创建文件Sheet页: 11_my_carrier_del_app 创建文件Sheet页: 11_my_carrier_del_app_oat 创建文件Sheet页: 11_my_carrier_priv_app 创建文件Sheet页: 11_my_carrier_priv_app_oat 创建文件Sheet页: 11_my_carrier_xiangxi 创建文件Sheet页: 12_my_region 创建文件Sheet页: 12_my_region_app 创建文件Sheet页: 12_my_region_app_oat 创建文件Sheet页: 12_my_region_del_app 创建文件Sheet页: 12_my_region_del_app_oat 创建文件Sheet页: 12_my_region_etc 创建文件Sheet页: 12_my_region_etc_camera 创建文件Sheet页: 12_my_region_media 创建文件Sheet页: 12_my_region_plugin 创建文件Sheet页: 12_my_region_priv_app 创建文件Sheet页: 12_my_region_priv_app_oat 创建文件Sheet页: 12_my_region_xiangxi 创建文件Sheet页: 13_my_manifest 创建文件Sheet页: 13_my_manifest_app 创建文件Sheet页: 13_my_manifest_etc 创建文件Sheet页: 13_my_manifest_etc_camera 创建文件Sheet页: 13_my_manifest_xiangxi 创建文件Sheet页: 13_my_preload 创建文件Sheet页: 13_my_preload_app 创建文件Sheet页: 13_my_preload_app_oat 创建文件Sheet页: 13_my_preload_del_app 创建文件Sheet页: 13_my_preload_del_app_oat 创建文件Sheet页: 13_my_preload_etc 创建文件Sheet页: 13_my_preload_priv_app 创建文件Sheet页: 13_my_preload_priv_app_oat 创建文件Sheet页: 13_my_preload_xiangxi 创建文件Sheet页: 14_data 创建文件Sheet页: 14_data_aee_exp 创建文件Sheet页: 14_data_apex 创建文件Sheet页: 14_data_app 创建文件Sheet页: 14_data_app_oat 创建文件Sheet页: 14_data_dalvik-cache 创建文件Sheet页: 14_data_data 创建文件Sheet页: 14_data_del_app 创建文件Sheet页: 14_data_local 创建文件Sheet页: 14_data_media 创建文件Sheet页: 14_data_media_0 创建文件Sheet页: 14_data_misc 创建文件Sheet页: 14_data_nandswap 创建文件Sheet页: 14_data_reserve 创建文件Sheet页: 14_data_user_de 创建文件Sheet页: 15_my_bigball 创建文件Sheet页: 15_my_bigball_app 创建文件Sheet页: 15_my_bigball_applist 创建文件Sheet页: 15_my_bigball_decouping_wallpap 创建文件Sheet页: 15_my_bigball_del-app-pre 创建文件Sheet页: 15_my_bigball_del-app 创建文件Sheet页: 15_my_bigball_etc 创建文件Sheet页: 15_my_bigball_framework 创建文件Sheet页: 15_my_bigball_lib 创建文件Sheet页: 15_my_bigball_lib64 创建文件Sheet页: 15_my_bigball_plugin 创建文件Sheet页: 15_my_bigball_priv-app 创建文件Sheet页: 16_my_manifest 创建文件Sheet页: 16_my_manifest_etc 创建文件Sheet页: 17_cache 创建文件Sheet页: 17_system_dlkm 创建文件Sheet页: 17_vendor_dlkm 创建文件Sheet页: 18_lpdump 创建文件Sheet页: 18_system_ext 创建文件Sheet页: 18_system_ext_app 创建文件Sheet页: 18_system_ext_etc 创建文件Sheet页: 18_system_ext_lib 创建文件Sheet页: 18_system_ext_lib64 创建文件Sheet页: 18_system_ext_media 创建文件Sheet页: 18_system_ext_priv_app 创建文件Sheet页: 18_system_ext_xiangxi 对比报告已成功生成: 24608_report_dual.xlsx #!/usr/bin/env python # -*- coding: utf-8 -*- import os import re import sys import argparse import xlwt from collections import defaultdict # 分区名称映射表(前缀 → 友好名称) PARTITION_NAME_MAP = { '02_': 'system', '03_': 'vendor', '04_': 'product', '05_': 'odm', '06_': 'my_product', '07_': 'my_engineering', '08_': 'my_stock', '09_': 'my_heytap', '10_': 'my_company', '11_': 'my_carrier', '12_': 'my_region', '13_': 'my_preload', '14_': 'data', '15_': 'my_bigball', '16_': 'my_manifest', '17_system_dlkm': 'system_dlkm', '17_vendor_dlkm': 'vendor_dlkm', '17_cache': 'cache', '18_': 'system_ext' } def parse_du_file(file_path): """解析du命令输出文件并转换为MB""" data = {} try: with open(file_path, 'r') as f: for line in f: if 'Permission denied' in line or 'No such file' in line or not line.strip(): continue match = re.match(r'(\d+\.?\d*)\s*([KMG]?)[Bb]?\s+(.*)', line.strip()) if match: size, unit, path = match.groups() size = float(size) # 单位转换到MB if unit == 'K': size = size / 1024.0 elif unit == '': size = size / (1024 * 1024.0) elif unit == 'M': pass elif unit == 'G': size = size * 1024.0 data[path] = round(size, 4) except IOError as e: print("警告: 无法读取文件 {}: {}".format(file_path, str(e))) return data def extract_file_prefix(filename): """提取文件前缀""" if filename.startswith('17_'): return filename.replace('.txt', '') match = re.match(r'^(\d+_)', filename) return match.group(1) if match else "other_" def is_main_partition_file(filename, prefix): """检查是否为主分区文件""" if prefix.startswith('17_'): return True expected_name = prefix + PARTITION_NAME_MAP[prefix] + ".txt" return filename == expected_name def parse_lpdump_file(file_path): """解析 lpdump 输出文件,获取各分区大小和super物理分区大小""" sector_size = 512 # 每个扇区大小为 512 字节 partition_sizes = {} try: with open(file_path, 'r') as f: lines = f.readlines() in_super_layout = False super_size = 0.0 # 初始化super物理分区大小 for line in lines: if "Super partition layout:" in line: in_super_layout = True continue if not in_super_layout or not line.strip(): continue if line.startswith("Size:"): try: size_bytes = int(line.split()[1]) super_size = size_bytes / float(1024 * 1024) # 转换为 MB print ("super 分区大小:%.2f MB" % super_size) except Exception as e: print ("无法解析 super 分区大小:%s" % str(e)) continue match = re.search(r'super:\s*(\d+)\s*.. (\d+):\s*([a-zA-Z0-9_]+)_a\s*\((\d+)\s+sectors\)', line) if match: name = match.group(3) + '_a' size_sectors = int(match.group(4)) # 直接使用括号内的数值 size_mb = round(size_sectors * sector_size / (1024 * 1024), 4) partition_sizes[name] = size_mb # 特别提取 super 分区的大小 if name == 'super_a': super_size = size_mb except Exception as e: print("解析 lpdump 文件出错: %s" % e) return partition_sizes, super_size def generate_dual_report(folder1, folder2, output_xlsx, is_os_project, upgrade_generations, maintenance_generations, reserve_per_generation, commercial_max_usage): """生成双机对比报告""" folder1_name = os.path.basename(os.path.normpath(folder1)) folder2_name = os.path.basename(os.path.normpath(folder2)) for folder in [folder1, folder2]: if not os.path.exists(folder): print("错误: 目录不存在 - %s" % folder) return "目录 %s 不存在,请检查路径" % folder if not os.path.isdir(folder): print("错误: 路径不是目录 - %s" % folder) return "%s 不是有效目录" % folder # 初始化数据结构 machine1_main_data = {} machine2_main_data = {} machine1_all_files = defaultdict(dict) machine2_all_files = defaultdict(dict) # 新增:解析 lpdump 文件 machine1_lpdump, machine1_super_size = parse_lpdump_file(os.path.join(folder1, '18_lpdump.txt')) machine2_lpdump, machine2_super_size = parse_lpdump_file(os.path.join(folder2, '18_lpdump.txt')) # 收集数据 for folder_path, main_dict, all_dict in [ (folder1, machine1_main_data, machine1_all_files), (folder2, machine2_main_data, machine2_all_files) ]: print("处理目录: %s" % folder_path) try: for filename in os.listdir(folder_path): if not filename.endswith('.txt'): continue prefix = extract_file_prefix(filename) if prefix == '01_' or prefix not in PARTITION_NAME_MAP: continue file_path = os.path.join(folder_path, filename) partition_name = PARTITION_NAME_MAP[prefix] file_data = parse_du_file(file_path) all_dict[filename] = file_data if is_main_partition_file(filename, prefix): print("解析主分区文件: %s" % file_path) main_dict[prefix] = file_data except OSError as e: print("目录访问错误: %s" % str(e)) return "无法访问目录 %s: %s" % (folder_path, str(e)) # 创建Excel工作簿 try: wb = xlwt.Workbook(encoding='utf-8') # ====== 定义样式变量 ====== header_style = xlwt.easyxf('font: bold on') title_style = xlwt.easyxf('font: bold on, height 280; align: wrap on, vert centre') normal_style = xlwt.easyxf() added_style = xlwt.easyxf('pattern: pattern solid, fore_colour light_green;') removed_style = xlwt.easyxf('pattern: pattern solid, fore_colour rose;') summary_style = xlwt.easyxf('font: bold on, color blue;') wrap_style = xlwt.easyxf('align: wrap on, vert centre') # 备注列样式 # ====== 创建总览Sheet页 ====== ws_overview = wb.add_sheet('总览') print("创建总览Sheet页(仅主分区文件)") current_row = 0 # 写入总览标题 ws_overview.write_merge( current_row, current_row, 0, 5, "存储使用总览(仅主分区文件)", title_style ) current_row += 1 # 写入文件夹名称 ws_overview.write(current_row, 1, folder1_name, header_style) ws_overview.write(current_row, 2, folder2_name, header_style) current_row += 1 # 写入表头(增加备注列) headers = ['分区', '总大小(MB)', '总大小(MB)', '差值(MB)', '标记', '备注(增大TOP3)'] for col, header in enumerate(headers): ws_overview.write(current_row, col, header, header_style) current_row += 1 # 存储各分区汇总数据 overview_data = [] total_machine1 = 0.0 total_machine2 = 0.0 # 按分区顺序处理数据 for prefix in sorted(PARTITION_NAME_MAP.keys()): partition_name = PARTITION_NAME_MAP[prefix] # 跳过data分区 if partition_name == 'data': continue # 使用 lpdump 提供的大小替代原来的 du 总和 key = partition_name + '_a' size1 = machine1_lpdump.get(key, 0.0) size2 = machine2_lpdump.get(key, 0.0) diff = round(size1 - size2, 4) # 更新总计 total_machine1 += size1 total_machine2 += size2 # 确定标记样式 if diff > 0: mark = "增加" style = added_style elif diff < 0: mark = "减少" style = removed_style else: mark = "无变化" style = normal_style # 计算分区中增大的大于5MB的路径 top_notes = [] if diff > 0: # 只在分区增大时计算TOP路径 path_diffs = [] all_paths = set(machine1_main_data.get(prefix, {}).keys()) | set(machine2_main_data.get(prefix, {}).keys()) for path in all_paths: size1_path = machine1_main_data.get(prefix, {}).get(path, 0.0) size2_path = machine2_main_data.get(prefix, {}).get(path, 0.0) path_diff = size1_path - size2_path if path_diff > 5: # 只记录增大小于5MB的路径 path_diffs.append((path, path_diff)) # 按增大值降序排序 path_diffs.sort(key=lambda x: x[1], reverse=True) for i, (path, diff_val) in enumerate(path_diffs): # 截断过长的路径名 if len(path) > 50: path = "..." + path[-47:] top_notes.append("%d. %s: +%.2fMB" % (i+1, path, diff_val)) # 保存分区数据 overview_data.append({ 'name': partition_name, 'machine1': size1, 'machine2': size2, 'diff': diff, 'style': style, 'mark': mark, 'notes': "\n".join(top_notes) if top_notes else "无显著增大路径" }) # 写入行数据到总览页(增加备注列) print("写入总览页: %s, 测试机大小: %.2f MB, 对比机大小: %.2f MB" % (partition_name, size1, size2)) # 调试输出 ws_overview.write(current_row, 0, partition_name, style) ws_overview.write(current_row, 1, size1, style) ws_overview.write(current_row, 2, size2, style) ws_overview.write(current_row, 3, diff, style) ws_overview.write(current_row, 4, mark, style) ws_overview.write(current_row, 5, overview_data[-1]['notes'], wrap_style) # 使用已定义的wrap_style current_row += 1 # 添加空行 current_row += 1 # 写入总计行 total_diff = total_machine1 - total_machine2 if total_diff > 0: total_mark = "总增加" total_style = added_style elif total_diff < 0: total_mark = "总减少" total_style = removed_style else: total_mark = "无变化" total_style = normal_style ws_overview.write(current_row, 0, "总计", header_style) ws_overview.write(current_row, 1, total_machine1, header_style) ws_overview.write(current_row, 2, total_machine2, header_style) ws_overview.write(current_row, 3, total_diff, header_style) ws_overview.write(current_row, 4, total_mark, header_style) ws_overview.write(current_row, 5, "", header_style) # 备注列留空 # 判断是否满足预留条件 current_row += 1 if is_os_project: reserved_space = total_machine1 + upgrade_generations * reserve_per_generation + maintenance_generations * 200 - commercial_max_usage*1024 else: reserved_space = total_machine1 + upgrade_generations * reserve_per_generation + maintenance_generations * 200 if reserved_space > machine1_super_size: status = "不满足" status_style = removed_style else: status = "满足" status_style = added_style # 写入判断结果 ws_overview.write(current_row, 0, "预留判断", header_style) ws_overview.write(current_row, 1, "", normal_style) ws_overview.write(current_row, 2, "", normal_style) ws_overview.write(current_row, 3, "", normal_style) ws_overview.write(current_row, 4, status, status_style) ws_overview.write(current_row, 5, "当前占用: %.2fMB | 预留空间: %.2fMB | Super大小: %.2fMB" % (total_machine1, reserved_space, machine1_super_size), wrap_style) # 设置备注列宽度(100字符) ws_overview.col(5).width = 256 * 100 # ====== 为每个文件创建单独的Sheet页(保持不变) ====== # 获取所有唯一的文件名(两个文件夹的并集) all_filenames = sorted(set(machine1_all_files.keys()) | set(machine2_all_files.keys())) for filename in all_filenames: # 提取文件前缀 prefix = extract_file_prefix(filename) # 跳过无效前缀 if prefix not in PARTITION_NAME_MAP: continue # 获取分区名称 partition_name = PARTITION_NAME_MAP[prefix] # 创建Sheet页名称(文件名不带扩展名) sheet_name = filename.replace('.txt', '') if len(sheet_name) > 31: # Excel sheet名称长度限制 sheet_name = sheet_name[:31] # 创建Sheet页 ws = wb.add_sheet(sheet_name) print("创建文件Sheet页: %s" % sheet_name) # 当前行指针 current_row = 0 # 写入分区标题 title = "分区: %s - 文件: %s" % (partition_name, filename) ws.write_merge( current_row, current_row, 0, 5, title, title_style ) current_row += 1 # 写入文件夹名称 ws.write_merge(current_row, current_row, 0, 1, folder1_name, header_style) ws.write_merge(current_row, current_row, 2, 3, folder2_name, header_style) ws.write(current_row, 4, "差异(M)", header_style) ws.write(current_row, 5, "标记", header_style) current_row += 1 # 写入表头 headers = ['路径', '大小(M)', '路径', '大小(M)', '差异(M)', '标记'] for col, header in enumerate(headers): ws.write(current_row, col, header, header_style) current_row += 1 # 获取文件数据 data1 = machine1_all_files.get(filename, {}) data2 = machine2_all_files.get(filename, {}) # 获取所有路径(合并两个文件夹的路径) all_paths = sorted(set(data1.keys()) | set(data2.keys())) # 初始化变化统计数据 total_increase = 0.0 # 增大总和 total_decrease = 0.0 # 减小总和 total_added = 0.0 # 新增文件总和 total_removed = 0.0 # 去除文件总和 # 写入数据行 for path in all_paths: size1 = data1.get(path, 0.0) size2 = data2.get(path, 0.0) # 计算差值 diff = size1 - size2 # 确定标记和样式 if size1 == 0 and size2 > 0: mark = "除去" cell_style = removed_style total_removed += size2 elif size1 > 0 and size2 == 0: mark = "新增" cell_style = added_style total_added += size1 else: if diff > 0: mark = "增大" cell_style = added_style total_increase += diff elif diff < 0: mark = "减小" cell_style = removed_style total_decrease += abs(diff) else: mark = "相同" cell_style = normal_style # 写入行数据 # folder1列 if size1 > 0: ws.write(current_row, 0, path, cell_style) ws.write(current_row, 1, size1, cell_style) else: ws.write(current_row, 0, "", cell_style) ws.write(current_row, 1, "", cell_style) # folder2列 if size2 > 0: ws.write(current_row, 2, path, cell_style) ws.write(current_row, 3, size2, cell_style) else: ws.write(current_row, 2, "", cell_style) ws.write(current_row, 3, "", cell_style) # 差异和标记列 ws.write(current_row, 4, diff, cell_style) ws.write(current_row, 5, mark, cell_style) current_row += 1 # 添加文件汇总行 file_total1 = sum(data1.values()) file_total2 = sum(data2.values()) file_diff = file_total1 - file_total2 # 写入汇总行 ws.write(current_row, 0, "文件汇总", header_style) ws.write(current_row, 1, file_total1, header_style) ws.write(current_row, 2, "", header_style) ws.write(current_row, 3, file_total2, header_style) ws.write(current_row, 4, file_diff, header_style) ws.write(current_row, 5, "", header_style) current_row += 1 # 添加变化分类统计行 message = ( u"%s路径下: " u"减小%.2fM " u"增大%.2fM " u"新增文件%.2fM " u"减少文件%.2fM" ) % ( partition_name, total_decrease, total_increase, total_added, total_removed ) ws.write_merge( current_row, current_row, 0, 5, message, summary_style ) # 保存文件 wb.save(output_xlsx) return "对比报告已成功生成: %s" % output_xlsx except Exception as e: import traceback traceback.print_exc() return "生成Excel文件时出错: %s" % str(e) # 单机拆解模式保持不变 def generate_single_report(folder, output_xlsx): """单机拆解模式(保持不变)""" # ...(原有单机拆解模式实现)... if __name__ == "__main__": # 创建参数解析器 parser = argparse.ArgumentParser(description='存储空间分析工具') subparsers = parser.add_subparsers(dest='mode', help='运行模式') # 双机对比模式 dual_parser = subparsers.add_parser('dual', help='双机对比模式') dual_parser.add_argument('folder1', help='第一个文件夹路径') dual_parser.add_argument('folder2', help='第二个文件夹路径') dual_parser.add_argument('output', help='输出Excel文件路径') dual_parser.add_argument('--is-os-project', action='store_true', default=False, help='是否是OS项目') dual_parser.add_argument('--upgrade-generations', type=int, default=0, help='升级代数') dual_parser.add_argument('--maintenance-generations', type=int, default=0, help='维护代数') dual_parser.add_argument('--reserve-per-generation', type=float, default=0, help='每代预留大小 (单位MB)') dual_parser.add_argument('--commercial-max-usage', type=float, default=0, help='商业化历史最大占用 (单位MB)') # 单机拆解模式 single_parser = subparsers.add_parser('single', help='单机拆解模式') single_parser.add_argument('folder', help='待分析文件夹路径') single_parser.add_argument('output', help='输出Excel文件路径') # 解析参数 args = parser.parse_args() if args.mode == 'dual': print("运行双机对比模式...") result = generate_dual_report( args.folder1, args.folder2, args.output, is_os_project=args.is_os_project, upgrade_generations=args.upgrade_generations, maintenance_generations=args.maintenance_generations, reserve_per_generation=args.reserve_per_generation, commercial_max_usage=args.commercial_max_usage ) elif args.mode == 'single': print("运行单机拆解模式...") result = generate_single_report(args.folder, args.output) else: result = "错误:请选择 'dual' 或 'single' 模式" print(result) super分区大小还是0 ,预留判断 不满足 当前占用: 12008.00MB | 预留空间: 12212.40MB | Super大小: 0.00MB
最新发布
11-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值