用Python CGI给老旧服务器写个简易后台管理面板(Apache配置+SQLite数据库)
用Python CGI打造轻量级服务器管理面板实战指南在资源受限的老旧服务器环境中部署现代Web框架往往显得大材小用。本文将展示如何利用Python CGI和SQLite数据库为树莓派、老款VPS等设备快速构建一个功能完备的轻量级管理面板。这种方案特别适合需要快速实现基础Web功能但又不愿引入复杂框架的开发者。1. 环境准备与基础配置1.1 Apache服务器配置首先确保Apache已安装并启用CGI模块。在Ubuntu/Debian系统上sudo apt install apache2 sudo a2enmod cgi sudo systemctl restart apache2编辑Apache配置文件通常位于/etc/apache2/sites-available/000-default.conf添加以下配置ScriptAlias /admin/ /var/www/admin/ Directory /var/www/admin Options ExecCGI AddHandler cgi-script .py Require all granted /Directory注意生产环境应将Require all granted替换为适当的访问控制1.2 项目目录结构建议采用以下目录布局/var/www/admin/ ├── cgi-bin/ # Python脚本存放处 │ ├── system.py # 系统管理模块 │ ├── files.py # 文件管理模块 │ └── dbadmin.py # 数据库管理模块 ├── data/ # SQLite数据库存放目录 ├── templates/ # HTML模板 └── uploads/ # 文件上传目录设置目录权限sudo mkdir -p /var/www/admin/{cgi-bin,data,templates,uploads} sudo chown -R www-data:www-data /var/www/admin sudo chmod 755 /var/www/admin/cgi-bin/*.py2. 核心功能实现2.1 系统状态监控模块创建system.py监控服务器基础指标#!/usr/bin/env python3 import cgi import psutil from datetime import datetime def get_system_stats(): return { cpu_usage: psutil.cpu_percent(), memory: psutil.virtual_memory().percent, disk: psutil.disk_usage(/).percent, uptime: str(datetime.now() - datetime.fromtimestamp(psutil.boot_time())), processes: len(psutil.pids()) } print(Content-Type: text/html\n) stats get_system_stats() print(f html headtitle系统监控/title/head body h1服务器状态概览/h1 table border1 trth指标/thth值/th/tr trtdCPU使用率/tdtd{stats[cpu_usage]}%/td/tr trtd内存使用/tdtd{stats[memory]}%/td/tr trtd磁盘空间/tdtd{stats[disk]}%/td/tr trtd运行时间/tdtd{stats[uptime]}/td/tr trtd进程数/tdtd{stats[processes]}/td/tr /table /body /html )2.2 文件管理模块files.py实现基础文件操作功能#!/usr/bin/env python3 import cgi import os import html from pathlib import Path BASE_DIR /var/www/admin/uploads form cgi.FieldStorage() action form.getvalue(action) print(Content-Type: text/html\n) print(htmlheadtitle文件管理/title/headbody) if action upload: fileitem form[file] if fileitem.filename: filename os.path.basename(fileitem.filename) save_path os.path.join(BASE_DIR, filename) with open(save_path, wb) as f: f.write(fileitem.file.read()) print(fp文件 {html.escape(filename)} 上传成功/p) elif action delete: filename form.getvalue(filename) if filename: safe_path os.path.join(BASE_DIR, os.path.basename(filename)) if os.path.exists(safe_path): os.remove(safe_path) print(fp文件 {html.escape(filename)} 已删除/p) # 显示文件列表 print(h2文件列表/h2ul) for f in sorted(Path(BASE_DIR).iterdir()): if f.is_file(): print(fli{html.escape(f.name)} - {f.stat().st_size/1024:.1f} KB f[a href?actiondeletefilename{f.name}删除/a]/li) print(/ul) # 上传表单 print( h2上传文件/h2 form methodpost enctypemultipart/form-data input typehidden nameaction valueupload input typefile namefile input typesubmit value上传 /form /body/html )3. SQLite数据库集成3.1 数据库管理界面创建dbadmin.py实现简易数据库操作#!/usr/bin/env python3 import cgi import sqlite3 from html import escape DB_PATH /var/www/admin/data/admin.db def init_db(): with sqlite3.connect(DB_PATH) as conn: conn.execute( CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY, value TEXT, description TEXT )) conn.commit() form cgi.FieldStorage() action form.getvalue(action) print(Content-Type: text/html\n) print(htmlheadtitle数据库管理/title/headbody) if action add_setting: key form.getvalue(key) value form.getvalue(value) desc form.getvalue(desc) if key and value: with sqlite3.connect(DB_PATH) as conn: conn.execute(INSERT OR REPLACE INTO settings VALUES (?,?,?), (key, value, desc)) conn.commit() print(p设置已保存/p) init_db() # 显示当前设置 print(h2系统设置/h2) print(table border1trth键/thth值/thth描述/thth操作/th/tr) with sqlite3.connect(DB_PATH) as conn: for row in conn.execute(SELECT key, value, description FROM settings): print(ftrtd{escape(row[0])}/tdtd{escape(row[1])}/td ftd{escape(row[2])}/td ftd[a href?actiondeletekey{row[0]}删除/a]/td/tr) print(/table) # 添加新设置表单 print( h2添加/更新设置/h2 form methodpost input typehidden nameaction valueadd_setting p键: input typetext namekey required/p p值: input typetext namevalue required/p p描述: textarea namedesc/textarea/p input typesubmit value保存 /form /body/html )3.2 数据库备份功能扩展dbadmin.py添加备份功能def backup_database(): backup_path f{DB_PATH}.backup.{datetime.now().strftime(%Y%m%d)} with sqlite3.connect(DB_PATH) as src, sqlite3.connect(backup_path) as dst: src.backup(dst) return backup_path if form.getvalue(action) backup: backup_file backup_database() print(fp数据库已备份到 {escape(backup_file)}/p)4. 安全加固与优化4.1 基础安全措施输入验证对所有用户输入进行消毒处理路径安全使用os.path.basename防止目录遍历攻击权限控制确保脚本以最小必要权限运行# 安全获取文件路径示例 def get_safe_path(user_input): base_dir /var/www/admin/uploads filename os.path.basename(user_input) full_path os.path.join(base_dir, filename) if not os.path.abspath(full_path).startswith(base_dir): raise ValueError(非法路径访问) return full_path4.2 性能优化技巧使用SQLite连接池减少数据库连接开销实现简单的缓存机制避免重复计算对静态资源启用浏览器缓存# 简易缓存装饰器 def cache_result(ttl60): def decorator(func): cache {} def wrapper(*args): now time.time() if args in cache and now - cache[args][time] ttl: return cache[args][value] result func(*args) cache[args] {value: result, time: now} return result return wrapper return decorator cache_result(ttl300) def get_system_stats(): # 原有实现...4.3 用户认证方案实现基础HTTP认证import base64 def check_auth(): auth os.environ.get(HTTP_AUTHORIZATION, ) if not auth.startswith(Basic ): return False auth base64.b64decode(auth[6:]).decode(utf-8) username, password auth.split(:, 1) return username admin and password securepassword if not check_auth(): print(Status: 401 Unauthorized) print(WWW-Authenticate: Basic realmAdmin Panel) print(Content-Type: text/html\n) print(h1401 Unauthorized/h1) exit()5. 功能扩展思路5.1 服务管理功能添加启动/停止系统服务的功能def service_action(service, action): if action not in [start, stop, restart]: return False try: subprocess.run([sudo, systemctl, action, service], checkTrue) return True except subprocess.CalledProcessError: return False5.2 日志查看器实现简易日志查看界面def tail_log(filepath, lines50): try: with open(filepath, r) as f: return .join(deque(f, lines)) except Exception as e: return f无法读取日志: {str(e)}5.3 计划任务管理集成crontab管理功能def list_cron_jobs(userwww-data): try: result subprocess.run([crontab, -u, user, -l], capture_outputTrue, textTrue) return result.stdout except subprocess.CalledProcessError: return 无计划任务或读取失败在实际部署中我发现将常用功能模块化后这套系统可以稳定运行在仅有512MB内存的树莓派上日均处理数百次请求毫无压力。对于需要快速搭建简单管理界面的场景这种复古方案反而展现出独特的优势。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2432081.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!