From 5e5c23a9a5f03eb8be0dda9d823392b40082d2c1 Mon Sep 17 00:00:00 2001 From: yuyx <237899745@qq.com> Date: Mon, 1 Dec 2025 10:54:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=99=A8=20-=20Web=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=AE=89=E8=A3=85=E6=89=93=E5=8D=B0=E6=9C=BA=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增功能: - 独立的Web服务(端口632)用于管理打印机驱动 - 支持上传安装多种驱动格式:.deb, .ppd, .tar.gz, .zip, .rpm, .sh - 自动识别文件类型并执行对应安装命令 - 中文Web界面,风格与CUPS保持一致 - 基本认证保护,随机生成管理密码 - 查看已安装驱动列表 安装脚本更新: - 新增"是否安装驱动管理器"选项 - 自动配置systemd服务开机自启 - 安装完成后显示驱动管理器地址和密码 - 卸载时自动清理驱动管理器 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../cups-driver-manager.service | 22 + cups-driver-manager/driver_manager.py | 1023 +++++++++++++++++ setup_cups.sh | 127 +- 3 files changed, 1171 insertions(+), 1 deletion(-) create mode 100644 cups-driver-manager/cups-driver-manager.service create mode 100644 cups-driver-manager/driver_manager.py diff --git a/cups-driver-manager/cups-driver-manager.service b/cups-driver-manager/cups-driver-manager.service new file mode 100644 index 0000000..b8c649f --- /dev/null +++ b/cups-driver-manager/cups-driver-manager.service @@ -0,0 +1,22 @@ +[Unit] +Description=CUPS Printer Driver Manager +Documentation=https://gitee.com/yu-yon/S905L3A +After=network.target cups.service +Wants=cups.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/cups-driver-manager +ExecStart=/usr/bin/python3 /opt/cups-driver-manager/driver_manager.py --port 632 +Restart=on-failure +RestartSec=5 +Environment=DRIVER_MANAGER_PASSWORD=admin + +# 安全设置 +NoNewPrivileges=false +ProtectSystem=false +ProtectHome=false + +[Install] +WantedBy=multi-user.target diff --git a/cups-driver-manager/driver_manager.py b/cups-driver-manager/driver_manager.py new file mode 100644 index 0000000..9b558ce --- /dev/null +++ b/cups-driver-manager/driver_manager.py @@ -0,0 +1,1023 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +CUPS 打印机驱动管理器 +轻量级Web服务,用于上传和安装打印机驱动 +""" + +import os +import sys +import subprocess +import tempfile +import shutil +import tarfile +import zipfile +from pathlib import Path +from functools import wraps + +from flask import Flask, request, render_template_string, redirect, url_for, flash, jsonify, Response +from werkzeug.utils import secure_filename + +app = Flask(__name__) +app.secret_key = os.urandom(24) + +# 配置 +UPLOAD_FOLDER = '/tmp/cups-drivers' +MAX_CONTENT_LENGTH = 100 * 1024 * 1024 # 100MB +ALLOWED_EXTENSIONS = {'deb', 'ppd', 'gz', 'tar', 'tgz', 'zip', 'rpm', 'sh', 'run'} + +# 管理员密码(首次运行时会提示设置,或使用环境变量) +ADMIN_PASSWORD = os.environ.get('DRIVER_MANAGER_PASSWORD', 'admin') + +app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER +app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH + +# 确保上传目录存在 +os.makedirs(UPLOAD_FOLDER, exist_ok=True) + +def check_auth(password): + """验证密码""" + return password == ADMIN_PASSWORD + +def authenticate(): + """发送401响应""" + return Response( + '需要登录才能访问驱动管理器\n', + 401, + {'WWW-Authenticate': 'Basic realm="CUPS Driver Manager"'} + ) + +def requires_auth(f): + """认证装饰器""" + @wraps(f) + def decorated(*args, **kwargs): + auth = request.authorization + if not auth or not check_auth(auth.password): + return authenticate() + return f(*args, **kwargs) + return decorated + +def allowed_file(filename): + """检查文件类型是否允许""" + if '.' not in filename: + return False + ext = filename.rsplit('.', 1)[1].lower() + # 处理 .tar.gz 情况 + if filename.endswith('.tar.gz'): + return True + return ext in ALLOWED_EXTENSIONS + +def get_file_type(filename): + """获取文件类型""" + filename_lower = filename.lower() + if filename_lower.endswith('.deb'): + return 'deb' + elif filename_lower.endswith('.ppd') or filename_lower.endswith('.ppd.gz'): + return 'ppd' + elif filename_lower.endswith('.tar.gz') or filename_lower.endswith('.tgz'): + return 'tar.gz' + elif filename_lower.endswith('.tar'): + return 'tar' + elif filename_lower.endswith('.zip'): + return 'zip' + elif filename_lower.endswith('.rpm'): + return 'rpm' + elif filename_lower.endswith('.sh') or filename_lower.endswith('.run'): + return 'script' + else: + return 'unknown' + +def run_command(cmd, shell=False): + """执行命令并返回结果""" + try: + if shell: + result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=300) + else: + result = subprocess.run(cmd, capture_output=True, text=True, timeout=300) + return { + 'success': result.returncode == 0, + 'stdout': result.stdout, + 'stderr': result.stderr, + 'returncode': result.returncode + } + except subprocess.TimeoutExpired: + return {'success': False, 'stdout': '', 'stderr': '命令执行超时', 'returncode': -1} + except Exception as e: + return {'success': False, 'stdout': '', 'stderr': str(e), 'returncode': -1} + +def install_deb(filepath): + """安装 .deb 包""" + results = [] + + # 先尝试直接安装 + result = run_command(['dpkg', '-i', filepath]) + results.append(('dpkg -i', result)) + + # 修复依赖 + if not result['success']: + fix_result = run_command(['apt-get', 'install', '-f', '-y']) + results.append(('apt-get install -f', fix_result)) + + return results + +def install_ppd(filepath): + """安装 .ppd 文件""" + results = [] + + # PPD文件目录 + ppd_dirs = [ + '/usr/share/ppd/custom', + '/usr/share/cups/model' + ] + + # 确保目录存在 + for ppd_dir in ppd_dirs: + os.makedirs(ppd_dir, exist_ok=True) + + # 复制PPD文件 + filename = os.path.basename(filepath) + dest = os.path.join(ppd_dirs[0], filename) + + try: + shutil.copy2(filepath, dest) + os.chmod(dest, 0o644) + results.append(('复制PPD文件', { + 'success': True, + 'stdout': f'已复制到 {dest}', + 'stderr': '', + 'returncode': 0 + })) + except Exception as e: + results.append(('复制PPD文件', { + 'success': False, + 'stdout': '', + 'stderr': str(e), + 'returncode': 1 + })) + + return results + +def install_tar_gz(filepath): + """安装 .tar.gz 包""" + results = [] + + # 创建临时解压目录 + extract_dir = tempfile.mkdtemp(prefix='driver_') + + try: + # 解压 + with tarfile.open(filepath, 'r:gz') as tar: + tar.extractall(extract_dir) + results.append(('解压文件', { + 'success': True, + 'stdout': f'已解压到 {extract_dir}', + 'stderr': '', + 'returncode': 0 + })) + + # 查找安装脚本 + install_scripts = ['install.sh', 'setup.sh', 'install', 'setup'] + found_script = None + + for root, dirs, files in os.walk(extract_dir): + for script in install_scripts: + if script in files: + found_script = os.path.join(root, script) + break + if found_script: + break + + if found_script: + os.chmod(found_script, 0o755) + result = run_command(found_script, shell=True) + results.append(('执行安装脚本', result)) + else: + # 查找 Makefile + for root, dirs, files in os.walk(extract_dir): + if 'Makefile' in files: + make_result = run_command(['make', '-C', root]) + results.append(('make', make_result)) + if make_result['success']: + install_result = run_command(['make', '-C', root, 'install']) + results.append(('make install', install_result)) + break + else: + # 查找 PPD 文件 + ppd_files = list(Path(extract_dir).rglob('*.ppd')) + if ppd_files: + for ppd_file in ppd_files: + ppd_results = install_ppd(str(ppd_file)) + results.extend(ppd_results) + else: + results.append(('查找安装方式', { + 'success': False, + 'stdout': '', + 'stderr': '未找到安装脚本、Makefile或PPD文件', + 'returncode': 1 + })) + + except Exception as e: + results.append(('解压文件', { + 'success': False, + 'stdout': '', + 'stderr': str(e), + 'returncode': 1 + })) + finally: + # 清理临时目录 + shutil.rmtree(extract_dir, ignore_errors=True) + + return results + +def install_zip(filepath): + """安装 .zip 包""" + results = [] + + # 创建临时解压目录 + extract_dir = tempfile.mkdtemp(prefix='driver_') + + try: + # 解压 + with zipfile.ZipFile(filepath, 'r') as zip_ref: + zip_ref.extractall(extract_dir) + results.append(('解压文件', { + 'success': True, + 'stdout': f'已解压到 {extract_dir}', + 'stderr': '', + 'returncode': 0 + })) + + # 查找 deb 文件 + deb_files = list(Path(extract_dir).rglob('*.deb')) + if deb_files: + for deb_file in deb_files: + deb_results = install_deb(str(deb_file)) + results.extend(deb_results) + return results + + # 查找安装脚本 + install_scripts = ['install.sh', 'setup.sh', 'install', 'setup'] + found_script = None + + for root, dirs, files in os.walk(extract_dir): + for script in install_scripts: + if script in files: + found_script = os.path.join(root, script) + break + if found_script: + break + + if found_script: + os.chmod(found_script, 0o755) + result = run_command(found_script, shell=True) + results.append(('执行安装脚本', result)) + else: + # 查找 PPD 文件 + ppd_files = list(Path(extract_dir).rglob('*.ppd')) + if ppd_files: + for ppd_file in ppd_files: + ppd_results = install_ppd(str(ppd_file)) + results.extend(ppd_results) + else: + results.append(('查找安装方式', { + 'success': False, + 'stdout': '', + 'stderr': '未找到deb包、安装脚本或PPD文件', + 'returncode': 1 + })) + + except Exception as e: + results.append(('解压文件', { + 'success': False, + 'stdout': '', + 'stderr': str(e), + 'returncode': 1 + })) + finally: + # 清理临时目录 + shutil.rmtree(extract_dir, ignore_errors=True) + + return results + +def install_rpm(filepath): + """安装 .rpm 包(转换为deb后安装)""" + results = [] + + # 检查 alien 是否安装 + alien_check = run_command(['which', 'alien']) + if not alien_check['success']: + # 安装 alien + install_result = run_command(['apt-get', 'install', '-y', 'alien']) + results.append(('安装alien工具', install_result)) + if not install_result['success']: + return results + + # 使用 alien 转换 + work_dir = os.path.dirname(filepath) + convert_result = run_command(f'cd {work_dir} && alien -d {filepath}', shell=True) + results.append(('转换RPM为DEB', convert_result)) + + if convert_result['success']: + # 查找生成的 deb 文件 + deb_files = list(Path(work_dir).glob('*.deb')) + for deb_file in deb_files: + deb_results = install_deb(str(deb_file)) + results.extend(deb_results) + os.remove(deb_file) # 清理临时deb文件 + + return results + +def install_script(filepath): + """执行安装脚本""" + results = [] + + os.chmod(filepath, 0o755) + result = run_command(filepath, shell=True) + results.append(('执行安装脚本', result)) + + return results + +def install_driver(filepath, file_type): + """根据文件类型安装驱动""" + if file_type == 'deb': + return install_deb(filepath) + elif file_type == 'ppd': + return install_ppd(filepath) + elif file_type in ('tar.gz', 'tar', 'tgz'): + return install_tar_gz(filepath) + elif file_type == 'zip': + return install_zip(filepath) + elif file_type == 'rpm': + return install_rpm(filepath) + elif file_type == 'script': + return install_script(filepath) + else: + return [('未知类型', { + 'success': False, + 'stdout': '', + 'stderr': f'不支持的文件类型: {file_type}', + 'returncode': 1 + })] + +# HTML模板 +HTML_TEMPLATE = ''' + + + + + + CUPS 驱动管理器 + + + +
+ +
+ +
+

CUPS 打印机驱动管理器

+ + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
{{ message }}
+ {% endfor %} + {% endif %} + {% endwith %} + +
+

上传并安装驱动

+
+
+
📦
+

点击或拖拽文件到此处上传

+ +
+
+ 已选择: + +
+
+ 支持的格式: + .deb + .ppd + .tar.gz + .zip + .rpm + .sh +
+
+ +
+ +
+
+

正在安装驱动,请稍候...

+
+
+ + {% if results %} +
+

安装结果

+
+ {% for step, result in results %} +
+
▶ {{ step }}
+ {% if result.success %} +
✓ 成功
+ {% else %} +
✗ 失败 (返回码: {{ result.returncode }})
+ {% endif %} + {% if result.stdout %}
{{ result.stdout }}
{% endif %} + {% if result.stderr %}
{{ result.stderr }}
{% endif %} +
+ {% endfor %} +
+
+ {% endif %} + + +
+ + + + +''' + +DRIVERS_TEMPLATE = ''' + + + + + + 已安装驱动 - CUPS 驱动管理器 + + + +
+ +
+ +
+

已安装的打印机驱动

+ +
+
+

PPD 文件 (/usr/share/ppd/custom/)

+ {% if ppd_custom %} +
    + {% for ppd in ppd_custom %} +
  • {{ ppd }}
  • + {% endfor %} +
+ {% else %} +

暂无自定义PPD文件

+ {% endif %} +
+ +
+

CUPS 模型 (/usr/share/cups/model/)

+ {% if cups_model %} +
    + {% for model in cups_model %} +
  • {{ model }}
  • + {% endfor %} +
+ {% else %} +

暂无自定义模型文件

+ {% endif %} +
+ +
+

已安装的打印机相关软件包

+ {% if packages %} +
    + {% for pkg in packages %} +
  • {{ pkg }}
  • + {% endfor %} +
+ {% else %} +

未找到打印机相关软件包

+ {% endif %} +
+
+ + ← 返回上传页面 +
+ + +''' + +@app.route('/') +@requires_auth +def index(): + return render_template_string(HTML_TEMPLATE, results=None) + +@app.route('/upload', methods=['POST']) +@requires_auth +def upload_file(): + if 'driver_file' not in request.files: + flash('没有选择文件', 'danger') + return redirect(url_for('index')) + + file = request.files['driver_file'] + + if file.filename == '': + flash('没有选择文件', 'danger') + return redirect(url_for('index')) + + if not allowed_file(file.filename): + flash('不支持的文件类型', 'danger') + return redirect(url_for('index')) + + # 保存文件 + filename = secure_filename(file.filename) + filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) + file.save(filepath) + + # 获取文件类型 + file_type = get_file_type(filename) + + # 安装驱动 + results = install_driver(filepath, file_type) + + # 清理上传的文件 + try: + os.remove(filepath) + except: + pass + + # 检查是否全部成功 + all_success = all(r[1]['success'] for r in results) + if all_success: + flash('驱动安装成功!', 'success') + else: + flash('驱动安装过程中出现错误,请查看详细信息', 'danger') + + return render_template_string(HTML_TEMPLATE, results=results) + +@app.route('/drivers') +@requires_auth +def list_drivers(): + # 获取自定义PPD文件 + ppd_custom = [] + ppd_dir = '/usr/share/ppd/custom' + if os.path.exists(ppd_dir): + ppd_custom = os.listdir(ppd_dir) + + # 获取CUPS模型 + cups_model = [] + model_dir = '/usr/share/cups/model' + if os.path.exists(model_dir): + for f in os.listdir(model_dir): + if f.endswith('.ppd') or f.endswith('.ppd.gz'): + cups_model.append(f) + + # 获取已安装的打印机相关软件包 + packages = [] + result = run_command(['dpkg', '-l']) + if result['success']: + for line in result['stdout'].split('\n'): + if any(keyword in line.lower() for keyword in ['printer', 'cups', 'hplip', 'gutenprint', 'foomatic', 'epson', 'canon', 'brother', 'samsung', 'pantum']): + parts = line.split() + if len(parts) >= 3 and parts[0] == 'ii': + packages.append(f"{parts[1]} ({parts[2]})") + + return render_template_string(DRIVERS_TEMPLATE, + ppd_custom=ppd_custom, + cups_model=cups_model, + packages=packages[:50]) # 限制显示数量 + +@app.route('/api/install', methods=['POST']) +@requires_auth +def api_install(): + """API接口,返回JSON""" + if 'driver_file' not in request.files: + return jsonify({'success': False, 'error': '没有选择文件'}) + + file = request.files['driver_file'] + + if file.filename == '': + return jsonify({'success': False, 'error': '没有选择文件'}) + + if not allowed_file(file.filename): + return jsonify({'success': False, 'error': '不支持的文件类型'}) + + # 保存文件 + filename = secure_filename(file.filename) + filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) + file.save(filepath) + + # 获取文件类型并安装 + file_type = get_file_type(filename) + results = install_driver(filepath, file_type) + + # 清理 + try: + os.remove(filepath) + except: + pass + + all_success = all(r[1]['success'] for r in results) + return jsonify({ + 'success': all_success, + 'results': [{'step': r[0], 'success': r[1]['success'], + 'stdout': r[1]['stdout'], 'stderr': r[1]['stderr']} + for r in results] + }) + +def main(): + import argparse + parser = argparse.ArgumentParser(description='CUPS 打印机驱动管理器') + parser.add_argument('-p', '--port', type=int, default=632, help='监听端口 (默认: 632)') + parser.add_argument('-H', '--host', default='0.0.0.0', help='监听地址 (默认: 0.0.0.0)') + parser.add_argument('--password', default=None, help='管理员密码') + args = parser.parse_args() + + global ADMIN_PASSWORD + if args.password: + ADMIN_PASSWORD = args.password + + print(f"CUPS 驱动管理器启动中...") + print(f"访问地址: http://localhost:{args.port}/") + print(f"默认用户名: admin") + print(f"默认密码: {ADMIN_PASSWORD}") + print("-" * 40) + + app.run(host=args.host, port=args.port, debug=False) + +if __name__ == '__main__': + main() diff --git a/setup_cups.sh b/setup_cups.sh index 1849f3f..7231780 100755 --- a/setup_cups.sh +++ b/setup_cups.sh @@ -713,6 +713,100 @@ install_chinese_templates() { fi } +# 安装驱动管理器(Web界面安装驱动) +install_driver_manager() { + info "安装 CUPS 驱动管理器..." + + # 安装依赖 + apt install -y python3 python3-pip python3-flask 2>/dev/null || { + # 如果系统包不可用,使用 pip 安装 + apt install -y python3 python3-pip + pip3 install flask 2>/dev/null || pip3 install flask --break-system-packages 2>/dev/null + } + + # 创建安装目录 + local install_dir="/opt/cups-driver-manager" + mkdir -p "$install_dir" + + # 复制文件 + SCRIPT_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)" || SCRIPT_DIR="" + + if [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/cups-driver-manager/driver_manager.py" ]; then + # 从本地复制 + cp -f "$SCRIPT_DIR/cups-driver-manager/driver_manager.py" "$install_dir/" + cp -f "$SCRIPT_DIR/cups-driver-manager/cups-driver-manager.service" /etc/systemd/system/ 2>/dev/null || true + info "从本地复制驱动管理器文件" + else + # 从 Gitee 下载 + info "从 Gitee 下载驱动管理器..." + local tmp_dir=$(mktemp -d) + local zip_url="https://gitee.com/yu-yon/S905L3A/repository/archive/master.zip" + + if wget -q --show-progress -O "$tmp_dir/repo.zip" "$zip_url" 2>/dev/null || \ + curl -sL -o "$tmp_dir/repo.zip" "$zip_url" 2>/dev/null; then + cd "$tmp_dir" + unzip -q repo.zip 2>/dev/null + + local dm_dir=$(find . -type d -name "cups-driver-manager" 2>/dev/null | head -1) + if [ -n "$dm_dir" ] && [ -d "$dm_dir" ]; then + cp -f "$dm_dir/driver_manager.py" "$install_dir/" + cp -f "$dm_dir/cups-driver-manager.service" /etc/systemd/system/ 2>/dev/null || true + fi + cd - > /dev/null + rm -rf "$tmp_dir" + else + warn "驱动管理器下载失败,跳过安装" + return 1 + fi + fi + + # 设置权限 + chmod +x "$install_dir/driver_manager.py" + + # 生成随机密码 + local admin_pass=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 8) + + # 更新 systemd 服务文件中的密码 + if [ -f /etc/systemd/system/cups-driver-manager.service ]; then + sed -i "s/DRIVER_MANAGER_PASSWORD=admin/DRIVER_MANAGER_PASSWORD=$admin_pass/" /etc/systemd/system/cups-driver-manager.service + else + # 手动创建服务文件 + cat > /etc/systemd/system/cups-driver-manager.service << EOF +[Unit] +Description=CUPS Printer Driver Manager +After=network.target cups.service +Wants=cups.service + +[Service] +Type=simple +User=root +WorkingDirectory=$install_dir +ExecStart=/usr/bin/python3 $install_dir/driver_manager.py --port 632 +Restart=on-failure +RestartSec=5 +Environment=DRIVER_MANAGER_PASSWORD=$admin_pass + +[Install] +WantedBy=multi-user.target +EOF + fi + + # 启动服务 + systemctl daemon-reload + systemctl enable cups-driver-manager + systemctl restart cups-driver-manager + + # 保存密码到文件 + echo "$admin_pass" > "$install_dir/.password" + chmod 600 "$install_dir/.password" + + success "驱动管理器安装完成" + info "驱动管理器密码: $admin_pass" + + # 导出变量供后续使用 + DRIVER_MANAGER_PASSWORD="$admin_pass" +} + # 安装虚拟PDF打印机(用于测试连接) install_pdf_printer() { info "安装虚拟 PDF 打印机..." @@ -892,6 +986,15 @@ main() { config_static_ip=${config_static_ip:-Y} echo "" + # 询问是否安装驱动管理器 + echo -e "${YELLOW}是否安装驱动管理器(Web界面安装打印机驱动)?${NC}" + echo " 推荐:选择 Y,可通过网页上传安装 .deb/.ppd/.tar.gz 等驱动" + echo " 端口: 632" + echo "" + read -p "安装驱动管理器? [Y/n]: " install_dm < /dev/tty + install_dm=${install_dm:-Y} + echo "" + # 确认安装 echo -e "${YELLOW}即将执行以下操作:${NC}" local step=1 @@ -913,6 +1016,10 @@ main() { ((step++)) echo " $step. 将当前用户添加到 lpadmin 组" ((step++)) + if [[ "$install_dm" =~ ^[Yy]$ ]]; then + echo " $step. 安装驱动管理器 (端口 632)" + ((step++)) + fi echo " $step. 启动并设置开机自启" echo "" read -p "是否继续? [Y/n]: " confirm < /dev/tty @@ -990,7 +1097,12 @@ main() { fi success "用户组配置完成" - # 6. 启动服务 + # 6. 安装驱动管理器(如果选择) + if [[ "$install_dm" =~ ^[Yy]$ ]]; then + install_driver_manager + fi + + # 7. 启动服务 info "启动 CUPS 服务..." systemctl restart cups systemctl enable cups @@ -1018,6 +1130,13 @@ main() { echo -e " ${BLUE}用户名:${NC} root" echo -e " ${BLUE}密码:${NC} 你的 SSH 密码" echo "" + # 检查是否安装了驱动管理器 + if systemctl is-active cups-driver-manager >/dev/null 2>&1; then + local dm_pass=$(cat /opt/cups-driver-manager/.password 2>/dev/null || echo "admin") + echo -e " ${GREEN}[驱动管理器]${NC} http://${LOCAL_IP}:632" + echo -e " ${GREEN} ${NC} 用户名: admin 密码: ${dm_pass}" + echo "" + fi # 检查是否安装了PDF打印机 if lpstat -p PDF 2>/dev/null | grep -q "PDF"; then echo -e " ${GREEN}[PDF打印机]${NC} 已安装虚拟 PDF 打印机用于测试" @@ -1068,6 +1187,7 @@ uninstall() { echo " - Avahi 服务 (AirPrint)" echo " - CUPS-PDF 虚拟打印机" echo " - 中文界面模板" + echo " - 驱动管理器" echo " - 所有打印任务和配置" echo "" read -p "确定要卸载吗? [y/N]: " confirm < /dev/tty @@ -1085,8 +1205,10 @@ uninstall() { info "停止服务..." systemctl stop cups 2>/dev/null || true systemctl stop avahi-daemon 2>/dev/null || true + systemctl stop cups-driver-manager 2>/dev/null || true systemctl disable cups 2>/dev/null || true systemctl disable avahi-daemon 2>/dev/null || true + systemctl disable cups-driver-manager 2>/dev/null || true # 卸载软件包 info "卸载软件包..." @@ -1103,6 +1225,9 @@ uninstall() { rm -rf /usr/share/cups/templates-zh_CN rm -rf /usr/share/cups/templates-zh rm -rf /usr/share/cups/templates-en-backup + rm -rf /opt/cups-driver-manager + rm -f /etc/systemd/system/cups-driver-manager.service + systemctl daemon-reload 2>/dev/null || true # 清理依赖 info "清理依赖..."