资讯动态

亲手造一套纯文本+SQLite的‘caveman‘效率工具

发布时间:2026/10/15 9:44:43 来源:尧图企业网站定制
1. 我为什么要亲手造一套caveman工具caveman不是什么怀旧游戏也不是洞穴主题餐厅而是我给自己那套原始人式效率工具集起的代号。起因挺简单我受够了被各种现代化工具来回折腾决定把自己平时的笔记、待办、记账、监控这类杂事全部用最土、最笨、最直白的方式重新做一遍。结果意外地发现当我把工具链砍到只剩纯文本、shell脚本和一个SQLite文件时效率不但没有下降反而稳定得让人安心。这个项目从起念到能用大概花了三个周末。core需求非常明确没有图形界面不依赖云服务不引入任何常驻后台进程所有操作都在终端里完成。我给它起名caveman就是因为这套东西的智力含量约等于一个原始人用石头砸开坚果用简单的规则处理信息能今天跑通的绝不放到明天。听起来很简陋对吧但正是这种简陋让我重新理解了够用到底意味着什么。文章不想讲宏大的道理就聊聊这个项目从选型到落地的完整过程以及里面每个设计背后的原因。如果你也处在工具一大堆、真正常用的没几个的状态或者想把手头那些重复性操作收拢成几个一眼就懂的脚本我的踩坑经历应该会对你有用。1.1 被工具绑架的那些年复杂工具链的失控现场先说说我为什么决定要返祖。去年我有段时间同时用着七八个工具Notion记笔记Trello管任务Google Sheets做记账再加上各种浏览器收藏夹、微信收藏、朋友圈置顶、公司内部wiki……数据散落得到处都是。每次想找一个东西第一反应不是搜索而是回忆我当时存到哪里了。更麻烦的是这些工具各有各的登录方式、同步策略、Markdown语法、导出格式一旦某个服务调整界面或者开始收费我就得花大力气搬家。真正让我崩溃的是一次Notion的同步冲突。某个周末我在高铁上改了半天的方案结果到晚上发现APP端和网页端各保留了一版冲突副本我凭印象手动合了四十多分钟最后还漏掉两段。那一刻我就想如果当初只是存在一个txt文件里这个问题根本不存在。文件在我手里谁也抢不走也不需要网络才能读取。于是我开始认真琢磨如果不用这些现代工具我到底会损失什么后来发现一个文本文件、一个grep命令、一个普通的vim/emacs/gedit就已经能覆盖我80%的笔记需求。我把之前散落在各处的笔记统一落盘到~/notes目录每个条目就一个markdown文件。查找时用grep -rni 关键词 ~/notes三秒出结果而且结果里会明确告诉你是在哪个文件哪一行比很多笔记软件的模糊搜索还要直接。1.2 原始人思路少零件、快反馈、随时扔掉重写原始人这个词包含两层意思一是工具形态足够原始二是心态也足够原始。工具形态原始指的是不用很重的框架和架构所有脚本加起来不超过三百行每一行我都能解释清楚它在干嘛。心态原始指的是不追求构建一个永久系统而是把它当作一个随时可以扔掉重来的原型。反正核心数据就是几个文本文件脚本坏了就重写重写成本不超过一个晚上。这个心态非常重要。很多个人项目之所以烂尾就是一开始想得太大要支持插件、要适配移动端、要有权限体系、要单元测试覆盖。对于自己一个人用的工具这些全是负担。我在做caveman时给自己定了几条铁律单个脚本尽量控制在100行以内所有配置文件用纯文本每个脚本的输出必须是我能一眼看懂的英文单词或数字如果某个功能半天想不清楚说明它本身够复杂就先不做。结果就是我得到了一个非常糙但非常可用的工具集并且因为它糙我改起来没有任何心理负担。2. caveman 的第一块基石纯文本与文件系统开搞之后第一件事是确定数据怎么存。我几乎没怎么犹豫就选了普通目录 普通文件的组合。一级目录就三个notes放笔记todo放待办事项records放结构化记录。这一切都没有数据库服务没有独立的app没有云同步就是最朴素的文件系统。有人可能会问这算哪门子项目其实很多所谓生产力工具解决的本来就不是技术问题而是习惯问题。当你把数据摊在文件系统里所有操作都变成了对文件的增删改查这种透明感让人非常踏实。2.1 为什么是纯文本搜索、备份、兼容性纯文本最大的优势是三个搜索快、备份容易、永不淘汰。先说搜索。文本文件的检索不需要建索引直接用系统自带的grep就够了。我笔记本上有两千多个markdown文件全量搜索一般也就一两秒这是正则表达式加文件系统缓存的功劳而且匹配到的每一行都能立刻跳转。其次是备份。一个tar或rsync命令就能完整快照还可以丢进git仓库进行历史回溯。这比任何导出功能都可靠因为导出的永远是一个系统自己定义的格式而文件系统本身就是通用接口。最后一个优点容易被忽视兼容性。今天你在一台没有图形界面的服务器上只需要一个SSH客户端就能读取全部的笔记和待办。你不用担心某个APP停止维护不用担心导入导出格式变来变去因为这些文件五十年后打开还是一堆字符。我的习惯是给每个笔记文件命名带日期和关键词比如2024-11-20-sqlite-notes.md这样光靠文件名就能过滤出很大一部分内容连内容扫描都不用做。2.2 笔记模块grep 就是我的搜索引擎我把笔记这块做成了一个约五十行的bash脚本放在了~/bin/note。它模仿了老派wiki的做法支持新建、搜索、列出标签三种动作。最核心的函数非常简单note() { local dir${HOME}/notes mkdir -p $dir case $1 in new) local fname$dir/$(date %Y%m%d)-$2.md if [ ! -f $fname ]; then echo # $2 $(date %Y-%m-%d) $fname fi $EDITOR $fname ;; s|search) shift grep -rniE --coloralways $* $dir | head -50 ;; tag) grep -rhE ^#[a-zA-Z0-9_] $dir | sort | uniq -c | sort -rn ;; *) echo usage: note {new title|s keyword|tag} ;; esac }使用习惯也很原始每天新建一个daily笔记脑子里想到什么就记什么格式完全自由。需要归档的时候通过note new 文章标题建独立页面把相关内容从daily里拷进去。标签不是强制体系只是约定在正文里写#tag这种形式然后用note tag统计出现频率。这个方案没有自动联想、没有双向链接但作为一个思考的排水沟它比很多所谓的第二大脑更随手。2.3 待办模块一个 bash 函数管理全部状态待办事项的原始版更简单一个目录~/todo里面按状态分成open/和done/两个子目录每个事项是一个文本文件。完成一个任务就是把文件从open移动到done。这个方案的好处是任务状态的变化变成了文件操作永远不会出现数据不一致。我写了个todo函数来封装操作todo() { local base${HOME}/todo case $1 in add) shift echo $(date %Y-%m-%d %H:%M) $* $base/open/$(date %s).txt ;; list) for f in $base/open/*.txt; do # 输出文件修改时间和首行内容 echo $(stat -c %y $f 2/dev/null | cut -d. -f1) $(cat $f) done | sort | nl ;; done) shift for n in $; do local target target$(ls $base/open/*.txt | sed -n ${n}p) if [ -n $target ] ; then mv $target $base/done/ fi done ;; *) echo usage: todo {add|list|done n} ;; esac }用的时候就是三条命令todo add 写周报todo listtodo done 3 5。任务内容、创建时间、完成时间全部保留在文件名和内容里。也许有人觉得没有优先级、没有提醒、没有打卡很可惜但我的经验是对于一个人来说一条清单如果超过两个小时没看放在哪个工具里都会被遗忘。与其追求花哨的排序不如让清单够短、够可见。3. caveman 的第二块基石SQLite 做结构化数据纯文本能解决记录问题但解决不了统计问题。比如记账每次消费都记成文本文件当然可以但月底想算我在餐饮上花了多少钱就会很痛苦。这类有明确字段、需要汇总计算的数据我统一交给SQLite处理。SQLite就一个文件一个命令行工具不占内存不需要账号。在caveman项目里records/cash.sqlite负责记账records/reading.sqlite记录读书和观影每类一个库互不干扰。3.1 为什么用 SQLite 而不是 MySQL / 其他理由只有一条省心。MySQL、PostgreSQL需要安装服务、管理用户权限、配置端口稍有差池就会收到一张拒绝连接的告警。而SQLite就是文件系统里的一个二进制文件它遵守ACID事务支持标准的SQL语法日常个人数据几个GB以内完全没有压力。更关键的是SQLite的备份就等于复制文件我在cron里每天半夜拷贝一次这就完成了备份。要是哪天真出了什么问题我这里还有最近七天的副本自己人用回滚成本几乎为零。实际使用中我甚至不需要装额外的GUI工具。通过命令行sqlite3即可完成建表、插入、查询。对于习惯写SQL的人来说这比任何记账软件的报表功能都灵活。我还可以随时用Python读取这个库画点简单的趋势图自由度极高。3.2 记账流水模块从支出记录到月度汇总记账的表结构我设计得很朴素CREATE TABLE ledger ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts TEXT NOT NULL DEFAULT (datetime(now, localtime)), category TEXT NOT NULL, amount_cents INTEGER NOT NULL, note TEXT ); CREATE INDEX idx_ledger_ts ON ledger(ts);金额用分存整数避免浮点误差。每次消费后我用一个shell别名快速添加alias spentsqlite3 ~/records/cash.sqlite INSERT INTO ledger(category, amount_cents, note) VALUES(...)当然真正的录入函数比这个复杂一些会做参数解析比如spent food 35 午餐就能直接插入一条记录。月底想知道支出构成一句SQLSELECT category, printf(%.2f, SUM(amount_cents) / 100.0) AS total FROM ledger WHERE strftime(%Y-%m, ts) strftime(%Y-%m, now, localtime) GROUP BY category ORDER BY total DESC;输出就是一张清晰的表格。我也可以随时查这个月一共花了多少、周一到周五平均餐饮支出这类问题每个问题一行SQL搞定。效率远高于打开一个记账APP点开报表选择时间范围再等它转圈。3.3 数据备份直接复制一个文件就能跑个人工具最容易被忽略的一点就是备份。很多APP自带云同步看起来安全但一旦服务商出问题你的数据就跟着遭殃。caveman的做法是每天晚上用一个定时任务把整个~/records和~/notes压缩打包丢到一块移动硬盘和一个对象存储桶里。命令简单到不用解释tar czf backup-$(date %F).tar.gz -C $HOME notes records备份文件带上日期再写一个保留最近十四份的清理逻辑。整个过程完全没有技术含量但它稳定运行了几个月救我两次。一次是我误删了某个笔记目录直接从压缩包里抽回来另一次是SQLite文件损坏好在备份只有几个小时的延迟丢的内容不多。这让我越发相信数据安全不是靠高级功能而是靠坚持执行最笨的方案。4. 自动化也可以很原始人cron 与 curl 的微监控工具集里最唬人的部分可能是监控自动化。一般公司会买APM、监控平台或者用Prometheus加一堆exporter。但自己的小项目尤其是部署在个人服务器上的几个服务只需要在cron里跑一个十行的shell脚本定期检查HTTP接口状态出问题发条通知就够了。我管这叫微监控意思是不需要把它做成一个系统只需要让异常发出声音。4.1 健康检查脚本十分钟搞定监控平台要做的事下面这个脚本是我实际在用的检查三个URL是否返回正常状态码#!/usr/bin/env bash set -euo pipefail URLS( https://api.example.com/health https://blog.example.com/ https://search.example.com/status ) for url in ${URLS[]}; do code$(curl -L -s -o /dev/null -w %{http_code} --max-time 10 $url || true) if [ $code ! 200 ]; then echo $(date %F %T) [$url] error, http_code$code ${HOME}/logs/check_url.log # 调用后续的通知函数 notify_me 服务异常: $url 返回 $code fi done逻辑一目了然循环遍历URL用curl拿到状态码只要不是200就记录日志并通知。没有复杂的依赖没有守护进程cron每五分钟执行一次。它唯一的弱点是没有历史趋势但对个人服务来说现在还活着吗往往比过去两个小时的性能趋势重要得多。4.2 如何让脚本在深夜不炸set -euo pipefail 与日志很多人写shell脚本喜欢随缘结果脚本在凌晨三点因为一个小问题挂掉连自己的异常状态都没人知道。我的经验是开三个开关set -e出错即停、set -u变量未定义即报错、set -o pipefail管道中任一步出错都算失败。这三件套能让脚本从大概能用变成出错就响亮地挂。加上set -e如果curl因为网络超时返回非零脚本会直接退出被我捕获到一个外层的cron守护逻辑里然后单独告警。日志也很讲究。脚本必须把正常的执行痕迹写到日志文件中这样第二天怀疑什么时可以查看~/logs/下的文件。尤其是cron执行没有终端界面所有输出默认会被丢进系统黑洞必须重定向到文件里再排查。我现在每个定时任务都是这么写的0 */6 * * * $HOME/bin/caveman_check.sh $HOME/logs/caveman_check.log 21这行cron表项的意思很直白每六个小时运行一次将标准输出和错误输出统统追加到同一个日志文件里。日志是你的时间机器任何脚本问题最后都要回到日志里去定位。4.3 把通知接到即时消息curl 一条 webhook 就够所谓发出声音最轻的实现方式是发到聊天工具的webhook。以企业微信、钉钉、Slack之类的群机器人为例本质上就是向一个特殊URL发送POST请求文本内容随便写。写个函数notify_me() { local text$1 curl -s -X POST https://your-webhook.example.com/hook \ -H Content-Type: application/json \ -d {\msgtype\:\text\,\text\:{\content\:\[caveman] ${text}\}} || true }这样任何异常都会推送到我手机的群消息里。整个过程没有用消息队列没有用推送SDK就一个curl。你可能觉得这也太简陋了但对于监控三个URL和一个数据库备份任务来说它完美工作。我从这套方案里学到一件事告警的可达性取决于两者的距离而不是链路长度。消息从服务器直接到聊天App中间只有一个webhook出故障的概率极低。5. 当原始人方案失效时边界与升级路径每种方案都有自己的适用半径。caveman这套东西好归好但它只适合一个人、低并发、天真地假设自己永远不会忘的场景。如果让我重新把它用于团队协作或更大的数据规模我肯定会踩坑。这里专门聊边界是想给想模仿的朋友一句忠告能否识别工具的局限比工具本身更重要。5.1 完全不建议当原始人的场景第一个场景就是团队协作。假设你和一个同事需要同时编辑同一批待办清单纯文件方案一定会遇到你改了A文件他改了A文件改谁的这种问题。虽然可以用Git去合并但会让日常操作变得比用工具本身还繁琐。第二个场景是需要复杂权限控制的数据比如用户访问记录、涉及财务审计的数据最好还是用带事务和权限管理的正经数据库系统。第三个场景是数据量增长到几十万条以上检索速度开始下降这时可能需要给SQLite建更多索引或者切换到真正的数据库服务。这些都不是原始人该硬扛的活。5.2 给caveman加一层轻量web界面可选后来我还是没忍住给caveman加了一个非常薄的Web界面用来在手机浏览器里查看笔记和记账统计。没有用重型前端框架就是从SQLite里生成一个JSON再用一个Python内置的HTTP服务器套一层极简HTML。这样做的好处是保留了文件系统为主的内核Web界面只是一个外观终端。就算整个Web服务崩掉也不影响我通过SSH直接访问原始数据。这个思路我觉得很值得借鉴核心数据永远用最通用的形态保存界面只是上层的一个可选附件。5.3 数据量变大时的应对从脚本到真正的服务如果有一天caveman的数据量大到shell脚本扛不住我自己规划的升级路径是数据层保留SQLite但增加更细的索引和归档策略服务层把监控、笔记同步、统计查询拆成独立的小服务展示层可以换成任何想用的前端。但即使升级核心原则不变——一切仍然可以由几个配置文件和一个可执行目录描述不引入无法掌控的复杂系统。换句话说升级应该像从石器换成青铜器而不是直接跳到全自动机械臂。6. 从caveman项目中沉淀的五条原则这个项目做完我更坚定了一些观念。这些观念可能早就有人说过但我是在亲手把东西做砸、修好、扔掉、重做的过程中真正理解的。写在这里既是整理也是给后来者的一点参考。6.1 能用十行写完绝不用一个框架我最初的todo管理是直接用在线看板工具后来发现只需要一个目录移动操作就能实现同样效果。面对一个需求先问最简单的形态长什么样而不是哪个工具比较强大。很多时候最简单的形态是一段bash或几条命令而不是一个打开的网站。6.2 输入输出必须可见caveman里每个脚本都有清晰的输出笔记搜索会打印文件名和行号待办列表会按序号排列监控脚本会把错误码写日志。绝不写那种很成功但没有任何输出的脚本。这样即使六个月后忘光了当时的逻辑看一眼输出就能回忆起来。可观测性不是监控平台的特权脚本时代就该焊死在设计里。6.3 每个工具只解决一个问题我把记账、待办、笔记、监控都拆成了各自独立的脚本它们之间唯一的关联是都在同一个用户目录下。这种隔离的好处是你可以随意替换其中任何一个而不必担心破坏其他部分。比如想把记账系统换成睡午觉前用手机记录的APP只需要导出SQLite数据其他模块完全不受影响。6.4 失败要立刻发出声音无论是cron任务还是健康检查只要出了异常都必须有一个我能感知的告警。沉默的失败比明确的报错可怕十倍。这套原始人工具里我宁可收到十条误报也不容忍一个异常被吞进/dev/null。6.5 花时间设计扔掉而不是设计长生最后一条是心态上的。caveman的每一个脚本都假设将来会被重写。没有深奥抽象层没有可扩展的插件系统只有简单到不配被维护的逻辑。正因为如此我每次想改点什么时都毫不犹豫改坏了就删掉重来。这种感觉和用大型工具时这功能在设置里找了半天还得查手册完全相反。作为一个独立折腾的人我更愿意拥抱这种随时可以归零的自由。caveman项目到今天还在继续跑着。它没有什么技术含量也拿不上台面去展示架构设计但它是我自己的数字生活基底稳定、透明、可控。如果你也整天被工具折腾不妨试着给自己造一把石斧把最核心的那几件事攥回手里。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑