はじめに
※ 本管理方法のご使用は、自己責任でお願いします。
会社用/研究用PCでもプライベートPCでも同じdotfiles環境を使用したいケースはあると思います。
ただ、会社内の情報など、会社用PCのdotfilesには記載したいけど、プライベートPCには記載したくないなど、単純に同じdotfilesを使用することはできません。
本記事では、会社用PCでもプライベートPCでもdotfiles環境を棲み分けつつ管理する方法を紹介します。
私のdotfilesはnarugit/dotfilesにて管理しています。
想定読者
- 同じdotfiles環境を複数PCで使用したい人
- dotfiles環境の管理方法に悩んでいる人
筆者の環境
私は、下記環境でdotfilesを運用しています。
-
PC1
- OS: Ubuntu 20.04
- 管理しているdotfiles
.zshrc
.tmux.conf
.gitconfig
.ssh/config
.vimrc
-
PC2
- OS: macOS Big Sur (Intel CPU)
- 管理しているdotfiles
.zshrc
.tmux.conf
.gitconfig
.ssh/config
.vimrc
本文のコード例では筆者の環境をベースに説明しますが、管理方法の考え方自体はファイル分割不可能なdotfileでも無い限り、他のdotfileでも応用可能だと思います。
また、私はzshユーザーであるため説明内では.zshrc
を持ち出して説明しますが、本管理をするにあたりzsh onlyな機能を使用していないため、.bashrc
に読み替えて頂いても問題ございません。
目次
1章は全員読んでください。
GitHubに上げられない秘匿情報がある方は3章を、会社PCと自宅PCでdotfilesを共通化したい方は4章を読んでください。
より効率化したい方は、2章、5章、6章を読んでください。
章 | タイトル |
---|---|
1章 | Gitで管理するには |
2章 | dotfilesの分割 |
3章 | シークレットな情報はGitHubにあげないようにする |
4章 | プライベートアカウントでcommitできるようにする |
5章 | リモートとローカルのdotfiles差分に気づけるようにする |
6章 | ワンライナーで環境構築 |
1章 Gitで管理するには
本文
1.1 ユースケース
育て上げたdotfilesを今後他のPCにも移植できるようクラウド上にアップロードしておきたいとき。
1.2 解決したい課題
ローカル環境にしかないdotfilesをクラウド上で管理したい。
1.3 アプローチ
dotfilesをGitで管理できるようにし、GitHub上にアップロードする。
1.4 実現方法
ここでは、dotfilesとして.zshrc
を例に説明する。
最終的には下記のようなディレクトリ構造となる。
${HOME}
|- .zshrc -> ${HOME}/dotfiles/etc/zsh/.zshrc
`- dotfiles/
|- .git/
`- etc/
`- zsh
`- .zshrc
-
dotfilesのバックアップを取っておく。
$ mkdir ~/dotfiles.bk $ cp ~/.zshrc ~/dotfiles.bk/
-
dotfiles配置用のディレクトリを作成する。
$ DOTFILES_DIR="${HOME}/dotfiles" $ ZSHRC_DIR="${DOTFILES_DIR}/etc/zsh" $ mkdir -p "${ZSHRC_DIR}"
-
dotfiles配置用ディレクトリをGitで管理する。
$ cd "${DOTFILES_DIR}" $ git init $ git commit --allow-empty -m "initial commit"
-
dotfiles配置用ディレクトリにdotfilesを移動する。
$ mv ~/.zshrc "${ZSHRC_DIR}"
-
dotfilesのシンボリックリンクを作成する。
$ ln -snfv "${ZSHRC_DIR}"/.zshrc ~/.zshrc
-
ターミナルを再起動し、dotfilesが問題無く読み込まれているか確認する。
以上の手順で、dotfilesをGitで管理することができるようになった。
適宜、GitHub上にpushすることでローカルのdotfilesをGitHub上にアップロードすることができる。
1.5 メリット
- dotfilesをバージョン管理できるようになる。
- PC乗り換えの際に、
git clone
して、シンボリックリンクを作成するだけで同じdotfiles環境を作り上げることができる。
参考リンク
2章 dotfilesの分割
本文
2.1 ユースケース
便利な機能を見つけ、dotfilesを修正したい。
ファイルのどの行に新機能に向けた行を追加しても動作はするが、似た機能同士は近くの行に配置したいとき。
2.2 解決したい課題
新機能向けの行を追加すべき箇所がどこなのか把握しやすくしたい。
2.3 アプローチ
機能のジャンルごとにファイルを分割することで、新機能を追加する際にジャンルからどのファイルを修正すべきか把握できるようにする。
2.4 実現方法
ここより先は、dotfilesごとにどう分割するかの具体例を記載する。 利用するdotfilesの項目だけご確認ください。
基本的には、エントリーポイントとなるファイルが分割したファイルを読み込むような構成となっている。 ファイルの分割ルール(機能ごとに分ける、ジャンルごとに分けるなど)や分割後のファイル名などは適宜自分好みに設定してください。
zsh
ディレクトリ構成は下記の通り。
${HOME}/
|- .zshrc -> ${HOME}/dotfiles/etc/zsh/.zshrc
|- .zsh.d -> ${HOME}/dotfiles/etc/zsh/.zsh.d
`- dotfiles/
`- etc/
`- zsh/
|- .zshrc
`- .zsh.d/
|- alias.zsh
|- audit.zsh
|- completion.zsh
|- peco.zsh
|- plugin.zsh
|- powerlevel10k.zsh
`- priorities.conf
下記のように各ファイル/ディレクトリに役割を与えている。
-
.zshrc
: エントリーポイント。.zsh.d
配下のファイルを読み込む。 -
.zsh.d/*.zsh
: もともとの.zshrc
を分割したファイル群 -
.zsh.d/priorities.conf
:.zsh.d/*.zsh
の各ファイルををどの順で読み込むかを記載している。 -
.zsh.d/audit.zsh
:priorities.conf
に記載されていないのに.zsh.d/
配下の*.zsh
ファイルがある場合に標準出力にメッセージを表示する。
各ファイルの中身は下記の通り。
ZSH_CONFS_DIR="${HOME}/.zsh.d"
ZSH_PRIORITIES_CONF="${ZSH_CONFS_DIR}/priorities.conf"
# Load ${ZSH_CONFS} in ${ZSH_PRIORITIES_CONF}
source "${ZSH_PRIORITIES_CONF}"
for zsh_conf in ${ZSH_CONFS}; do
source "${ZSH_CONFS_DIR}/${zsh_conf}"
done
# Be careful about the order of settings, as they are loaded in order from the top.
ZSH_CONFS=(
"audit.zsh" \
"plugin.zsh" \
"powerlevel10k.zsh" \
"peco.zsh" \
"completion.zsh" \
"alias.zsh" \
)
DOTFILES_DIR="${HOME}/dotfiles"
zsh_d_list=($(find "${HOME}/.zsh.d/"*.zsh -type f | awk -F '/' '{ print $NF }' | sort))
source "${HOME}/.zsh.d/priorities.conf"
zsh_confs=$(printf "%s\n" "${ZSH_CONFS[@]}" | sort)
invaders=$(echo ${zsh_d_list[@]} ${zsh_confs[@]} | tr ' ' '\n' | sort | uniq -u | tr '\n' ' ')
if test -n "${invaders}"; then
echo "Not managed in ${HOME}/.zsh.d/priorities.conf: ${invaders}"
fi
tmux
ディレクトリ構成は下記の通り。
${HOME}/
|- .tmux.conf -> ${HOME}/dotfiles/etc/tmux/.tmux.conf
|- .tmux.d/ -> ${HOME}/dotfiles/etc/tmux/.tmux.d
`- dotfiles/
`- etc/
`- tmux/
|- .tmux.conf
`- .tmux.d/
|- continuum.tmux
|- keybinding.tmux
|- pane.tmux
`- stateline.tmux
TMUX_CONFS_DIR="${HOME}/.tmux.d"
source-file ${TMUX_CONFS_DIR}/keybinding.tmux
source-file ${TMUX_CONFS_DIR}/stateline.tmux
source-file ${TMUX_CONFS_DIR}/pane.tmux
source-file ${TMUX_CONFS_DIR}/continuum.tmux
set -g @plugin 'tmux-plugins/tpm'
# Plugins
set -g @plugin "tmux-plugins/tmux-battery"
set -g @plugin "tmux-plugins/tmux-continuum"
set -g @plugin "tmux-plugins/tmux-cpu"
set -g @plugin "tmux-plugins/tmux-prefix-highlight"
set -g @plugin "tmux-plugins/tmux-resurrect"
set -g @plugin "tmux-plugins/tmux-sensible"
set -g @plugin "narugit/tmux-storage-status"
set -g @plugin "narugit/tmux-temp"
set -g @plugin "samoshkin/tmux-plugin-sysstat"
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run -b '~/.tmux/plugins/tpm/tpm'
ssh
ディレクトリ構成は下記の通り。
${HOME}/
|- .ssh
|- config -> ${HOME}/dotfiles/etc/ssh/config
`- .config.d/ -> ${HOME}/dotfiles/etc/ssh/.config.d/[darwin|linux]
`- dotfiles/
`- etc/
`- ssh/
|- config
`- .config.d/
|- darwin/
`- linux/
Include .config.d/*
vim
ディレクトリ構成は下記の通り。
${HOME}/
|- .vimrc -> ${HOME}/dotfiles/etc/vim/.vimrc
|- .vim/
|- dein/
|- userconfig/
|- plugins.toml -> ${HOME}/dotfiles/etc/vim/dein/plugins.toml
|- plugins_lazy.toml -> ${HOME}/dotfiles/etc/vim/dein/plugins_lazy.toml
|- init/ -> ${HOME}/dotfiles/etc/vim/init
`- plugin/ -> ${HOME}/dotfiles/etc/vim/plugin
`- dotfiles/
`- etc/
`- vim/
|- .vimrc
|- dein
|- plugins.toml
`- plugins_lazy.toml
|- init
|- input.vim
|- plugin.vim
`- view.vim
`- plugin
|- ale.vim
`- ctrlp.vim
runtime! init/*.vim
runtime! plugin/*.vim
git
ディレクトリ構成は下記の通り。
${HOME}/
|- .gitconfig -> dotfiles/etc/git/.gitconfig
|- .git.d -> dotfiles/etc/git/.git.d
`- dotfiles/
`- etc/
`- git/
|- .gitconfig
`- .git.d
|- alias.git
|- core.git
|- init.git
|- pager.git
`- user.git
[include]
path = ~/.git.d/alias.git
path = ~/.git.d/core.git
path = ~/.git.d/init.git
path = ~/.git.d/pager.git
path = ~/.git.d/user.git
2.5 メリット
- ファイルを分割したため、各ファイルの行数が少なくなり、ファイルさえ特定できれば修正箇所を追加する場所が分かりやすい。
- ある機能について記載された箇所がどこなのか探しやすい。
参考リンク
3章 シークレットな情報はGitHubにあげないようにする
本文
3.1 ユースケース
会社用PCで使うGitHubアカウントの情報やproxy用環境変数などシークレットな環境変数を.gitconfig
や.zshrc
、.ssh/config
に記載したいとき。
3.2 解決したい課題
シークレットな情報はGitHubにアップロードせずに、.gitconfig
, .zshrc
, .ssh/config
をGitで運用したい。
3.3 アプローチ
gitignoreの仕組みを使って、Git管理外のファイルにシークレットな情報を書き込む。Gitで管理しているファイルからそれらシークレットな情報が記載されたファイルを読み込む。
3.4 実現方法
.zshrc
, .gitconfig
, .ssh/config
のそれぞれでどう実現するか説明する。
zsh
${HOME}/.zshrc.secret
を作成し、GitHub上にアップロードしたくない、シークレットな情報を記載する。
.zshrc.secret
を.gitignore
に記載した上で、.zshrc
から.zshrc.secret
を読み込む。
.gitignore
, .zshrc
に記載する内容は下記。
.zshrc.secret
ZSH_SECRET_CONF="${HOME}/.zshrc.secret"
if [ -e "${ZSH_SECRET_CONF}" ]; then
source "${ZSH_SECRET_CONF}"
fi
git
${HOME}/.gitconfig.secret
を作成し、GitHub上にアップロードしたくない、シークレットな情報を記載する。
.gitconfig.secret
を.gitignore
に記載した上で、.gitconfig
から.gitconfig.secret
を読み込む。
.gitignore
, .gitconfig
に記載する内容は下記。
.gitconfig
は後勝ち方式なので、.gitconfig.secret
の情報を最優先させたい場合は、一番最後にincludeされるように記載する。
例えば、.gitconfig
にプライベートアカウントの情報を記載しており、会社用のPCを使用する場合は、デフォルトのGitHubアカウントは会社用のアカウントにしたい。
この場合は、.gitconfig.secret
に会社用のアカウント情報を記載し、.gitconfig
内で最後にincludeして、.gitconfig.secret
の情報が最優先されるように設定する。
.gitconfig.secret
[include]
path = ~/.gitconfig.secret
ssh
${HOME}/.ssh/config.secret
を作成し、GitHub上にアップロードしたくない、シークレットな情報を記載する。
config.secret
を.gitignore
に記載した上で、.ssh/config
から.ssh/config.secret
を読み込む。
.gitignore
, .ssh/config
に記載する内容は下記。
config.secret
Include config.secret
3.5 メリット
GitHub上にあげても良い情報とそうではない情報を別々で管理することができる。
4章 プライベートアカウントでcommitできるようにする
本文
4.1 ユースケース
社内PCのデフォルトcommitユーザーが社用アカウントである場合に、dotfilesリポジトリ上でcommitするとき。
4.2 解決したい課題
デフォルトcommitユーザーに依らずに、dotfilesリポジトリ上のcommit及びpushを行うユーザーはプライベートアカウントとなるようにしたい。
4.3 アプローチ
dotfilesリポジトリの.git/config
を下記のように修正する。
- push時に使用する秘密鍵がプライベートアカウントに紐付いたものとなるようにする。
- commit時のアカウント情報をプライベートアカウントのものと同一にする。
4.4 実現方法
-
プライベートアカウント向けのssh設定を記載する。
.ssh/config
から.ssh/.config.d/github.config
をIncludeしている前提。.ssh/.config.d/github.configHost github-personal User git HostName github.com IdentityFile ~/.ssh/id_rsa_personal Port 22 TCPKeepAlive yes IdentitiesOnly yes AddKeysToAgent yes
-
dotfiles管理リポジトリにて、push及びcommit時にプライベートアカウントを使用するよう設定する。各変数は自身の環境に応じて適宜変更する。
GIT_CONFIG_LOCAL_USER_NAME
,GIT_CONFIG_LOCAL_USER_EMAIL
はそれぞれ自身のプライベートGitHubアカウントのユーザー名、メールアドレスを設定する。$ DOTFILES_DIR="${HOME}/dotfiles" $ DOTFILES_REPO="narugit/dotfiles.git" $ GITHUB_PERSONAL_HOST="github-personal" $ cd "${DOTFILES_DIR}" $ git remote set-url --push origin "${GITHUB_PERSONAL_HOST}:${DOTFILES_REPO}" $ git config --local user.name "${GIT_CONFIG_LOCAL_USER_NAME}" $ git config --local user.email "${GIT_CONFIG_LOCAL_USER_EMAIL}"
-
実際にダミーcommitを作成し、正しく設定できているか確認する。
git log
でcommit authorがプライベートアカウントになっているか、またpush dry-run(-n
)でエラーが出ていなければOK。$ git switch -c dummy_branch $ touch hoge $ git add hoge $ git commit -m "dummy commit" $ git log +++ 確認ポイント1: commit authorがプライベートアカウントであることを確認する +++ $ git push -n origin HEAD +++ 確認ポイント2: エラーが出ていないことを確認する +++ $ git switch - $ git branch -D dummy_branch
4.5 メリット
社用アカウントなど、プライベートアカウント以外で社外リポジトリである、dotfiles管理リポジトリに変更修正を加えることができるようになる。
5章 リモートとローカルのdotfiles差分に気づけるようにする
本文
5.1 ユースケース
PCを複数台使用する場合に、あるPC上のdotfilesのみが更新され、他のPC上のdotfilesの更新を忘れてしまうとき。
5.2 解決したい課題
あるPC上でだけdotfilesが更新されている状態をできるだけ短くしたい。
5.3 アプローチ
ローカル上のdotfiles管理リポジトリとGitHub上のdotfiles管理リポジトリ間に更新差分がある場合、shellの起動時に標準出力で通知する。
5.4 実現方法
大まかな流れとしては、下記の通りである。
-
10分に1度、GitHub上のdotfiles管理リポジトリをfetchする。
-
shellを起動時に下記いずれかが真の場合、標準出力上にメッセージを表示する。
- ローカル上にある先頭commit IDとfetchしたリモート相当の先頭commit IDが異なる
- ローカルリポジトリ上に新規ファイルが存在する
ただ、shellを起動する度に標準出力上にメッセージするのは鬱陶しいため、ガッツリ開発中な時間帯はdotfilesの管理に時間を割けないと考え、指定した時間帯にはメッセージの出力頻度を抑えるようにしている。
また、定期的にfetchする方法がMacとUbuntuとで異なるため、それぞれ分けて説明する。
最終的なディレクトリ構成は下記の通り。
Mac
/usr/local/bin/
`- dotfiles_fetch.sh -> ${HOME}/dotfiles/bin/dotfiles_fetch.sh
${HOME}/
|- .zshrc -> ${HOME}/dotfiles/etc/zsh/.zshrc
|- .zsh.d/ -> ${HOME}/dotfiles/etc/zsh/.zsh.d
|- Library/
`- LaunchAgents/
`- dotfiles/ -> ${HOME}/dotfiles/etc/launchd
`- dotfiles/
|- bin/
|- dotfiles_compare.sh
`- dotfiles_fetch.sh
`- etc/
|- launchd/
`- dotfiles-fetch.plist
`- zsh/
|- .zshrc
`- .zsh.d/
`- dotfiles_monitor.zsh
Ubuntu
/usr/local/bin/
`- dotfiles_fetch.sh -> ${HOME}/dotfiles/bin/dotfiles_fetch.sh
${HOME}/
|- .config/
`- systemd/
`- user/
|- dotfiles-fetch.service -> ${HOME}/dotfiles/etc/systemd/dotfiles-fetch.service
`- dotfiles-fetch.timer -> ${HOME}/dotfiles/etc/systemd/dotfiles-fetch.timer
|- .zshrc -> ${HOME}/dotfiles/etc/zsh/.zshrc
|- .zsh.d/ -> ${HOME}/dotfiles/etc/zsh/.zsh.d
`- dotfiles/
|- bin/
|- dotfiles_compare.sh
`- dotfiles_fetch.sh
`- etc/
|- systemd/
|- dotfiles-fetch.service
`- dotfiles-fetch.timer
`- zsh/
|- .zshrc
`- .zsh.d/
`- dotfiles_monitor.zsh
各ファイルの役割は下記の通り。
-
dotfiles-fetch.plist
(Mac): launchdの機能を使用して、10分に1度、dotfiles_fetch.sh
を実行する。 -
dotfiles-fetch.service
(Ubuntu):dotfiles_fetch.sh
を実行する。 -
dotfiles-fetch.timer
(Ubuntu): systemdの機能を使用して、10分に1度、dotfiles-fetch.service
を起動する。 -
dotfiles_fetch.sh
: GitHub上のdotfiles管理リポジトリからローカル管理リポジトリにfetchする。 -
dotfiles_monitor.zsh
: ガッツリ開発中な時間帯はたまにdotfiles_compare.sh
を実行する。 -
dotfiles_compare.sh
: 下記がいずれかが真な場合は、標準出力上にメッセージ を出力する。- ローカル上にある先頭commit IDとfetchしたリモート相当の先頭commit IDが異 なる
- ローカルリポジトリ上に新規ファイルが存在する
環境構築手順を紹介する。
-
(Macの場合)
dotfiles-fetch.plist
を作成する。$ DOTFILES_DIR="${HOME}/dotfiles" $ PLIST_LOG_DIR="/var/log/dotfiles" $ sudo mkdir -p "${PLIST_LOG_DIR}" $ sudo chmod 777 "${PLIST_LOG_DIR}" $ editor ${DOTFILES_DIR}/etc/launchd/dotfiles-fetch.plist
dotfiles-fetch.plist<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>dotfiles.fetch.plist</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/dotfiles_fetch.sh</string> </array> <key>StartCalendarInterval</key> <array> <dict> <key>Minute</key> <integer>0</integer> </dict> <dict> <key>Minute</key> <integer>10</integer> </dict> <dict> <key>Minute</key> <integer>20</integer> </dict> <dict> <key>Minute</key> <integer>30</integer> </dict> <dict> <key>Minute</key> <integer>40</integer> </dict> <dict> <key>Minute</key> <integer>50</integer> </dict> </array> <key>StandardOutPath</key> <string>/var/log/dotfiles/fetch.out</string> <key>StandardErrorPath</key> <string>/var/log/dotfiles/fetch.err</string> </dict> </plist>
-
(Ubuntuの場合)
dotfiles-fetch.service
,dotfiles-fetch.timer
を作成する。$ DOTFILES_DIR="${HOME}/dotfiles" $ editor ${DOTFILES_DIR}/etc/systemd/dotfiles-fetch.service $ editor ${DOTFILES_DIR}/etc/systemd/dotfiles-fetch.timer
dotfiles-fetch.service[Unit] Description=Fetch master from narugit/dotfiles [Service] ExecStart=/usr/local/bin/dotfiles_fetch.sh Type=oneshot [Install] WantedBy=timers.target
dotfiles-fetch.timer[Unit] Description=exec every 10 minutes [Timer] OnCalendar=*-*-* *:0/10:00 [Install] WantedBy=timers.target
-
dotfiles_fetch.sh
を作成する。$ editor ${DOTFILES_DIR}/bin/dotfiles_fetch.sh
dotfiles_fetch.sh#!/bin/bash set -o pipefail DOTFILES_DIR="${HOME}/dotfiles" log_print() { if [ -p /dev/stdin ]; then local arg=$(cat /dev/stdin) else local arg="$@" fi local file_name=${BASH_SOURCE[1]##*/} if [ -n "${arg}" ]; then echo -e "$(date '+%Y-%m-%d %H:%M:%S') ${file_name} (${file_name}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $arg" fi } log_error() { if [ -p /dev/stdin ]; then local arg=$(cat /dev/stdin) else local arg="$@" fi local file_name=${BASH_SOURCE[1]##*/} if [ -n "${arg}" ]; then >&2 echo -e "$(date '+%Y-%m-%d %H:%M:%S') ${file_name} (${file_name}:${BASH_LINENO[0]}:${FUNCNAME[1]}) ERROR: $arg" fi } fetch_command() { (cd "${DOTFILES_DIR}" && git fetch -q origin master) } fetch() { (fetch_command | log_print) 2>&1 | log_error local ret="$?" if [ "$ret" = 0 ]; then log_print "Success to fetch." else log_error "Failed to fetch." fi } fetch
-
dotfiles_compare.sh
を作成する。DOTFILES_REMOTE_URL
は適宜変更する。$ editor ${DOTFILES_DIR}/bin/dotfiles_comapre.sh
dotfiles_comapre.sh#!/bin/bash DOTFILES_DIR="${HOME}/dotfiles" DOTFILES_REMOTE_URL="https://github.com/narugit/dotfiles" is_hash_same() { local DOTFILES_DEFAULT_BRANCH="master" local DOTFILES_REMOTE_HASH=$(cd ${DOTFILES_DIR} && git rev-parse origin/${DOTFILES_DEFAULT_BRANCH}) local DOTFILES_LOCAL_HASH=$(cd ${DOTFILES_DIR} && git rev-parse ${DOTFILES_DEFAULT_BRANCH}) if [ -z "${DOTFILES_REMOTE_HASH}" ]; then echo "Please set ${HOME}/.ssh/id_rsa_personal" false else if [ "${DOTFILES_LOCAL_HASH}" = "${DOTFILES_REMOTE_HASH}" ]; then true else false fi fi } is_local_clean() { if [ -z "$(cd ${DOTFILES_DIR} && git status --porcelain)" ]; then true else false fi } echo "Comparing remote dotfiles" if is_hash_same && is_local_clean; then echo "Your local dotfiles may be up to date at least in a hour!" else echo "Your local dotfiles differs from remote dotfiles. Please check ${DOTFILES_DIR} and ${DOTFILES_REMOTE_URL}" fi
-
dotfiles_monitor.zsh
を作成する。ACTIVE_HOUR_START
からACTIVE_HOUR_END
の時間帯は、1/RARITY_ACTIVE_HOUR
の確率でdotfiles_compare.sh
を実行する。$ editor ${DOTFILES_DIR}/etc/zsh/.zsh.d/dotfiles_monitor.zsh
dotfiles_monitor.zshDOTFILES_DIR="${HOME}/dotfiles" ACTIVE_HOUR_START=10 ACTIVE_HOUR_END=17 # rarity: one time in how many times to compare with remote's dotfiles. RARITY_MIN=1 RARITY_ACTIVE_HOUR=10 RARITY_NON_ACTIVE_HOUR=1 generate_random() { local min="$1" local max="$2" local random_num=$(awk -v min="$min" -v max="$max" 'BEGIN{srand(); print int(min+rand()*(max-min+1))}') echo "$random_num" } is_active_hour() { current_hour=$(date +"%H") if [ ${ACTIVE_HOUR_START} -le ${current_hour} ] && [ ${current_hour} -lt ${ACTIVE_HOUR_END} ]; then true else false fi } check_rarity() { if [ ${RARITY_ACTIVE_HOUR} -lt ${RARITY_MIN} ]; then echo "RARITY_ACTIVE_HOUR should be greater than ${RARITY_MIN}." fi if [ ${RARITY_NON_ACTIVE_HOUR} -lt ${RARITY_MIN} ]; then echo "RARITY_NON_ACTIVE_HOUR should be greater than ${RARITY_MIN}." fi if is_active_hour; then echo ${RARITY_ACTIVE_HOUR} else echo ${RARITY_NON_ACTIVE_HOUR} fi } lottery_to_compare() { rarity=$(check_rarity) num=$(generate_random ${RARITY_MIN} $rarity) if [ $num = ${RARITY_MIN} ]; then true else false fi } if lottery_to_compare; then source "${DOTFILES_DIR}/bin/dotfiles_compare.sh" fi
-
(Macの場合) シンボリックリンクを作成する。
$ mkdir -p "${HOME}/Library/LaunchAgents" $ ln -snfv "${DOTFILES_DIR}/etc/launchd" "${HOME}/Library/LaunchAgents/dotfiles" $ ln -snvf "${DOTFILES_DIR}/bin/dotfiles_fetch.sh" /usr/local/bin
-
(Ubuntuの場合) シンボリックリンクを作成する。
$ mkdir -p "${HOME}/.config/systemd/user" $ chmod 644 "${DOTFILES_DIR}/etc/systemd/dotfiles-fetch.service" $ chmod 644 "${DOTFILES_DIR}/etc/systemd/dotfiles-fetch.timer" $ systemctl link --user "${DOTFILES_DIR}/etc/systemd/dotfiles-fetch.service" $ systemctl link --user "${DOTFILES_DIR}/etc/systemd/dotfiles-fetch.timer" $ ln -snvf "${DOTFILES_DIR}/bin/dotfiles_fetch.sh" /usr/local/bin
-
(Macの場合)
dotfiles-fetch.plist
を起動する。$ sudo chmod 644 "${HOME}/Library/LaunchAgents/dotfiles/dotfiles-fetch.plist" $ launchctl unload "${HOME}/Library/LaunchAgents/dotfiles/dotfiles-fetch.plist" &> /dev/null $ launchctl load "${HOME}/Library/LaunchAgents/dotfiles/dotfiles-fetch.plist"
-
(Ubuntuの場合)
dotfiles-fetch.timer
を起動する。$ systemctl --user daemon-reload $ systemctl --user enable "dotfiles-fetch.timer" $ systemctl --user start "dotfiles-fetch.timer"
-
dotfiles_monitor.zsh
のRARITY_ACTIVE_HOUR
を1に変更して、shellを起動するタイミングで"Comparing remote dotfiles"というメッセージが標準出力上に出現するか確認する。出現した場合、問題なく設定できているため、RARITY_ACTIVE_HOUR
を好きな値に設定する。
5.5 メリット
- dotfilesをGitHubで管理していたことを思い出すことができる。
- 最新のdotfilesを使用できているか把握することができる。
6章 ワンライナーで環境構築
本文
6.1 ユースケース
新しいPCでdotfiles環境を手軽に構築したいとき。
6.2 解決したい課題
dotfiles環境を構築するのが手間。
6.3 アプローチ
環境構築用スクリプトを作成し、curlでダウンロードした上で実行する。
スクリプトの大まかな流れとしては、下記の通り。
他に処理が必要な場合は適宜追加する。
-
dotfiles管理リポジトリのclone。
-
dotfiles管理リポジトリのファイルを使用したシンボリックリンクの作成など、必要とする処理を実行。
6.4 実現方法
-
環境構築用スクリプトを作成する。
install.sh#!/bin/bash -e DOTFILES_DIR="${HOME}/dotfiles" git clone ${Your Remote Repository} ${DOTFILES_DIR} # シンボリックリンクの作成など、自分の必要とする処理を記載する
-
スクリプトをGitHub上にpushする。
-
下記コマンドでスクリプトをワンライナーで実行する。URLは適宜変更する。下記は
{Yout GitHub Account}/{Your Repository}
上の{branch}
ブランチにinstall.sh
を配置した例。$ bash -c "$(curl -fsSL https://raw.githubusercontent.com/{Yout GitHub Account}/{Your Repository}/{branch}/install.sh)"
6.5 メリット
お手軽にdotfiles環境構築することができる。
参考リンク
最後に
本記事に記載した内容でうまく動作しないなどございましたら、是非コメントお願いします。
快適なdotfiles管理生活を送りましょう!