git-syncで定期バックアップをとる

Posted on | 396 words | ~2 mins

Context

  • Obsidian vaultのback up先として、privateのGitHub repoへ置いている
    • iOSアプリとの連携用でiCloud同期は別でやっている
    • iCloudストレージの操作をミスっておじゃんにすることもあろうかと、git repoへもsyncしておいて安心しておきたい
  • 日々差分が生じているが、push作業は手動でおもいついたらやっている。アドホック運用。(数日だったり1週間空くこともありがち)
  • syncを自動daily実行されるしくみがほしい
  • git-syncをつかうとよさそう

git-syncを実行する

git-syncをcloneしてPATHを通す

❯ git clone https://github.com/simonthum/git-sync.git
❯ sudo ln -snfv `pwd`/git-sync /usr/local/bin/git-sync

Obsidian vaultのあるディレクトリへ移動

❯ cd /path/to/ObsidianVault

git-sync用のgit config設定

❯ git config --bool branch.main.sync true
❯ git config --bool branch.main.syncNewFiles true

.git/configに以下が追加される

[branch "main"]
	remote = origin
	merge = refs/heads/main
+	sync = true
+	syncNewFiles = true

git-sync実行

❯ git-sync
git-sync: Preparing. Repo in .git ~/Library/Mobile Documents/iCloud~md~obsidian/Documents/ObsidianVault
git-sync: Mode sync
git-sync: Using origin/main
git-sync: Committing local changes using git add -A ; git commit -m "changes from hrfmmrM1MBP.local on Sat Sep 10 16:51:46 JST 2022";
[main e31cb50] changes from hrfmmrM1MBP.local on Sat Sep 10 16:51:46 JST 2022
 1 file changed, 27 insertions(+), 43 deletions(-)
 rewrite "Obsidian\343\201\256vault\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\343\202\222\344\273\273\346\204\217git repo\343\201\
253sync\343\201\231\343\202\213.md" (68%)
git-sync: Fetching from origin/main
From github.com:hrfmmr/obsidian
 * branch            main       -> FETCH_HEAD
git-sync: Pushing changes...
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 10 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 433 bytes | 433.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:hrfmmr/obsidian.git
   6f52e29..e31cb50  main -> main
git-sync: In sync, all fine.

よしなに差分がpushされてる🚀

定期実行する

  • macOSなのでlaunchdをつかう
  • LaunchAgentかLaunchDaemonか
  • 今回はユーザログイン状態に関わらず指定時間にdaily実行してもらいたいので、daemon serviceとして登録する

$ sudo vim /Library/LaunchDaemons/com.hrfmmr.ObsidianGitSync.daemon.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>com.hrfmmr.ObsidianGitSync.daemon</string>
    <key>UserName</key>
    <string>hrfmmr</string>
    <key>SessionCreate</key>
    <true />
    <key>WorkingDirectory</key>
    <string>/Users/hrfmmr/Library/Mobile Documents/iCloud~md~obsidian/Documents/ObsidianVault</string>
	<key>ProgramArguments</key>
	<array>
        <string>/usr/local/bin/git-sync</string>
	</array>
	<key>StandardErrorPath</key>
	<string>/Users/hrfmmr/.log/obsidian-git-sync/stderr.log</string>
	<key>StandardOutPath</key>
    <string>/Users/hrfmmr/.log/obsidian-git-sync/stdout.log</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>0</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
</dict>
</plist>

launchdに登録

❯ launchctl load /Library/LaunchDaemons/com.hrfmmr.ObsidianGitSync.daemon.plist

テストする

ログを監視しつつ

❯ tail -f ~/.log/obsidian-git-sync/*.log

登録したservice実行

❯ launchctl start com.hrfmmr.ObsidianGitSync.daemon

tailしてるログみると、ちゃんと動いてそう

==> /Users/hrfmmr/.log/obsidian-git-sync/stdout.log <==
git-sync: Preparing. Repo in .git /Users/hrfmmr/Library/Mobile Documents/iCloud~md~obsidian/Documents/ObsidianVault
git-sync: Mode sync
git-sync: Using origin/main
git-sync: Committing local changes using git add -A ; git commit -m "changes from hrfmmrM1MBP.local on Sat Sep 10 21:37:16 JST 2022";
[main b0d41bc] changes from hrfmmrM1MBP.local on Sat Sep 10 21:37:16 JST 2022
 1 file changed, 86 insertions(+), 3 deletions(-)
git-sync: Fetching from origin/main
git-sync: Pushing changes...
git-sync: In sync, all fine.

失敗したときの検知

  • syncがコケたらそれに気づくしくみが必要
  • とりあえず個人用Slack channelにsync失敗したことを検知できる通知を投げるようにする

/path/to/ObsidianVault/scripts/git-sync.sh

#!/bin/sh

__post_to_slack() 
{
  curl -X POST 'https://slack.com/api/chat.postMessage' \
  -d 'token=<SLACK_APP_TOKEN>' \
  -d 'channel=#obsidian-git-sync-status' \
  -d "text=$1"
}

out="$(/usr/local/bin/git-sync 2>&1)"
if [ ! "$(echo $?)" -eq 0 ]; then
  __post_to_slack "❗️$out"
fi

/Library/LaunchDaemons/com.hrfmmr.ObsidianGitSync.daemon.plist

	<key>ProgramArguments</key>
	<array>
-        <string>/usr/local/bin/git-sync</string>
+        <string>scripts/git-sync.sh</string>
	</array>

serviceをreload

❯ launchctl unload /Library/LaunchDaemons/com.hrfmmr.ObsidianGitSync.daemon.plist
❯ launchctl load /Library/LaunchDaemons/com.hrfmmr.ObsidianGitSync.daemon.plist

まとめ

git-syncとlaunchd(macOS)で、「git repoへの定期sync」のしくみがつくれる