yadm
yadm用于在类 Unix 系统上管理你的 dotfiles 文件。所谓的 dotfiles 即以点开头的文件,他在 Linux 中会被隐藏因此常用来作为配置文件。所以 yadm 说白了就是管理个人配置文件的。
安装
各大发行版都提供了 yadm 包,直接使用包管理工具安装即可。实际上 yadm 就是一个shell script
通用性非常的好(兼容 bash 即可),可以直接使用下面的命令安装:
sudo curl -fLo /usr/local/bin/yadm https://github.com/TheLocehiliosan/yadm/raw/master/yadm && sudo chmod a+x /usr/local/bin/yadm
基本使用
yadm 是构建在 git 之上的,git 要求整个仓库都在同一个文件夹下面,文件夹下面所有的文件都是潜在跟踪目标。yadm 改进了这一点,它会创建一个干净的 repository,只追踪用户主动添加的文件。其他 yadm 的使用流程基本上和 git 是一样的:
# 初始化一个仓库,yadm 默认的 worktree 是 $HOME
yadm init
Initialized empty shared Git repository in $HOME/.local/share/yadm/repo.git/
# 添加文件到暂存区
yadm add <file-path>
# 提交
yadm commit -m <mssage>
# 绑定远程仓库并推送
yadm remote add origin <url>
yadm push -u origin <local branch>:<remote branch>
之后我们要在一个新的机器上部署只需要执行:
yadm clone <url>
# 如果存在子模块还需要执行
git submodule update --init --recursive
# 或者直接执行
yadm clone --recurse-submodules <url>
如果本地存在与版本库不同的内容的同路径文件,并不会覆盖本地,你需要自己来处理差异或者直接覆盖掉。
高级功能
子模块(submodule)
yadm 以$HOME
目录作为仓库的 git。同样他是支持添加子模块的:
完全可以像正常的管理 git 子模块那样管理即可。注意一定不要跟绝对路径:
# 使用 ~/.config/dir 这样会是一个绝对路径,在 MacOS 和 Linux 以及不同的用户下切换会出现问题
[submodule "/Users/yangguodong/.config/python_cookbook"]
path = /Users/yangguodong/.config/python_cookbook
url = git@gitee.com:hncjygd/python_cookbook.git
# 直接切换到 .config 然后 submodule add ,给出的是相对路径,yadm 的管理的仓库根为 $HOME 这样就没有问题
[submodule ".config/python_cookbook"]
path = .config/python_cookbook
url = git@gitee.com:hncjygd/python_cookbook.git
引导(Bootstrap)
所谓的 Bootstrap 即引导,他通常用于初始化操作,最常见的就是安装依赖。yadm 对 Bootstrap 的支持非常简单,他在 clone 后会自动运行$HOME/.config/yadm/bootstrap
脚本。
这个 bootstrap 可以是任何可执行文件,不过通常就是一个 shell 脚本。如果该脚本存在 在 clone 会提示你:
Found .config/yadm/bootstrap
It appears that a bootstrap program exists.
Would you like to execute it now? (y/n)
即使选着了 n 也不需要着急,直接运行 yadm bootstrap 同样可以安装。
一个简单的示例,在 macOS 上安装 homebrew:
#!/bin/sh
system_type=$(uname -s)
if [ "$system_type" = "Darwin" ]; then
# install homebrew if it's missing
if ! command -v brew >/dev/null 2>&1; then
echo "Installing homebrew"
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
fi
if [ -f "$HOME/.Brewfile" ]; then
echo "Updating homebrew bundle"
brew bundle --global
fi
fi
加密(Encryption)
yadm 管理的文件通常需要公布到远程仓库中,他们应当是脱敏的,但是像管理 ssh 密钥的需求是存在的。yadm 同样提供了一种机制来为我们加密这些文件。使用加密需要以下步骤:
- 在
$HOME/.config/yadm/encrypt
文件中添加要加密的文件(支持通配符) - 执行
yadm encrypt
命令,他会读取上面的配置文件然后询问密码,之后会将匹配到的文件加密保存到$HOME/.local/share/yadm/archive
文件中 - 之后我们需要将上述的两个文件提交到 yadm 管理
yadm add .config/yadm/encrypt & yadm add .local/share/yadm/archive
当我们需要在一个新的环境中 clone 配置后,这些加密的文件是不会自动解密的,如果想要解密还需要执行:
加密默认是基于 gpg 的,因此需要可以运行 gpg 命令。如果在终端中执行加密和解密有时候会提示
gpg: signing failed: Inappropriate ioctl for device
错误,这是因为 gpg 无法在当前终端弹出密码输入窗口导致的,此时可以定义export GPG_TTY=$(tty)
即在终端显示密码输入窗口。
更改为 openssl 加密
gpg 加密问题比较多,可以修改为 openssl 加密:
之后需要将.config/yadm/config
添加到仓库中。
多平台部署
所谓的Alternate Files
即提供了一种机制来作为后备文件,这些后备文件具有特定的文件名,他们都能够在不同的环境中被部署。
后备文件使用##<condition>[,<condition>,…]
作为后缀,其中condition
就是条件,除了default
条件外每一个条件都是以key.value
形式的键值对,可用的条件:
键 | 含义 | 典型值 |
---|---|---|
default | 默认 | default |
arch,a | 架构(uname -m) | a.x86_64,a.arm64 |
distro,d | 发行版(/etc/os-release id) | d.debian,d.centos |
hostname,h | 主机名(uname -n) | h.hostname |
os,o | 操作系统名(uname -s) | o.Darwin,o.Linux,o.WSL |
user,u | 用户名(id -u -n) |
可以使用任意数量的条件,yadm 会从最佳的匹配来进行选着,例如一个文件:
$HOME/path/example.txt##default
$HOME/path/example.txt##os.Darwin
$HOME/path/example.txt##os.Darwin,hostname.host1
$HOME/path/example.txt##os.Darwin,hostname.host2
$HOME/path/example.txt##os.Linux
如果在 Linux 上直接匹配到##os.Linux
,如果是在 MacOS 上有几种情况:
- 如果
hostname = host1
那么就匹配##os.Darwin,hostname.host1
- 如果
hostname = host2
那么就匹配##os.Darwin,hostname.host2
- 如果是其他
hostname
的用户那么就匹配到##os.Darwin
- 再有其他情况,例如在 WSL 中就使用
##default
对于加密保存的文件,即列入
$HOME/.config/yadm/encrypt
中的文件, 还有 bootstrap 都同样适用这种命名方式。 通常不推荐使用这么复杂的管理方式。如果可能的话还是尽量提供一套统一的配置文件,可以在文件中检测变量来提供不同的分支。
yadm alt
Alternate Files 的实现方式是在 clone 项目的时候匹配最佳的文件,然后使用符号连接来引用这个文件,还是上面的例子,如果我们在 WSL 中使用实际上是创建了一个:
他最大的问题在于,所有 Alternate Files 文件还是位于$HOME/path/
目录下,这就导致了这个目录异常混乱。
yadm 提供了一种机制,我们可以将这些文件以相对路径的形式放置到$HOME/.config/yadm/alt/
目录下,例如上面的可以放置到 $HOME/.config/yadm/alt/path/example.txt##default
,之后的交由 yadm 来管理即可。
还有 yadm 会自动创建这些符号链接,如果存在冲突可以解决后执行:
XDG Base Directory specifications
配置文件通常都是家目录下的一系列文本文件,他们通过以 . 开头来隐藏。这就导致了一个问题就是家目录下的文件异常混乱。开源社区发布了一套规范即XDG Base Directory spec来约束家目录下文件的存放:
环境变量 | 默认值 | 含义 |
---|---|---|
$XDG_CONFIG_HOME |
$HOME/.config/ |
软件配置存放路径 |
$XDG_DATA_HOME |
$HOME/.local/share/ |
软件依赖的数据存放目录(静态的) |
$XDG_STATE_HOME |
$HOME/.local/state/ |
软件依赖的状态数据存放目录(动态的,不可移植的。例如日志) |
$XDG_CACHE_HOME |
$HOME/.cache/ |
软件缓存存放路径(非必要文件) |
还推荐用户的可执行文件位于
$HOME/.local/bin
目录下,需要将他们放置到$PATH
环境变量中
目前很多程序都已经遵循了这个规范,但是也有例外。如果想要不支持该配置的程序也支持通常有两种方式,这主要取决于应用: