Skip to content

Instantly share code, notes, and snippets.

@MetroWind
Last active October 15, 2020 23:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MetroWind/721d13e988206cf5e001f52d88f94b20 to your computer and use it in GitHub Desktop.
Save MetroWind/721d13e988206cf5e001f52d88f94b20 to your computer and use it in GitHub Desktop.
配置管理系统的脑洞

配置管理系统

为嘛

我有四台常用的电脑:工作用 Mac,工作用大便,私用 Mac,私用 Gentoo,这四台电脑的主要配置都差不多,只在少数地方不同。

以 Git 为例,这四台电脑上都有相同的 ~/.gitignore,相同的 ~/.gitconfig。不同之处是有一台电脑上设置了默认开启 gpg-sign,另外几台电脑上设置好了 GPG,但是 Git 不默认添加签名。

另一个例子是 Xmonad/Xorg,显然在两台 Mac 上是没有 Xmonad 的,这时原则上上不需要安装配置(但是配置了也无所谓)。在大便上,进入图形界面的时候会调用 ~/.xinitrc,里面有我的输入法设置和壁纸设置,而在 Gentoo 上,这些设置在 ~/.xprofile 里。

下一个例子是 Zsh 配置。在我的两台工作机器上,我要设置大量和工作相关的环境变量和别名,而且两台机器需要的环境不一样。并且我不想在配置所在的 Git 仓库上暴露任何与工作有关的信息。Emacs 配置也有类似的需求。

最后一个例子是 GnuPG。我使用 GPG 的主要场景是 SSH 登录和 Git 签名。这里涉及到多个程序和配置文件:

  • .gitconfig

  • .profile(设置 $SSH_AGENT_SOCK

  • gpg.conf

  • gpg-agent.conf

  • sshcontrol

在配置一个新环境的时候我要修改所有这些文件。

要啥自行车

除了常见的「把一些文件复制/连接到正确的目录里」以外,以上四种场景还需要如下的功能:

  • 模板文件,通过用户提供的变量生成配置文件

  • 在不同的系统上使用不同的文件

  • 从用户提供的变量生成配置文件(无模板)

  • 通过用户提供的一组变量给多个程序生成配置文件。

可以看到有多个需求都涉及到用户提供的变量,所以这里可以再加一个需求:

  • 提供统一的界面管理用户提供的变量

咋整

接下来是脑洞时间。我的设想是把每个程序的配置都独立成一个包,包里除了有相关的配置文件和模板以外还有逻辑,也就是个程序。这个程序能读取用户提供的变量,并且正确地生成并安装配置。所有的用户变量都存在一个指定的文件里。用户只需要修改这一个文件就可以适配不同的机器。

栗子(伪 Scheme):

存用户变量的文件:

(define machine-name "fity")
(define gpg-default-sign (= machine-name "fity"))
(define user-name "MetroWind")
(define user-email (base64-decode "jfksal;fjkdsal;jf=="))
(define use-gpg #t)
(define gpg-master-key "abcdef")
(define gpg-auth-key "123456")

Git 的配置逻辑:

(import 'user-conf)

(copy-files '(... ... ...))

(define (append-git-conf section key value)
  ;; ...
)

(append-git-conf "user" "name" user-name)
(append-git-conf "user" "email" user-email)
(if gpg-default-sign
  (append-git-conf "user" "gpg-sign" "true"))
(if use-gpg
  (append-git-conf "user" "signingkey" gpg-master-key))

append-git-conf 这样的函数,可以作为 Scheme「标准库」的一部分提供,这样定义包的时候就不需要再定义了。或者可以做为内建函数提供,这样就可以用 Rust 实现。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment