beancount-gs 一款 self-hosted 复式记账程序,简化你的记账方式!

目录

本程序将部署在 macOS 上,不使用 Docker(mac 上的 Docker 太卡了)

动机

我利用 beancount 来记账已经有一段时间了,但有些痛点问题困扰着我:

  • 没有 web 界面,fava 真的只能用来展示和分析且不好理解,需要有一个方便记账的界面
  • text 记账的方式,在 vscode 插件能力有限的情况下,很容易忘记 assets 和 expenses 到底叫啥名,如果有 web 界面那么一定会好很多,一个下拉列表就可以解决

有没有解决方案,不需要自己造轮子的那种?

  • 有!beancoutn-gs ,最近还在更新,就喜欢长期维护的!

主旨

下载与编译

我手头就一台 intel 的 MBP,不想装虚拟机,也绝不会想用 Docker Desktop(用过的都知道有多么卡和费电)。

因此,我的需求就是将程序作为服务直接在 mac 上跑,这不跟 Linux 的服务一个样么,多好啊。

pip3 install beancount

git clone https://github.com/BaoXuebin/beancount-gs.git

beancount-gs

go build

完事,golang 就是好用啊!

我对源码中的监听端口做了修改,同时注释掉了打开浏览器的操作:

Untitled

还加入了环境变量的设置,防止找不到我的 beancount:

Untitled

请将编译好的可执行文件放到 /opt/beancount-gs/ 文件夹中。

还有很重要的事情是,把源码中编译好的前端文件夹 public 、 config 和 template 也 copy 到 /opt/beancount-gs/ 文件夹中,不然访问时啥也没有。

Untitled

开机自启动

launchd 是 macOS 内核装载后启动的第一个进程,类似 Linux 的1号进程。

Linux 中咱们是编写服务,然后使用 systemctl enable xxx 实现的。

编写 plist 文件

Plist 的全称是 Property lists 。

Untitled

类似的,macOS 就需要编写 plist 文件,放到用户登录后的 ~/Library/LaunchAgents 中:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>beancount-gs</string>
        <key>ProgramArguments</key>
        <array>
            <string>/opt/beancount-gs/beancount-gs</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>WorkingDirectory</key>
        <string>/opt/beancount-gs/</string>
        <key>StandardOutPath</key>
        <string>/opt/beancount-gs/beancount-gs.log</string>
        <key>StandardErrorPath</key>
        <string>/opt/beancount-gs/beancount-gs.log</string>
    </dict>
</plist>

这个就不用解释了吧,xml 文件就是写了一些键值对配置和启动的命令~

载入 plist 文件

man launchctl 查看用法吧

launchctl load -w /Users/yuhanliu/Library/LaunchAgents/beancount-gs.plist
# launchctl unload -w /Users/yuhanliu/Library/LaunchAgents/beancount-gs.plist
# launchctl bootstrap user/501 ~/Library/LaunchAgents/beancount-gs.plist
# id -u yuhanliu 

launchctl start beancount-gs
# launchctl stop beancount-gs

Untitled

访问

Untitled

中间居然出现好多问题,这个程序的健壮性不是很强啊:

Untitled

我还要手动新建文件夹和对应的文件……

Untitled

参考文章

前言 · 语雀

Mac 开机自启动

comments powered by Disqus

相关文章

什么软件才能让你的 macOS 更好用?

动机 起因是我重置了系统,然后发现过去的习惯都要重新来一遍,于是为什么不写一篇文章呢? brew install --cask microsoft-edge calibre sogouinput mos snipaste iina iterm2 rectangle 这里先给出一份 CheckList: 软件 clash for windows homebrew microsoft onenote & outlook & edge wechat & qq sogouinput、微信输入法 Desktop Pets:App Store 上的有趣软件,养一个电子宠物吧 Notion:必备人生管理软件,管理你的任务、物品、健身情况等,自定义能力超强的数据库 阿里云盘:不限速云盘 Calibre:电子书管理器 mos: 鼠标与触控板方向不一致的解决方案 Snipaste:截图贴图 iina:超好用的播放器,配合网络上资源站的视频地址,完全不会发热 iterm2:可以透明背景、图片背景的终端 Lens:管理 k8s 神器 Rectangle:向 windows 一样排布窗口 Paragon NTFS for Mac:希捷官网下载是免费的 软件和固件下载 | Support Seagate US 系统设置:键盘快捷键、触发角、默认网页浏览器、调度中心使窗口按应用程序成组 ActivityWatch:时间追踪工具 Typora:markdown 编辑器,剪贴板的图片能给你自动复制到当前文件夹下,很适合本地写博客 Squash:图片压缩工具 macOS Assistant: macOS 小助手,一键 bypass 签名 LocalSend:本地传输文件,特别是往安卓设备传输东西 浏览器插件 简悦:纯净阅读 Adblock plus:屏蔽广告 Dark Reader:暗黑模式 Menu fish:古诗词标签页 Relingo:英语生词自动标记 Wayback Machine:网站记录备份 Stylus:重新编辑网站 CSS 样式 Wappalyzer:网站使用了哪些技术栈 Web Clipper(配合语雀):剪藏 FireShot:截屏 篡改猴(浏览器同步脚本) Microsoft编辑器:检查拼写和语法 命令行 oh-my-zsh:一定要用 zsh Roboto Mono for powerline 字体:在 iterm2 中设置 zsh 插件 zsh-syntax-highlighting zsh-autosuggestions spaceship-ember spaceship-vi-mode autojump:j neovim:nvim 开发 TabNine:GitHub Copilot 平替 visual-studio-code:开发必备 主旨 ZSH 配置 Spaceship 安装与配置 https://github.com/spaceship-prompt/spaceship-prompt

阅读更多
如何在 React 中进行状态管理?使用 Zustand!

计数器 import { create } from 'zustand' const useStore = create(set => ({ count: 1, inc: () => set(state => ({ count: state.count + 1 })), })) function Controls() { const inc = useStore(state => state.inc) return <button onClick={inc}>one up</button> } function Counter() { const count = useStore(state => state.count) return <h1>{count}</h1> } 用法 创建状态 state 操作 action Basic typescript usage doesn’t require anything special except for writing create<State>()(...) instead of create(...)… import { create } from 'zustand' interface BearState { bears: number increase: (by: number) => void } const useBearStore = create<BearState>()((set) => ({ bears: 0, increase: (by) => set((state) => ({ bears: state.bears + by })), })) const useFishStore = create((set) => ({ salmon: 1, tuna: 2, deleteEverything: () => set({}, true), // clears the entire store, actions included deleteTuna: () => set((state) => omit(state, ['tuna']), true), })) const useSoundStore = create((set, get) => ({ sound: "grunt", action: () => { const sound = get().sound // you still have access to state outside of it through get // ... } }) export default useBearStore 在 react 之外使用呢?

阅读更多
最小生成树

最小生成树:Kruskal算法和Prim算法的实现 这里直接给出离散数学中的几个定理和推论: 无向图G具有生成树当且仅当G连通. G为n阶m条边的无向连通图,则 m >= n - 1. G是树 $\Leftrightarrow$ G中任意两个顶点之间存在唯一路径 $\Leftrightarrow$ G中无回路且m=n-1$\Leftrightarrow$ G是连通的且m=n-1$\Leftrightarrow$ G中没有回路但在任何2个不同的顶点间加一条新边就能在图中得到唯一的含新边的环圈. 生成子图指的是顶点集相同,但边集是图G的子集的图. 生成树指的是图G的生成子图并且是树. 最小生成树指的是图G的所有生成树中权最小的. 算法第4版中这样定义:

阅读更多