add ntfsfix
This commit is contained in:
231
build.sh
231
build.sh
@@ -1,164 +1,113 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# Linux 存储管理器 - PyInstaller 打包脚本
|
# Linux 存储管理器 - PyInstaller 打包脚本 (简化版)
|
||||||
# 自动安装依赖并打包应用程序
|
# 直接打包,仅保留 dist 目录中的最终文件
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
||||||
echo "║ Linux 存储管理器 - PyInstaller 打包工具 ║"
|
|
||||||
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 检查 Python3
|
|
||||||
if ! command -v python3 &> /dev/null; then
|
|
||||||
echo "✗ 错误: 未找到 python3"
|
|
||||||
echo " 请先安装 Python 3.6+"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
|
||||||
echo " Python 版本: $PYTHON_VERSION"
|
|
||||||
|
|
||||||
# 检查主程序文件
|
|
||||||
if [ ! -f "mainwindow_tkinter.py" ] && [ ! -f "mainwindow.py" ]; then
|
|
||||||
echo "✗ 错误: 未找到主程序文件"
|
|
||||||
echo " 请确保在包含 mainwindow_tkinter.py 或 mainwindow.py 的目录中运行此脚本"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
echo " 步骤 1/4: 安装依赖包"
|
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
|
|
||||||
# 检测是否为外部管理环境 (PEP 668)
|
|
||||||
IS_EXTERNALLY_MANAGED=0
|
|
||||||
if python3 -c "import sys; sys.exit(0 if (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix) or 'VIRTUAL_ENV' in __import__('os').environ else 1)" 2>/dev/null; then
|
|
||||||
echo " 检测到在虚拟环境中"
|
|
||||||
IS_EXTERNALLY_MANAGED=0
|
|
||||||
elif python3 -c "import sysconfig; import os; print(os.path.exists(os.path.join(sysconfig.get_path('stdlib'), 'EXTERNALLY-MANAGED')))" | grep -q "True"; then
|
|
||||||
echo " 检测到外部管理环境 (PEP 668)"
|
|
||||||
IS_EXTERNALLY_MANAGED=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
install_deps() {
|
|
||||||
local EXTRA_ARGS=""
|
|
||||||
if [ "$IS_EXTERNALLY_MANAGED" -eq 1 ]; then
|
|
||||||
EXTRA_ARGS="--break-system-packages"
|
|
||||||
echo " 使用 --break-system-packages 选项"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 安装/升级 pip
|
|
||||||
python3 -m pip install --upgrade pip $EXTRA_ARGS 2>/dev/null || {
|
|
||||||
echo " pip 升级失败,继续安装..."
|
|
||||||
}
|
|
||||||
|
|
||||||
# 安装 pyinstaller 和 pexpect
|
|
||||||
pip3 install pyinstaller pexpect $EXTRA_ARGS || {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if ! install_deps; then
|
|
||||||
echo " 尝试使用 sudo 安装依赖..."
|
|
||||||
sudo pip3 install pyinstaller pexpect --break-system-packages 2>/dev/null || {
|
|
||||||
echo ""
|
|
||||||
echo "✗ 依赖安装失败"
|
|
||||||
echo ""
|
|
||||||
echo " 您可以选择以下方式安装:"
|
|
||||||
echo ""
|
|
||||||
echo " 方式 1 - 创建虚拟环境 (推荐):"
|
|
||||||
echo " python3 -m venv venv"
|
|
||||||
echo " source venv/bin/activate"
|
|
||||||
echo " pip install pyinstaller pexpect"
|
|
||||||
echo " ./build.sh"
|
|
||||||
echo ""
|
|
||||||
echo " 方式 2 - 使用系统包管理器 (Arch):"
|
|
||||||
echo " sudo pacman -S python-pyinstaller python-pexpect"
|
|
||||||
echo " ./build.sh"
|
|
||||||
echo ""
|
|
||||||
echo " 方式 3 - 强制安装 (有风险):"
|
|
||||||
echo " pip3 install pyinstaller pexpect --break-system-packages"
|
|
||||||
echo " ./build.sh"
|
|
||||||
echo ""
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
echo " 步骤 2/4: 清理构建文件"
|
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
|
|
||||||
# 清理旧文件
|
|
||||||
rm -rf build dist __pycache__
|
|
||||||
rm -f mainwindow*.spec
|
|
||||||
|
|
||||||
echo " 已清理构建文件"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
echo " 步骤 3/4: PyInstaller 打包"
|
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
|
|
||||||
# 确定主文件
|
# 确定主文件
|
||||||
MAIN_SCRIPT="mainwindow_tkinter.py"
|
MAIN_SCRIPT="mainwindow_tkinter.py"
|
||||||
if [ ! -f "$MAIN_SCRIPT" ]; then
|
if [ ! -f "$MAIN_SCRIPT" ]; then
|
||||||
MAIN_SCRIPT="mainwindow.py"
|
MAIN_SCRIPT="mainwindow.py"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " 打包文件: $MAIN_SCRIPT"
|
# 检查 tkinter
|
||||||
|
if ! python3 -c "import tkinter" 2>/dev/null; then
|
||||||
|
echo "错误: 未找到 tkinter 模块"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 获取 tkinter 路径
|
||||||
|
TKINTER_INFO=$(python3 << 'EOF'
|
||||||
|
import tkinter
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
tcl = tkinter.Tcl()
|
||||||
|
tk_version = tcl.call("info", "tclversion")
|
||||||
|
tk_lib = tcl.call("info", "library")
|
||||||
|
print(f"TK_VERSION:{tk_version}")
|
||||||
|
print(f"TK_LIBRARY:{tk_lib}")
|
||||||
|
|
||||||
|
tkinter_file = tkinter.__file__
|
||||||
|
print(f"TKINTER_FILE:{tkinter_file}")
|
||||||
|
|
||||||
|
tcl_lib = os.path.dirname(tk_lib)
|
||||||
|
print(f"TCL_LIBRARY:{tcl_lib}")
|
||||||
|
|
||||||
|
import sysconfig
|
||||||
|
lib_dynload = os.path.join(sysconfig.get_config_var('LIBDIR'), f"python{sys.version_info.major}.{sys.version_info.minor}", "lib-dynload")
|
||||||
|
if not os.path.exists(lib_dynload):
|
||||||
|
lib_dynload = os.path.join(sysconfig.get_config_var('LIBDIR'), "lib-dynload")
|
||||||
|
print(f"LIB_DYNLOAD:{lib_dynload}")
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
TK_VERSION=$(echo "$TKINTER_INFO" | grep "TK_VERSION:" | cut -d: -f2)
|
||||||
|
TK_LIBRARY=$(echo "$TKINTER_INFO" | grep "TK_LIBRARY:" | cut -d: -f2)
|
||||||
|
TCL_LIBRARY=$(echo "$TKINTER_INFO" | grep "TCL_LIBRARY:" | cut -d: -f2)
|
||||||
|
LIB_DYNLOAD=$(echo "$TKINTER_INFO" | grep "LIB_DYNLOAD:" | cut -d: -f2)
|
||||||
|
PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
|
||||||
|
|
||||||
|
# 查找 _tkinter 共享库
|
||||||
|
TKINTER_SO=""
|
||||||
|
for pattern in "_tkinter.cpython-${PYTHON_VERSION//./}m-x86_64-linux-gnu.so" "_tkinter.cpython-${PYTHON_VERSION//./}-x86_64-linux-gnu.so" "_tkinter.so"; do
|
||||||
|
if [ -f "$LIB_DYNLOAD/$pattern" ]; then
|
||||||
|
TKINTER_SO="$LIB_DYNLOAD/$pattern"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$TKINTER_SO" ]; then
|
||||||
|
TKINTER_SO=$(find $LIB_DYNLOAD -name "_tkinter*.so" 2>/dev/null | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 构建 PyInstaller 参数
|
||||||
|
PYINSTALLER_ARGS=(
|
||||||
|
--onefile
|
||||||
|
--name "linux-storage-manager"
|
||||||
|
--clean
|
||||||
|
--noconfirm
|
||||||
|
--console
|
||||||
|
--hidden-import "tkinter"
|
||||||
|
--hidden-import "tkinter.ttk"
|
||||||
|
--hidden-import "tkinter.scrolledtext"
|
||||||
|
--hidden-import "tkinter.messagebox"
|
||||||
|
--hidden-import "tkinter.filedialog"
|
||||||
|
--hidden-import "tkinter.simpledialog"
|
||||||
|
--hidden-import "_tkinter"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 添加 tkinter 库文件
|
||||||
|
if [ -n "$TKINTER_SO" ]; then
|
||||||
|
PYINSTALLER_ARGS+=(--add-binary "$TKINTER_SO:.")
|
||||||
|
fi
|
||||||
|
if [ -d "$TCL_LIBRARY" ]; then
|
||||||
|
PYINSTALLER_ARGS+=(--add-data "$TCL_LIBRARY:tcl")
|
||||||
|
fi
|
||||||
|
if [ -d "$TK_LIBRARY" ]; then
|
||||||
|
PYINSTALLER_ARGS+=(--add-data "$TK_LIBRARY:tk")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 查找并添加其他 Tcl/Tk 文件
|
||||||
|
for dir in /usr/lib64/tcl$TK_VERSION /usr/lib/tcl$TK_VERSION /usr/share/tcltk /usr/lib/tcltk /usr/lib64/tcltk; do
|
||||||
|
if [ -d "$dir" ]; then
|
||||||
|
PYINSTALLER_ARGS+=(--add-data "$dir:tcltk")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# 执行打包
|
# 执行打包
|
||||||
python3 -m PyInstaller \
|
python3 -m PyInstaller "${PYINSTALLER_ARGS[@]}" "$MAIN_SCRIPT"
|
||||||
--onefile \
|
|
||||||
--name "linux-storage-manager" \
|
|
||||||
--clean \
|
|
||||||
--noconfirm \
|
|
||||||
--console \
|
|
||||||
"$MAIN_SCRIPT"
|
|
||||||
|
|
||||||
echo ""
|
# 检查结果
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
echo " 步骤 4/4: 创建桌面快捷方式"
|
|
||||||
echo "═══════════════════════════════════════════════════════════════"
|
|
||||||
|
|
||||||
cat > linux-storage-manager.desktop << 'EOF'
|
|
||||||
[Desktop Entry]
|
|
||||||
Name=Linux 存储管理器
|
|
||||||
Comment=Linux 存储管理工具
|
|
||||||
Exec=/usr/local/bin/linux-storage-manager
|
|
||||||
Icon=drive-harddisk
|
|
||||||
Terminal=false
|
|
||||||
Type=Application
|
|
||||||
Categories=System;Utility;
|
|
||||||
Keywords=storage;disk;partition;raid;lvm;
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo " 已创建桌面文件: linux-storage-manager.desktop"
|
|
||||||
echo " 安装命令: sudo cp linux-storage-manager.desktop /usr/share/applications/"
|
|
||||||
|
|
||||||
# 检查输出
|
|
||||||
if [ -f "dist/linux-storage-manager" ]; then
|
if [ -f "dist/linux-storage-manager" ]; then
|
||||||
SIZE=$(du -h dist/linux-storage-manager | cut -f1)
|
SIZE=$(du -h dist/linux-storage-manager | cut -f1)
|
||||||
echo ""
|
echo ""
|
||||||
echo "╔══════════════════════════════════════════════════════════════╗"
|
echo "打包成功!"
|
||||||
echo "║ 打包成功! ║"
|
|
||||||
echo "╚══════════════════════════════════════════════════════════════╝"
|
|
||||||
echo ""
|
|
||||||
echo " 输出文件: dist/linux-storage-manager"
|
echo " 输出文件: dist/linux-storage-manager"
|
||||||
echo " 文件大小: $SIZE"
|
echo " 文件大小: $SIZE"
|
||||||
echo ""
|
echo " 运行命令: sudo dist/linux-storage-manager"
|
||||||
echo " 使用方法:"
|
|
||||||
echo " 直接运行: sudo dist/linux-storage-manager"
|
|
||||||
echo " 安装到系统: sudo cp dist/linux-storage-manager /usr/local/bin/"
|
|
||||||
echo ""
|
|
||||||
else
|
else
|
||||||
echo "✗ 打包失败: 未找到输出文件"
|
echo "打包失败"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -190,26 +190,48 @@ class DiskOperations:
|
|||||||
logger.info(f"尝试挂载设备 {device_path} 到 {mount_point}。")
|
logger.info(f"尝试挂载设备 {device_path} 到 {mount_point}。")
|
||||||
success, _, stderr = self._execute_shell_command(
|
success, _, stderr = self._execute_shell_command(
|
||||||
["mount", device_path, mount_point],
|
["mount", device_path, mount_point],
|
||||||
f"挂载设备 {device_path} 失败"
|
f"挂载设备 {device_path} 失败",
|
||||||
|
show_dialog=False
|
||||||
)
|
)
|
||||||
if success:
|
|
||||||
messagebox.showinfo("成功", f"设备 {device_path} 已成功挂载到 {mount_point}。")
|
# 如果普通挂载失败,检查是否是 NTFS 并尝试使用 ntfs-3g
|
||||||
if add_to_fstab:
|
if not success:
|
||||||
device_details = self.system_manager.get_device_details_by_path(device_path)
|
device_details = self.system_manager.get_device_details_by_path(device_path)
|
||||||
if device_details:
|
fstype = device_details.get('fstype', '').lower() if device_details else ''
|
||||||
fstype = device_details.get('fstype')
|
|
||||||
uuid = device_details.get('uuid')
|
if fstype == 'ntfs' or 'ntfs' in stderr.lower():
|
||||||
if fstype and uuid:
|
logger.info(f"尝试使用 ntfs-3g 挂载设备 {device_path}。")
|
||||||
self._add_to_fstab(device_path, mount_point, fstype, uuid)
|
success, _, stderr = self._execute_shell_command(
|
||||||
else:
|
["mount", "-t", "ntfs-3g", device_path, mount_point],
|
||||||
logger.error(f"无法获取设备 {device_path} 的文件系统类型或 UUID 以添加到 fstab。")
|
f"使用 ntfs-3g 挂载设备 {device_path} 失败"
|
||||||
messagebox.showwarning("警告", f"设备 {device_path} 已挂载,但无法获取文件系统类型或 UUID 以添加到 fstab。")
|
)
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("成功", f"设备 {device_path} 已通过 ntfs-3g 成功挂载到 {mount_point}。")
|
||||||
else:
|
else:
|
||||||
logger.error(f"无法获取设备 {device_path} 的详细信息以添加到 fstab。")
|
messagebox.showerror("错误", f"挂载设备 {device_path} 失败。\n\n"
|
||||||
messagebox.showwarning("警告", f"设备 {device_path} 已挂载,但无法获取详细信息以添加到 fstab。")
|
f"普通挂载和 ntfs-3g 挂载均失败。\n"
|
||||||
return True
|
f"如果是 NTFS 文件系统损坏,请先使用文件系统工具中的 "修复文件系统 (ntfsfix)" 修复。")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
messagebox.showerror("错误", f"挂载设备 {device_path} 失败: {stderr}")
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
return False
|
messagebox.showinfo("成功", f"设备 {device_path} 已成功挂载到 {mount_point}。")
|
||||||
|
|
||||||
|
if success and add_to_fstab:
|
||||||
|
device_details = self.system_manager.get_device_details_by_path(device_path)
|
||||||
|
if device_details:
|
||||||
|
fstype = device_details.get('fstype')
|
||||||
|
uuid = device_details.get('uuid')
|
||||||
|
if fstype and uuid:
|
||||||
|
self._add_to_fstab(device_path, mount_point, fstype, uuid)
|
||||||
|
else:
|
||||||
|
logger.error(f"无法获取设备 {device_path} 的文件系统类型或 UUID 以添加到 fstab。")
|
||||||
|
messagebox.showwarning("警告", f"设备 {device_path} 已挂载,但无法获取文件系统类型或 UUID 以添加到 fstab。")
|
||||||
|
else:
|
||||||
|
logger.error(f"无法获取设备 {device_path} 的详细信息以添加到 fstab。")
|
||||||
|
messagebox.showwarning("警告", f"设备 {device_path} 已挂载,但无法获取详细信息以添加到 fstab。")
|
||||||
|
return success
|
||||||
|
|
||||||
def unmount_partition(self, device_path, show_dialog_on_error=True):
|
def unmount_partition(self, device_path, show_dialog_on_error=True):
|
||||||
"""卸载指定设备"""
|
"""卸载指定设备"""
|
||||||
|
|||||||
38
diskmanager.spec
Normal file
38
diskmanager.spec
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# -*- mode: python ; coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(
|
||||||
|
['main_tkinter.py'],
|
||||||
|
pathex=[],
|
||||||
|
binaries=[],
|
||||||
|
datas=[],
|
||||||
|
hiddenimports=[],
|
||||||
|
hookspath=[],
|
||||||
|
hooksconfig={},
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[],
|
||||||
|
noarchive=False,
|
||||||
|
optimize=0,
|
||||||
|
)
|
||||||
|
pyz = PYZ(a.pure)
|
||||||
|
|
||||||
|
exe = EXE(
|
||||||
|
pyz,
|
||||||
|
a.scripts,
|
||||||
|
a.binaries,
|
||||||
|
a.datas,
|
||||||
|
[],
|
||||||
|
name='diskmanager',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
upx_exclude=[],
|
||||||
|
runtime_tmpdir=None,
|
||||||
|
console=True,
|
||||||
|
disable_windowed_traceback=False,
|
||||||
|
argv_emulation=False,
|
||||||
|
target_arch=None,
|
||||||
|
codesign_identity=None,
|
||||||
|
entitlements_file=None,
|
||||||
|
)
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
a = Analysis(
|
a = Analysis(
|
||||||
['mainwindow_tkinter.py'],
|
['mainwindow_tkinter.py'],
|
||||||
pathex=[],
|
pathex=[],
|
||||||
binaries=[],
|
binaries=[('/usr/lib/python3.14/lib-dynload/_tkinter.cpython-314-x86_64-linux-gnu.so', '.')],
|
||||||
datas=[],
|
datas=[('/usr/lib', 'tcl'), ('/usr/lib/tcl8.6', 'tk'), ('/usr/lib64/tcl8.6', 'tcltk'), ('/usr/lib/tcl8.6', 'tcltk')],
|
||||||
hiddenimports=[],
|
hiddenimports=['tkinter', 'tkinter.ttk', 'tkinter.scrolledtext', 'tkinter.messagebox', 'tkinter.filedialog', 'tkinter.simpledialog', '_tkinter'],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
|
|||||||
@@ -440,6 +440,9 @@ class MainWindow:
|
|||||||
elif fstype == 'xfs':
|
elif fstype == 'xfs':
|
||||||
fs_menu.add_command(label=f"修复文件系统 (xfs_repair) {device_path}",
|
fs_menu.add_command(label=f"修复文件系统 (xfs_repair) {device_path}",
|
||||||
command=lambda dp=device_path: self._handle_xfs_repair(dp))
|
command=lambda dp=device_path: self._handle_xfs_repair(dp))
|
||||||
|
elif fstype.lower() == 'ntfs':
|
||||||
|
fs_menu.add_command(label=f"修复文件系统 (ntfsfix) {device_path}",
|
||||||
|
command=lambda dp=device_path: self._handle_ntfsfix(dp))
|
||||||
if fs_menu.index(tk.END) is not None:
|
if fs_menu.index(tk.END) is not None:
|
||||||
menu.add_cascade(label=f"文件系统工具 {device_path}", menu=fs_menu)
|
menu.add_cascade(label=f"文件系统工具 {device_path}", menu=fs_menu)
|
||||||
|
|
||||||
@@ -546,6 +549,9 @@ class MainWindow:
|
|||||||
elif fstype == 'xfs':
|
elif fstype == 'xfs':
|
||||||
fs_menu.add_command(label=f"修复文件系统 (xfs_repair) {array_path}",
|
fs_menu.add_command(label=f"修复文件系统 (xfs_repair) {array_path}",
|
||||||
command=lambda dp=array_path: self._handle_xfs_repair(dp))
|
command=lambda dp=array_path: self._handle_xfs_repair(dp))
|
||||||
|
elif fstype.lower() == 'ntfs':
|
||||||
|
fs_menu.add_command(label=f"修复文件系统 (ntfsfix) {array_path}",
|
||||||
|
command=lambda dp=array_path: self._handle_ntfsfix(dp))
|
||||||
if fs_menu.index(tk.END) is not None:
|
if fs_menu.index(tk.END) is not None:
|
||||||
menu.add_cascade(label=f"文件系统工具 {array_path}", menu=fs_menu)
|
menu.add_cascade(label=f"文件系统工具 {array_path}", menu=fs_menu)
|
||||||
|
|
||||||
@@ -637,6 +643,9 @@ class MainWindow:
|
|||||||
elif fstype == 'xfs':
|
elif fstype == 'xfs':
|
||||||
fs_menu.add_command(label=f"修复文件系统 (xfs_repair) {lv_path}",
|
fs_menu.add_command(label=f"修复文件系统 (xfs_repair) {lv_path}",
|
||||||
command=lambda dp=lv_path: self._handle_xfs_repair(dp))
|
command=lambda dp=lv_path: self._handle_xfs_repair(dp))
|
||||||
|
elif fstype.lower() == 'ntfs':
|
||||||
|
fs_menu.add_command(label=f"修复文件系统 (ntfsfix) {lv_path}",
|
||||||
|
command=lambda dp=lv_path: self._handle_ntfsfix(dp))
|
||||||
if fs_menu.index(tk.END) is not None:
|
if fs_menu.index(tk.END) is not None:
|
||||||
menu.add_cascade(label=f"文件系统工具 {lv_path}", menu=fs_menu)
|
menu.add_cascade(label=f"文件系统工具 {lv_path}", menu=fs_menu)
|
||||||
|
|
||||||
@@ -919,6 +928,37 @@ class MainWindow:
|
|||||||
messagebox.showerror("错误", f"调整文件系统大小失败:\n{stderr[:500] if stderr else '未知错误'}")
|
messagebox.showerror("错误", f"调整文件系统大小失败:\n{stderr[:500] if stderr else '未知错误'}")
|
||||||
self.refresh_all_info()
|
self.refresh_all_info()
|
||||||
|
|
||||||
|
def _handle_ntfsfix(self, device_path):
|
||||||
|
"""修复 NTFS 文件系统"""
|
||||||
|
# 检查设备是否已挂载
|
||||||
|
mount_point = self.system_manager.get_mountpoint_for_device(device_path)
|
||||||
|
if mount_point and mount_point != 'N/A':
|
||||||
|
messagebox.showwarning("警告", f"设备 {device_path} 已挂载到 {mount_point}\n请先卸载后再执行文件系统修复。")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not messagebox.askyesno("确认",
|
||||||
|
f"即将对 {device_path} (NTFS) 执行文件系统修复。\n"
|
||||||
|
f"命令: sudo ntfsfix -d {device_path}\n\n"
|
||||||
|
f"注意:此操作会清除 NTFS 卷的脏标志并尝试修复。\n"
|
||||||
|
f"如果修复后仍无法挂载,请尝试使用 ntfs-3g 方式挂载。",
|
||||||
|
default=messagebox.NO):
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"开始修复 NTFS 文件系统: {device_path}")
|
||||||
|
success, stdout, stderr = self.lvm_ops._execute_shell_command(
|
||||||
|
["ntfsfix", "-d", device_path],
|
||||||
|
f"修复 NTFS 文件系统 {device_path} 失败"
|
||||||
|
)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("成功", f"NTFS 文件系统修复完成:\n{stdout[:500] if stdout else '无输出'}\n\n"
|
||||||
|
f"如果仍无法正常挂载,请尝试使用:\n"
|
||||||
|
f"mount -t ntfs-3g {device_path} <挂载点>")
|
||||||
|
else:
|
||||||
|
messagebox.showerror("错误", f"NTFS 文件系统修复失败:\n{stderr[:500] if stderr else '未知错误'}\n\n"
|
||||||
|
f"建议尝试使用 ntfs-3g 驱动挂载。")
|
||||||
|
self.refresh_all_info()
|
||||||
|
|
||||||
def on_disk_formatting_finished(self, success, device_path, stdout, stderr):
|
def on_disk_formatting_finished(self, success, device_path, stdout, stderr):
|
||||||
"""接收格式化完成回调并刷新界面"""
|
"""接收格式化完成回调并刷新界面"""
|
||||||
logger.info(f"格式化完成信号接收: 设备 {device_path}, 成功: {success}")
|
logger.info(f"格式化完成信号接收: 设备 {device_path}, 成功: {success}")
|
||||||
|
|||||||
Reference in New Issue
Block a user