
簡介這是一套面向計算機、通信、人工智能及自動化等專業學生的主機安全態勢感知系統實戰項目適用于畢業設計、期末大作業及安全方向進階學習。系統基于Python開發融合深度學習與日志分析技術可實現對SSH、HTTP、暴力破解等常見攻擊行為的實時識別與可視化呈現具備完整工程閉環能力。資源包共662個文件含15個核心Python腳本含brute_analyse、http_analyse等模塊、619個JavaScript前端交互文件支撐ECharts與ECharts-GL動態圖表渲染、以及配套HTML頁面、CSS樣式、GeoIP數據庫mmdb和多國地理數據JS文件整體壓縮后35.19MB結構清晰、模塊解耦度高。目前已有104人下載學習提供經答辯驗證99分、全鏈路調試通過的可運行代碼詳細文檔涵蓋部署指南、功能說明與關鍵算法注釋特別適合初學者理解安全態勢建模邏輯也便于進階者二次開發與功能擴展。1. 這不是“殺毒軟件界面美化”而是一套可落地的主機安全態勢感知最小閉環很多同學拿到“基于Python開發的主機安全態勢感知系統”這個畢設題目時第一反應是去GitHub搜一個帶Web界面的掃描器改改前端——結果跑起來只顯示“正在掃描中…”連進程列表都拿不到更別說判斷是否存在異常行為。實際上真正的主機安全態勢感知核心不在炫酷圖表而在能穩定采集、可解釋建模、有依據告警這三個剛性環節。它面向的是Linux/Windows服務器或開發機本地環境解決的是“我這臺機器此刻是否被植入后門有沒有異常外連關鍵服務是否被篡改”這類具體問題。本方案不依賴第三方SaaS平臺全部用標準Python庫psutil、osquery-lite封裝、scapy、yara-python實現數據采集用輕量級規則引擎json條件表達式做策略匹配用SQLite做本地狀態快照存儲避免引入Flask/Django等重量框架增加部署復雜度。適合計算機、信息安全、網絡工程專業學生在無云資源、無運維權限的條件下兩周內完成從零部署到生成首份安全態勢報告的全過程。2. 數據采集層用原生Python接口直取操作系統底層信號避開Shell命令解析陷阱主機安全態勢感知的第一道門檻是能否穩定、低開銷、跨平臺地獲取真實運行時數據。很多畢設代碼直接調用os.popen(netstat -ano)或subprocess.run([ps, -ef])看似簡單實則埋下三類隱患一是Windows/Linux命令參數不一致導致腳本崩潰二是Shell輸出格式隨系統語言/版本變化如中文Windows返回“PID”列名英文系統為“PID”但位置偏移三是無法獲取進程內存映射、文件句柄、網絡連接狀態等深層字段。我們采用分層采集策略所有數據源均通過Python原生綁定庫獲取確保字段語義統一、返回結構可序列化。2.1 進程與服務狀態psutil win32serviceWindows/ systemdLinux雙路徑psutil是跨平臺進程信息采集的事實標準但默認不暴露服務啟動類型auto/manual/disabled和依賴關系。Windows需補充pywin32獲取服務控制管理器SCM數據Linux則需解析systemctl list-units --typeservice --staterunning的JSON輸出需啟用--outputjson。關鍵代碼如下# process_collector.py import psutil import json import platform from typing import List, Dict, Any def get_running_processes() - List[Dict[str, Any]]: 統一返回標準化進程字典列表字段名與Linux/Windows保持一致 processes [] for proc in psutil.process_iter([pid, name, status, cpu_percent, memory_info, connections, create_time]): try: pinfo proc.info # 統一字段windows pid為intlinux同理name強制strstatus映射為running/stopped/zombie proc_dict { pid: int(pinfo[pid]), name: str(pinfo[name]), status: running if pinfo[status] in [running, sleeping] else stopped, cpu_percent: float(pinfo[cpu_percent]), mem_rss_mb: int(pinfo[memory_info].rss / 1024 / 1024), create_time: int(pinfo[create_time]), connections_count: len(pinfo[connections]) } processes.append(proc_dict) except (psutil.NoSuchProcess, psutil.AccessDenied, KeyError): continue return processes def get_services_status() - List[Dict[str, Any]]: Windows用win32serviceLinux用systemctl解析返回統一service結構 if platform.system() Windows: import win32serviceutil services [] # 注意此處需管理員權限否則跳過 try: for service_name in win32serviceutil.EnumServicesStatus(): services.append({ name: service_name[0], display_name: service_name[1], status: running if service_name[2] 4 else stopped, start_type: [boot, system, auto, manual, disabled][service_name[3]] }) except Exception: pass # 權限不足時返回空列表不影響主流程 return services else: # Linux: systemctl list-units --typeservice --staterunning --outputjson import subprocess try: result subprocess.run( [systemctl, list-units, --typeservice, --staterunning, --outputjson], capture_outputTrue, textTrue, timeout5 ) if result.returncode 0: units json.loads(result.stdout) return [{name: u[unit], display_name: u[description], status: running, start_type: u[load]} for u in units] except Exception: pass return []提示psutil.process_iter()必須包裹try-except否則遇到已退出進程會拋NoSuchProcess異常connections字段在Windows上需額外開啟psutil.net_connections()權限Linux默認可用。get_services_status()在非管理員權限下Windows分支會靜默失敗這是設計使然——安全采集本身就需要權限校驗畢設演示時建議在管理員CMD中運行。2.2 網絡連接與監聽端口繞過netstat用psutil.connections()直接讀取內核socket表netstat輸出需正則解析且不同系統列數不一。psutil.connections()直接讀取/proc/net/tcpLinux或GetExtendedTcpTableWindows返回結構化元組。關鍵字段包括laddr(本地地址)、raddr(遠程地址)、type(TCP/UDP)、status(LISTEN/ESTABLISHED)、pid(關聯進程ID)。以下代碼提取所有監聽端口并關聯進程名# network_collector.py import psutil from typing import List, Dict, Any def get_listening_ports() - List[Dict[str, Any]]: 獲取所有監聽端口關聯進程名過濾掉內核線程pid0 listeners [] for conn in psutil.net_connections(kindinet): if conn.status LISTEN and conn.pid ! 0: # 排除內核線程 try: proc psutil.Process(conn.pid) listeners.append({ port: conn.laddr.port, address: conn.laddr.ip or 0.0.0.0, protocol: tcp if conn.type socket.SOCK_STREAM else udp, pid: conn.pid, process_name: proc.name(), user: proc.username().split(\\)[-1] if \\ in proc.username() else proc.username() }) except (psutil.NoSuchProcess, psutil.AccessDenied): # 進程已退出或無權限讀取記錄pid但不填名稱 listeners.append({ port: conn.laddr.port, address: conn.laddr.ip or 0.0.0.0, protocol: tcp if conn.type socket.SOCK_STREAM else udp, pid: conn.pid, process_name: unknown, user: unknown }) return listeners注意psutil.net_connections()在macOS上不支持pid字段需用lsof -i -P -n替代但本畢設聚焦Windows/Linux主流教學環境macOS兼容性作為可選擴展點。address字段為0.0.0.0表示監聽所有網卡127.0.0.1表示僅本地回環——這是識別潛在風險端口如Redis未綁定127.0.0.1的關鍵依據。2.3 文件完整性校驗用hashlib對關鍵系統路徑做快照比對態勢感知需發現文件篡改但全盤哈希性能不可接受。我們聚焦/etc/passwd、/etc/shadowLinux、C:\Windows\System32\drivers\etc\hostsWindows、/usr/bin/下常用工具ls, ps, netstat等高危路徑。使用hashlib.sha256()計算文件內容哈希存入SQLite快照表每次采集時比對# file_integrity.py import hashlib import os import sqlite3 from pathlib import Path CRITICAL_PATHS [ /etc/passwd, /etc/shadow, /usr/bin/ls, /usr/bin/ps, /usr/bin/netstat, C:\\Windows\\System32\\drivers\\etc\\hosts, C:\\Windows\\System32\\notepad.exe ] def calculate_file_hash(filepath: str) - str: 計算文件SHA256忽略不存在或無權限文件 try: if not Path(filepath).exists(): return with open(filepath, rb) as f: return hashlib.sha256(f.read()).hexdigest() except (OSError, IOError): return def save_baseline(db_path: str baseline.db): 首次運行時生成基線快照 conn sqlite3.connect(db_path) conn.execute( CREATE TABLE IF NOT EXISTS file_baseline ( path TEXT PRIMARY KEY, hash TEXT NOT NULL, timestamp INTEGER NOT NULL ) ) for path in CRITICAL_PATHS: file_hash calculate_file_hash(path) if file_hash: # 僅存有效哈希 conn.execute( INSERT OR REPLACE INTO file_baseline (path, hash, timestamp) VALUES (?, ?, ?), (path, file_hash, int(time.time())) ) conn.commit() conn.close() def check_integrity(db_path: str baseline.db) - List[Dict[str, str]]: 比對當前文件哈希與基線返回變更列表 conn sqlite3.connect(db_path) cursor conn.cursor() cursor.execute(SELECT path, hash FROM file_baseline) baseline {row[0]: row[1] for row in cursor.fetchall()} changes [] for path, baseline_hash in baseline.items(): current_hash calculate_file_hash(path) if current_hash and current_hash ! baseline_hash: changes.append({path: path, status: modified, old_hash: baseline_hash, new_hash: current_hash}) elif not current_hash: changes.append({path: path, status: unreachable, old_hash: baseline_hash}) conn.close() return changes提示save_baseline()需手動執行一次生成初始快照后續check_integrity()才有效。calculate_file_hash()對大文件如/var/log/syslog應加大小限制如f.read(10*1024*1024)避免內存溢出——畢設場景下關鍵路徑文件均小于1MB故省略此步實際部署需補全。3. 規則引擎層用JSON定義檢測邏輯避免硬編碼if-else支持畢業答辯現場動態增刪規則態勢感知的核心是“什么算異?!?。硬編碼if cpu 90: alert()無法應對答辯老師“那如果我要檢測SSH暴力破解呢”的提問。我們采用聲明式規則引擎所有檢測邏輯寫在rules.json中Python加載后動態執行。規則結構包含id、name、description、source數據源名、conditionJMESPath表達式、severitylow/medium/high、actionlog/alert。JMESPath語法簡潔支持數組過濾、數值比較、字符串匹配學習成本低于自研DSL。3.1 規則定義規范與示例覆蓋進程、網絡、文件三類典型威脅rules.json示例截取關鍵片段[ { id: high_cpu_process, name: CPU占用率持續過高, description: 單個進程CPU占用超過80%持續30秒, source: processes, condition: [?cpu_percent 80], severity: medium, action: alert }, { id: suspicious_port, name: 監聽高危端口, description: 監聽端口為22SSH、3306MySQL、6379Redis且綁定0.0.0.0, source: listening_ports, condition: [?port 22 || port 3306 || port 6379] | [?address 0.0.0.0], severity: high, action: alert }, { id: hosts_modified, name: hosts文件被篡改, description: 檢測/etc/hosts或C:\\Windows\\System32\\drivers\\etc\\hosts內容變更, source: file_integrity, condition: [?status modified (contains(path, hosts))], severity: high, action: alert } ]3.2 規則執行引擎用jmespath庫解析condition避免eval安全風險# rule_engine.py import json import jmespath from typing import List, Dict, Any class RuleEngine: def __init__(self, rules_path: str rules.json): with open(rules_path, r, encodingutf-8) as f: self.rules json.load(f) def evaluate_rules(self, data: Dict[str, Any]) - List[Dict[str, Any]]: 對data字典中各source鍵執行對應規則返回匹配結果列表 alerts [] for rule in self.rules: source_key rule[source] if source_key not in data: continue # 使用jmespath.search安全執行表達式不執行任意代碼 try: result jmespath.search(rule[condition], data[source_key]) if result: # JMESPath返回非空即匹配 alerts.append({ rule_id: rule[id], rule_name: rule[name], matched_data: result if isinstance(result, list) else [result], severity: rule[severity], timestamp: int(time.time()) }) except jmespath.exceptions.JMESPathError as e: # condition語法錯誤記錄日志但不中斷 print(fRule {rule[id]} JMESPath error: {e}) continue return alerts # 使用示例 if __name__ __main__: # 假設已采集數據 collected_data { processes: get_running_processes(), listening_ports: get_listening_ports(), file_integrity: check_integrity() } engine RuleEngine() alerts engine.evaluate_rules(collected_data) for alert in alerts: print(f[{alert[severity].upper()}] {alert[rule_name]}: {len(alert[matched_data])} items matched)注意jmespath.search()比eval()安全萬倍它只解析查詢語法不執行Python代碼。condition中[?cpu_percent 80]是合法JMESPath[?name python cpu_percent 90]也支持。若需更復雜邏輯如“過去5分鐘平均CPU70%”可在數據采集層預計算滑動窗口指標再交由JMESPath過濾。3.3 規則熱加載與調試答辯時現場修改JSON立即生效畢設答辯常被要求“現場演示新增規則”。傳統硬編碼需改Python再重啟而JSON規則可做到熱加載# main.py 中的采集循環 import time import threading def run_monitoring(): engine RuleEngine() # 初始化一次 while True: # 每30秒采集一次 collected_data { processes: get_running_processes(), listening_ports: get_listening_ports(), file_integrity: check_integrity() } # 每次都重新讀取rules.json支持熱更新 engine.rules json.load(open(rules.json)) alerts engine.evaluate_rules(collected_data) # 輸出到控制臺答辯演示 for alert in alerts: print(f\033[91mALERT [{alert[severity]}] {alert[rule_name]}\033[0m) for item in alert[matched_data][:3]: # 只打印前3條避免刷屏 print(f → {item}) time.sleep(30) # 啟動監控線程 threading.Thread(targetrun_monitoring, daemonTrue).start()提示daemonTrue確保主線程退出時子線程自動結束避免答辯結束程序卡死。print()用ANSI顏色碼\033[91m標紅高危告警視覺沖擊力強符合答辯場景需求。4. 態勢聚合與報告生成用SQLite存狀態快照用Jinja2渲染HTML報告告別Excel手工整理采集和告警只是起點態勢感知要求回答“這臺機器整體安全水位如何哪些風險在惡化歷史趨勢怎樣”。我們不引入Elasticsearch等重型組件而是用SQLite存儲時間序列快照 Jinja2模板生成靜態HTML報告既滿足畢設交付物要求可打包提交的獨立HTML文件又具備分析能力。4.1 SQLite數據庫設計三個核心表支撐態勢演進分析創建security_state.db含三張表表名字段說明snapshotid(PK), timestamp, hostname, os_version, total_processes, listening_ports_count, high_cpu_count, file_modified_count每次采集的宏觀快照alertsid(PK), snapshot_id(FK), rule_id, severity, matched_json, created_at每次觸發的原始告警詳情matched_json存JSON字符串trendid(PK), metric_name, value, timestamp用于繪制趨勢圖的指標如cpu_max_5min,ports_opened建表SQLdb_init.pyimport sqlite3 def init_database(db_pathsecurity_state.db): conn sqlite3.connect(db_path) conn.execute( CREATE TABLE IF NOT EXISTS snapshot ( id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER NOT NULL, hostname TEXT NOT NULL, os_version TEXT NOT NULL, total_processes INTEGER DEFAULT 0, listening_ports_count INTEGER DEFAULT 0, high_cpu_count INTEGER DEFAULT 0, file_modified_count INTEGER DEFAULT 0 ) ) conn.execute( CREATE TABLE IF NOT EXISTS alerts ( id INTEGER PRIMARY KEY AUTOINCREMENT, snapshot_id INTEGER NOT NULL, rule_id TEXT NOT NULL, severity TEXT NOT NULL, matched_json TEXT NOT NULL, created_at INTEGER NOT NULL, FOREIGN KEY(snapshot_id) REFERENCES snapshot(id) ) ) conn.execute( CREATE TABLE IF NOT EXISTS trend ( id INTEGER PRIMARY KEY AUTOINCREMENT, metric_name TEXT NOT NULL, value REAL NOT NULL, timestamp INTEGER NOT NULL ) ) conn.commit() conn.close()4.2 快照入庫與趨勢計算將離散告警轉化為連續態勢指標每次采集后不僅存原始數據更要計算衍生指標# report_generator.py import sqlite3 import json import platform from datetime import datetime def save_snapshot_and_alerts(db_path: str, collected_data: dict, alerts: list): conn sqlite3.connect(db_path) cursor conn.cursor() # 插入快照 hostname platform.node() os_ver f{platform.system()} {platform.release()} total_procs len(collected_data.get(processes, [])) listening_ports len(collected_data.get(listening_ports, [])) high_cpu_count len([p for p in collected_data.get(processes, []) if p.get(cpu_percent, 0) 80]) file_modified_count len([f for f in collected_data.get(file_integrity, []) if f.get(status) modified]) cursor.execute( INSERT INTO snapshot (timestamp, hostname, os_version, total_processes, listening_ports_count, high_cpu_count, file_modified_count) VALUES (?, ?, ?, ?, ?, ?, ?), (int(time.time()), hostname, os_ver, total_procs, listening_ports, high_cpu_count, file_modified_count) ) snapshot_id cursor.lastrowid # 插入告警 for alert in alerts: cursor.execute( INSERT INTO alerts (snapshot_id, rule_id, severity, matched_json, created_at) VALUES (?, ?, ?, ?, ?), (snapshot_id, alert[rule_id], alert[severity], json.dumps(alert[matched_data]), alert[timestamp]) ) # 計算并插入趨勢指標示例高CPU進程數 cursor.execute( INSERT INTO trend (metric_name, value, timestamp) VALUES (?, ?, ?), (high_cpu_processes, float(high_cpu_count), int(time.time())) ) conn.commit() conn.close()4.3 HTML報告生成用Jinja2模板嵌入圖表支持答辯PPT直接截圖report_template.html精簡版!DOCTYPE html html headtitle主機安全態勢報告/title stylebody{font-family:Arial,sans-serif;margin:20px}table{border-collapse:collapse;width:100%}th,td{border:1px solid #ddd;padding:8px;text-align:left}/style /head body h1主機安全態勢報告/h1 p生成時間{{ now }}/p p主機名{{ hostname }} | 操作系統{{ os_version }}/p h2宏觀態勢概覽/h2 table trth指標/thth當前值/thth7日均值/th/tr trtd運行進程數/tdtd{{ snapshot.total_processes }}/tdtd{{ avg_processes }}/td/tr trtd監聽端口數/tdtd{{ snapshot.listening_ports_count }}/tdtd{{ avg_ports }}/td/tr trtd高CPU進程數/tdtd{{ snapshot.high_cpu_count }}/tdtd{{ avg_cpu }}/td/tr /table h2最新告警最近10條/h2 {% for alert in recent_alerts %} div stylebackground:#ffebee;padding:10px;margin:5px 0 strong[{{ alert.severity|upper }}]/strong {{ alert.rule_name }}br small{{ alert.matched_data|length }}項匹配{{ alert.matched_data|first|tojson|truncate(100) }}/small /div {% endfor %} h2歷史趨勢高CPU進程數/h2 !-- 此處可嵌入Chart.js圖表畢設簡化用文字描述 -- p過去24小時高CPU進程數峰值{{ max_cpu_last24h }}均值{{ avg_cpu_last24h }}/p /body /html生成報告代碼# generate_report.py from jinja2 import Template import sqlite3 import json from datetime import datetime, timedelta def generate_html_report(db_pathsecurity_state.db, output_pathreport.html): conn sqlite3.connect(db_path) cursor conn.cursor() # 獲取最新快照 cursor.execute(SELECT * FROM snapshot ORDER BY timestamp DESC LIMIT 1) snap cursor.fetchone() if not snap: return # 計算7日均值 week_ago int((datetime.now() - timedelta(days7)).timestamp()) cursor.execute(SELECT AVG(total_processes), AVG(listening_ports_count), AVG(high_cpu_count) FROM snapshot WHERE timestamp ?, (week_ago,)) avg_vals cursor.fetchone() # 獲取最近10條告警 cursor.execute( SELECT a.rule_id, r.name as rule_name, a.severity, a.matched_json, a.created_at FROM alerts a JOIN (SELECT id, name FROM rules) r ON a.rule_id r.id ORDER BY a.created_at DESC LIMIT 10 ) recent_alerts [] for row in cursor.fetchall(): recent_alerts.append({ rule_id: row[0], rule_name: row[1], severity: row[2], matched_data: json.loads(row[3]), created_at: row[4] }) # 計算24小時趨勢 day_ago int((datetime.now() - timedelta(hours24)).timestamp()) cursor.execute(SELECT MAX(value), AVG(value) FROM trend WHERE metric_name high_cpu_processes AND timestamp ?, (day_ago,)) trend_vals cursor.fetchone() conn.close() # 渲染模板 with open(report_template.html) as f: template Template(f.read()) html template.render( nowdatetime.now().strftime(%Y-%m-%d %H:%M:%S), hostnamesnap[2], os_versionsnap[3], snapshot{ total_processes: snap[4], listening_ports_count: snap[5], high_cpu_count: snap[6], file_modified_count: snap[7] }, avg_processesround(avg_vals[0], 1) if avg_vals[0] else 0, avg_portsround(avg_vals[1], 1) if avg_vals[1] else 0, avg_cpuround(avg_vals[2], 1) if avg_vals[2] else 0, recent_alertsrecent_alerts, max_cpu_last24hint(trend_vals[0]) if trend_vals[0] else 0, avg_cpu_last24hround(trend_vals[1], 1) if trend_vals[1] else 0 ) with open(output_path, w, encodingutf-8) as f: f.write(html) print(fReport generated: {output_path}) if __name__ __main__: generate_html_report()提示答辯時只需運行python generate_report.py即可生成report.html。打開瀏覽器查看所有數據來自本地SQLite無需網絡確保演示環境純凈。若需圖表可引入chart.js在模板中添加canvas但純文字版已滿足畢設基礎要求。5. 畢設交付與答辯技巧三個必做動作讓老師一眼看到技術深度畢業設計評審最怕“看起來很熱鬧細看全是調API”。要讓老師快速認可工作量和技術含量必須在交付包和答辯陳述中突出三個硬核動作5.1 交付包結構必須體現工程化思維拒絕“一堆py文件扔根目錄”標準交付目錄結構host-security-situation/├── README.md # 含環境要求、啟動命令、規則修改指南、截圖示例 ├── requirements.txt # 明確列出psutil5.9.5 jmespath1.0.1等精確版本 ├── config/ │ ├── rules.json # 預置10條規則含注釋說明每條檢測邏輯 │ └── baseline.db # 已初始化的文件基線數據庫 ├── src/ │ ├── __init__.py │ ├── collector/ # 數據采集模塊 │ │ ├── __init__.py │ │ ├── process_collector.py │ │ ├── network_collector.py │ │ └── file_integrity.py │ ├── engine/ │ │ ├── __init__.py │ │ └── rule_engine.py # 規則引擎核心 │ ├── database/ │ │ ├── __init__.py │ │ └── db_init.py # 數據庫初始化 │ └── report/ │ ├── __init__.py │ ├── report_template.html │ └── generate_report.py ├── scripts/ │ ├── setup_baseline.py # 首次運行生成基線 │ └── start_monitor.py # 主監控入口含熱加載邏輯 └── docs/ └── design_doc.md # UML類圖用PlantUML語法、數據流圖、規則設計說明注意requirements.txt必須用pip freeze requirements.txt生成而非手寫。答辯時老師可能檢查psutil版本是否與process_collector.py中psutil.process_iter([connections])兼容——5.9.0才支持該參數舊版本會報錯。5.2 答辯演示必須包含“規則動態增刪”和“基線重置”兩個高光時刻老師最想驗證你是否真懂原理而非復制粘貼。準備兩段1分鐘演示動態增規則打開config/rules.json新增一條檢測powershell.exe異常網絡連接的規則Windows專屬保存后觀察控制臺30秒內打印新告警。強調“規則引擎不重啟靠每次循環重讀JSON實現熱加載這是生產環境常見做法?!被€重置故意修改C:\Windows\System32\drivers\etc\hosts加一行127.0.0.1 evil.com運行python scripts/setup_baseline.py重建基線再運行監控——告警消失。說明“文件完整性檢測依賴可信基線基線必須在干凈系統上生成這模擬了企業安全運維中‘黃金鏡像’的概念。”5.3 技術難點表格化呈現直擊評審關注點在PPT最后一頁用表格總結技術難點與解法避免口語化描述評審關注點你的解法為什么比別人強跨平臺兼容性psutil統一進程采集 Windows/Linux雙路徑服務檢測避免subprocess調用Shell命令導致的解析失敗字段語義完全一致規則可維護性JSON定義 JMESPath引擎支持答辯現場修改不用改Python代碼降低維護成本體現軟件工程思想數據持久化SQLite存儲快照告警趨勢生成靜態HTML報告無需部署數據庫服務單文件交付符合畢設輕量級要求安全采集權限Windows服務檢測自動降級權限不足時跳過、Linux進程連接數統計用psutil而非netstat明確處理權限邊界不因權限問題導致整個系統崩潰提示答辯時指著表格說“老師這四個點是我們重點攻克的比如第三點很多同學用Excel手工整理數據而我們實現了自動化的態勢報告生成點擊這里就能導出HTML——請看屏幕?!?然后切換到已生成的report.html放大展示“最新告警”區塊。本文還有配套的精品資源點擊獲取