(2017-04-26更新【方案4】)
這個博客是部署在VPS上的,但我并没有在VPS上部署git server,VPS上只是一个git repository(即Github的鐿象)。Github在本博的架构里是作为中心仓库的角色存在的,在寫文章時,只需把本地的commit push到Github上。
但这样数据同步的问题就来了:
當Github收到新push的時候,Github Pages會自動build出靜態HTML,但VPS上的repository是不知道有更新的,這需要有個機制讓VPS上的repository感知Github的更新信息,然後自動pull Github倉庫的最新改動。至於jekyll的自動build,可以通過jekyll的--watch
選項監控源代碼變量自動build。
以daemon模式啟動jekyll的build進程,開啟watch選項,這樣就可以在更新代碼時自動重新build出整站的HTML代碼到_site目錄中:
nohup jekyll build --watch > /dev/null 2>&1 &
Webhooks是Github提供的一個事件觸發服務,當指定的事件發生時,Webhooks會把該事件通知給事先在Github.io上配置的外部web服務器。Webhooks事件举例:
通过GitHub API,你可以配合webhooks搭建一系列项目构建服务,例如持续集成(Continuous Integration)、同步備份鏡象(我的VPS其實就是GitHub的一個鏡象)、甚至是部署項目到你的production server。
前提, 要使用Webhooks,你必須:
Webhooks的鐿象同步方案架構:
從架構圖可以看出此方案的重點:
Webhooks作為Github提供的項目構建接口方案,定義了事件、通用API協議、一組對應的安全配置等規範,對於大型項目來說用起來是很有價值的。但對於我的需求來說,只需要當Github有更新時,VPS自動pull一下代碼而已。對接一個定義得完整的API是有一定工作量的,我一看webhook的文檔就沒有對接的興趣了(沒有快速接入說明),於是我開始思考有沒有更簡單的辦法。
其實只是一個事件通知,不使用Webhooks也能自己實現。這樣就能避免接入webhooks的開發與調試工作量了。自己實現通知的架構圖如下:
與【方案1】的區別:
git push
curl http://4377.me/sync_blog.php
git pull
一下最新改動到VPS。直接用PHP即可簡單實現,代碼如下(FileName: sync_blog.php):<?php
$out = array();
exec('/var/wsp/blog/sunshine17.github.io/sync.sh', $out); // 邏輯部分由shell腳本實現
echo json_encode($out);
php調用的shell腳本(FileName: sync.sh):
#!/bin/zsh
cd "$(dirname "$0")"
git pull
這樣,在寫作環境寫完文章後,只要執行push.sh就可以自動同步代碼到Github倉庫,且調用VPS上的HTTP API執行一次同步Github操作,從而自動更新了博客。
使用IFTTT。
這是國外做得很不錯的一個條件觸發服務,整合了很多知名的互聯網服務,包括天氣、股票、facebook、twitter、google等。甚至還能發中國運營商的短信(幾年前我試過發當天氣預報有雨時發信息到我的中國移動手機卡,但用了一段時間就用不了了)。
可惜的是,查了一下IFTTT上的Github Channel,貌似沒有git push的觸發條件,只好作罷。 其實IFTTT的方案本質也是一樣,只是IFTTT充當了觸發器的角色(Webhooks)。
使用Teamcity之类的CI(Continuous Integration)服务。
方案2有个缺陷:需要使用php调用shell脚本,这有一定安全隐患,以及需要部署多一个PHP服务。 于是,我想到了成熟团队都可能用到的Teamcity。简单方案如下:
cd /home/your_blog_repo_dir
git pull
最后,我选择的是【方案4】。原因是我的VPS要用到teamcity,既然已经用到它了,干脆就物尽其用,总比方案2的php+shell更安全可靠。