“Everything You Do Is Being Recorded”这句话放到今天不是一句网络段子而是一句工具级的描述。操作系统会记录活动历史浏览器会保留访问记录输入法会保存输入习惯AI 工具会把你的提问和文件内容一起收进对话上下文。对这些记录保持敏感不是为了陷入监控焦虑而是开发者必须理解的一种基础机制谁在记录、记录了什么、存在哪里、能不能删。这篇文章会从三个层面展开先拆解操作系统、浏览器和 AI 工具各自记录了什么再给一套可以自己运行在本地、把活动日志可视化自管自控的轻量级方案最后讲清理、脱敏和合规边界。无论你是做安全审计、想统计自己的时间都花在了哪里还是纯粹想搞清楚设备上那些行为数据到底流向哪里这篇都可以作为一次本地实践的开始。1. 行为记录能力速览先明确一个基本判断行为记录本身不是坏事坏事是记录不被用户感知、不被用户控制。下面把常见的记录层面和典型内容整理成一张表方便对照排查。记录层面典型记录内容常见存储位置用户可控程度操作系统层应用使用时间、前台窗口、登录日志、最近文件系统日志库、事件查看器中可部分关闭浏览器层历史记录、Cookie、扩展读取的页面数据浏览器用户目录中可清理或隐私模式输入法与剪贴板输入习惯、复制内容输入法服务端、系统剪贴板低存在明文字段风险AI 工具提问内容、上传文件、生成结果服务商云端或本地缓存低依赖隐私政策与本地化设置自建记录系统应用使用事件、窗口标题、时间戳自己控制的本地数据库高可删可改可迁移从开发者角度看最有价值的动作不是把记录全关掉而是把记录能力纳入自己的掌控范围知道哪些数据在产生、存在哪、以什么形式存在、能不能被第三方读取。这里先给出一套自建行为记录系统的能力速览。后面的章节会带你把最小版本跑起来。能力项说明记录范围本机应用使用事件不采集键盘明文不监听聊天内容存储方式本地 SQLite 数据库默认不联网查询方式Web 页面与简单 JSON API部署条件Python 3、一台电脑、能安装依赖适合场景个人时间统计、本地审计、活动日志分析2. 系统与应用的记录机制拆解聊行为记录先要知道现状。2.1 操作系统层系统一直在记账Windows 有活动历史记录会记录你打开过哪些应用、访问过哪些文件任务管理器里的“应用历史记录”标签页能直接看到每个应用的使用时间。Linux 这一侧更直接shell 会写~/.bash_historysystemd 日志会记下服务启动和登录事件last命令能列出最近登录记录。macOS 的“屏幕使用时间”和统一日志unified log也在做类似的事。这些机制的设计初衷是系统审计和用户体验但它们默认产生的数据量非常大。如果你从来没有主动查看过这些记录大概率你的设备里已经躺着很多“行为痕迹”。系统层记录的特点是写入位置固定普通用户不一定知道怎么清理企业管理员则可以通过组策略或 MDM 强制开启审计。2.2 浏览器与应用层记录被当成默认能力浏览器是所有本机行为记录里最直观的一层。历史记录、Cookie、indexedDB、localStorage任何一个普通用户打开开发者工具都能看到一堆数据被写进浏览器存储。第三方扩展拿到的权限更大一个能读取所有站点数据的扩展实际上可以知道你一天里打开过哪些网页、在页面上输入过什么。应用层的情况类似。即时通讯软件会保留聊天记录文档编辑器会保留最近打开的文件列表截图工具会保存历史截图。记录本身是为了使用便利但一旦应用内部保留的日志被意外上传或泄露风险就会放大。2.3 AI 工具层上下文机制决定了它必须“记住”AI 工具的行为记录跟前两者不太一样。大模型的对话能力依赖上下文窗口它需要把你的提问、上传的文件片段、系统提示词一起放进上下文才能生成回答。这意味着用户输入的内容会在推理过程中被读取和计算也可能会被服务商按隐私政策保存一段时间。如果你在输入框里贴入一段源代码、一份合同或者一张带个人信息的截图这些内容本质上已经进入了对应该工具的数据链路。了解这一点之后哪些内容适合粘贴、哪些必须在本地模型里处理、哪些需要先脱敏应该成为一种习惯。3. 环境准备与前置条件自建行为记录系统不挑机器重点是把环境拆干净避免把日志写进系统目录造成权限混乱。3.1 系统与硬件要求操作系统可以是 Windows、Linux 或 macOS。考虑到后续还要显示 Web 界面建议内存保持在 4GB 以上磁盘剩余空间在 20GB 以上。采集器和 Web 服务都跑在同一台机器时占用会很低。3.2 Python 环境建议使用 Python 3.9 及以上版本。为了避免污染系统 Python先建一个虚拟环境。python -m venv activity-env source activity-env/bin/activate # Windows 下使用 activity-env\Scripts\activate安装依赖pip install flask3.3 磁盘与日志轮转规划行为记录最大的问题是数据会持续增长。频率越高、保留越久磁盘占用越大。提前规划一个数据目录把数据库和未来可能生成的导出文件都放进去建议结构如下activity-system/ ├── app.py # 主程序 ├── collector.py # 事件采集示例 ├── requirements.txt # 依赖清单 └── data/ # 数据目录也可以挂载到 Docker 卷 └── activity.db # SQLite 数据库3.4 权限边界这套系统只记录本机、本用户的应用使用事件不监听网络流量不记录键盘明文。在正式写到采集逻辑之前先明确一条边界如果代码逻辑里需要读取密码、验证码、聊天内容这类数据说明范围已经越界应当直接删除该功能而不是试图给它做脱敏。4. 自建本地活动记录与审计面板下面给出一个最小可行的行为记录系统。它包含三个部分数据库初始化、事件写入、Web 查询接口。所有代码都是通用示例可以直接复制到本地项目里跑通。4.1 初始化数据库新建collector.py先创建一张基础的事件表。import sqlite3 from datetime import datetime DB_PATH data/activity.db def init_db(): conn sqlite3.connect(DB_PATH) conn.execute( CREATE TABLE IF NOT EXISTS events ( id INTEGER PRIMARY KEY AUTOINCREMENT, event_type TEXT NOT NULL, app_name TEXT, title TEXT, detail TEXT, created_at TEXT NOT NULL ) ) conn.commit() conn.close() def record_event(event_type, app_nameNone, titleNone, detailNone): conn sqlite3.connect(DB_PATH) conn.execute( INSERT INTO events (event_type, app_name, title, detail, created_at) VALUES (?, ?, ?, ?, ?), (event_type, app_name, title, detail, datetime.now().isoformat()) ) conn.commit() conn.close() if __name__ __main__: init_db() record_event( manual_test, app_namedemo, titleEverything You Do Is Being Recorded, detail这个事件用于验证本地记录链路 ) print(event recorded)这段代码只是演示事件入库逻辑。实际部署时采集事件的方式会因操作系统不同而变化比如 Windows 上用窗口句柄获取前台程序名Linux 上用wmctrl或xpropmacOS 上用 AppleScript。核心思路一致采集到事件后调用record_event写入数据库。4.2 启动 Web 查询接口新建app.py用 Flask 暴露一个查询接口。from flask import Flask, jsonify, request import sqlite3 app Flask(__name__) DB_PATH data/activity.db def query_events(limit50): conn sqlite3.connect(DB_PATH) rows conn.execute( SELECT * FROM events ORDER BY id DESC LIMIT ?, (limit,) ).fetchall() conn.close() return [ { id: r[0], event_type: r[1], app_name: r[2], title: r[3], detail: r[4], created_at: r[5], } for r in rows ] app.route(/api/events) def events(): limit request.args.get(limit, default50, typeint) return jsonify({events: query_events(limit)}) if __name__ __main__: app.run(host127.0.0.1, port5000)启动方式python app.py启动后访问http://127.0.0.1:5000/api/events可以看到刚写入的测试事件。4.3 curl 验证 API接口能跑通说明这套系统已经具备最基本的查询能力。用 curl 验证一下curl http://127.0.0.1:5000/api/events?limit20返回结果类似{ events: [ { id: 1, event_type: manual_test, app_name: demo, title: Everything You Do Is Being Recorded, detail: 这个事件用于验证本地记录链路, created_at: 2025-01-01T10:00:00.000000 } ] }到这里一个能记录、能查询的最小系统已经跑通。后续要接批量任务或数据导出可以直接复用这张事件表。4.4 Docker 部署模板如果你不想在宿主机上装 Python 依赖可以用 Docker 跑。下面是一份通用配置实际使用时需要把项目路径替换成你本机的绝对路径。version: 3 services: activity-web: build: . ports: - 5000:5000 volumes: - ./data:/app/data restart: unless-stopped对应的 Dockerfile 可以保持最小体积FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . VOLUME /app/data EXPOSE 5000 CMD [python, app.py]这个模板适用于任何把 SQLite 文件放在工作目录下的 Python Web 服务。数据目录通过volumes挂载出来重装容器也不用担心数据库丢失。5. 功能测试与效果验证自建系统最容易出现的问题是采集端正常、展示端报错或者反过来。下面给出一套通用验证流程照着走一遍能很快定位问题。5.1 验证事件写入先运行一次采集脚本确认没有报错。python collector.py如果看不到event recorded输出优先检查data/目录是否存在、SQLite 是否已经创建了表。Windows 上尤其要注意路径分隔符建议统一使用相对路径并保证当前工作目录正确。5.2 验证 API 查询Web 服务启动后直接在浏览器打开接口地址确认能返回 JSON。不能返回时按顺序检查四件事Flask 是否启动成功终端有没有报错。端口是否被占用换一个端口再试。数据库路径是否和采集端一致。是否有请求触发了异常但被 Flask 默认错误页挡住。5.3 判断成功的标准一个行为记录系统判断是否成功不看“能跑”而看“连续跑一段时间后数据可用”。建议用以下标准验证点通过标准事件写入数据库里能看到新时间戳数据持续时间至少记录 24 小时查询稳定性页面上连续刷新不报错数据隔离日志目录只在本地外部无法访问停止与恢复进程中断重启后数据库仍可查询5.4 扩展自动采集前台窗口如果要自动记录前台应用可以写一个系统相关的采集函数。下面是通用结构具体命令需要按平台替换def get_active_window(): # Windows 示例使用 pywin32 获取 GetForegroundWindow # Linux 示例使用 wmctrl -l 解析 # macOS 示例使用 AppleScript 获取 frontmost app return current_app_name调用侧保持不变record_event(app_switch, app_nameget_active_window(), title窗口标题)重点在于采集函数只返回应用名和窗口标题不读取窗口内部内容。一旦采集插件开始抓取验证码、密码框、聊天消息就必须停止使用。6. 开源现成工具快速落地如果你不想从零写采集器也可以直接用现成的开源行为记录工具。这个领域最典型的项目是 ActivityWatch它主打本地优先、开源、数据留在本机主打个人时间追踪和自动记录应用使用情况。使用思路通常是安装官方客户端或者用 Docker 启动本地服务会把应用使用数据写入数据库然后在浏览器打开 Web 面板查看时间线、应用分类和网页访问统计。选择这类工具时应该关注几条原则必须开源能查看代码确认数据流向。必须本地优先默认不向第三方服务器上传。数据格式可导出最好直接落 SQLite 或 JSON。项目活跃度正常至少最近一年还有发布记录。反向的提示也要给不要下载来路不明的“录屏监控工具”或“键盘记录器”。这类工具里经常混入恶意代码轻则后台挖矿重则窃取账号密码。自建行为记录系统的意义是把数据留在自己手里而不是交给另一个黑盒。7. 资源占用与数据清理行为记录系统长期运行时需要持续观察三个资源指标CPU、内存、磁盘。7.1 CPU 与内存采集端如果用轮询方式获取前台窗口CPU 占用主要来自轮询间隔。间隔越短数据越实时但占用越高。建议轮询间隔设置在 2 到 5 秒对现代 CPU 几乎没有影响。Web 服务端在只有个人访问时内存占用可以控制在很低水平。如果页面变慢先查是不是数据库增长过大导致查询变慢再考虑加索引。7.2 磁盘增长与保留策略SQLite 数据库的大小取决于事件频率和 detail 字段的长度。如果每秒记一条事件一年大约会产生 3000 多万条记录磁盘占用会明显上升。建议在采集端加数量限制def trim_events(max_rows500000): conn sqlite3.connect(DB_PATH) conn.execute( DELETE FROM events WHERE id NOT IN ( SELECT id FROM events ORDER BY id DESC LIMIT ? ) , (max_rows,)) conn.commit() conn.close()这个函数可以在每天定时任务里执行保留最近 50 万条事件避免日志无限膨胀。7.3 清理与归档如果数据有长期保存价值可以按周导出 JSON 或 CSV然后清理主表。导出时要注意脱敏窗口标题、文件名、URL 都可能包含个人信息发布或上传之前先过滤一遍。8. 常见问题与排查方法问题现象可能原因排查方式解决方案采集脚本报数据库锁错误SQLite 同时被多个进程写入查看是否有脚本重复启动用单进程采集或写入加锁Web 页面打不开端口被占用或服务未启动检查日志和端口监听更换端口或重启服务接口返回空数据数据库路径不一致对比采集端和 Web 端的 DB_PATH统一路径数据量增长过快轮询间隔太短或采集事件类型过多查看数据库总行数增加轮询间隔减少事件类型进程重启后数据丢失Docker 卷未挂载检查 docker-compose volumes 配置挂载宿主目录页面加载越来越慢数据表缺少索引查看查询耗时给 created_at 加索引磁盘被日志占满没有清理策略查看数据库文件大小添加 trim 和归档依赖安装失败Python 版本或网络问题查看 pip 报错换镜像源或升级 Python9. 隐私保护、开源协议与合规边界本地记录系统的价值是让你获得数据控制权而不是替你规避法律和伦理问题。以下几点必须明确。第一记录行为的对象边界。自己电脑上的个人行为记录属于个人对设备的合理管理。把同样的工具装到别人电脑上未经授权持续记录他人应用使用习惯就可能触碰隐私和安全红线。公司电脑上通常有统一合规审计政策个人额外部署记录工具前需要确认是否符合公司规定。第二任何与账号密码、验证码、聊天内容、人脸、声音相关的数据都不应该进入这个事件表。不是技术不允许而是风险不可控。一旦数据库文件泄露明文保存的敏感字段会让损失成倍放大。第三内容发布前的脱敏。如果后续要把活动记录导出成报告或截图分享必须先检查窗口标题、文件名、URL 中是否包含姓名、手机号、邮箱、Token 等信息。工业界常见的做法是用正则或规则引擎先打码再人工复核。第四开源协议与依赖合规。如果自己写采集器要检查依赖库是不是商用友好协议如果直接用开源工具要看它的代码有没有内置遥测上报有的话要在配置里关闭。10. 总结与下一步“Everything You Do Is Being Recorded”描述的不是某个软件的 bug而是现代系统的默认工程特性。真正值得关注的不是“有没有记录”而是“记录是否可感知、可管理、可清理”。这篇文章给出的最小版本已经能完成事件写入、本地存储和 API 查询你可以先跑通这套链路再决定要不要接入真实的前台窗口采集。如果你第一次尝试建议按这个顺序验证先把数据库和 Flask 跑通再确认数据只存在本地目录最后接入窗口标题采集观察一天的数据。最容易踩的坑是采集端和 Web 端路径不一致导致查不到数据以及数据库无限膨胀导致页面变慢。后续可以扩展的方向包括把日报自动整理成 Markdown、用 SQL 做每周使用时间统计、接入本地大模型做行为摘要、给数据库加 SQLCipher 加密。数据在自己手里这些扩展才真正可控。