資工問題雜筆

[資工雜筆] 利用 Git 來自動化 deploy 實驗程式碼到遠端主機

熟悉 hexo 的人,應該會知道,hexo deploy 的方式非常的方便,只要輸入 hexo deploy 就可以把產生好的檔案 push 到 github.io 上。上個周末教學生 deploy hexo 時得到這個靈感,趁等門診的時間,趕緊來把這篇記錄起來。

首先先描述一下我的狀況。我在遠端有一些主機可以用,ip、port、user 的設定類似如下:

pc1001@140.113.0.1 port 1001
pc1002@140.113.0.1 port 1002

不同的主機可能會跑不同的實驗。因為開發速度的關係,我在 local 的 mac 上開發,如果改一點小小的內容,我希望輸一行指令就可以把修改後的程式碼發到指定的 server 上。

最先的做法有三種,非常笨拙。羅列如下:

  1. 開不同的 branch,然後各自跑不同的實驗 ,參照 git flow 的用法。程式碼一改動,全部都 push 到  GitHub 上,然後 remote server 再 git pull 和 checkout 到我要的 branch。這個的缺點是當主機一多的時候,branch 會變的很亂。此外,大部分的 branch 之間都只要小改一點點,但要是用這個方法,任何改動都會變成一個新的 commit ,到時還要重新 rebase ,實在是太麻煩。
  2. 直接 ssh 到 remote server 去改。這個方法的問題是如果要改的程式碼一多,又很分散,那就很麻煩。遠端的編輯環境不見得好用,而且所有改動都沒有記錄。
  3. 用 sftp 把程式碼丟過去。如果改的檔案一多,就很麻煩,要一次傳很多,而且很可能會漏傳,一樣改動都沒有記錄。

Remote 設定

以上方法都不是好的方法。然而,如果善用 git 和 shell script 的話,可以把以上這些動作通通自動化。在開始之前,先定義一些待會會用到的參數:

project name: proj
server ip: ip
port: port
username: user

首先,需要在遠端先建一個 git server repo。一定要輸入  –bare,因為這樣才會建立一個 git server repo,而不是一個 git local repo。

mkdir proj.git && cd proj.git && git init --bare

除了 proj.git 外,我們也要在 remote server 建立一個 project directory,因為實驗要跑在這個  directory。那這個 repository 就直從 proj.git clone 就可以了。(想想看怎麼操作 github 的?意思相同)

git clone proj.git proj

接著,要在 proj.git/hooks 新增一個 post-receive 的檔案。這個檔案的意思是當 server 接收到新的 push 後,server 可以緊接著做一些我們想要的事。在這裡我們要做的,就是讓 proj 自動 git pull,把檔案更新。因此要輸入以下程式碼(這邊是示意,最後會有整份完整的 bash script):

cd ../proj
unset GIT_DIR
git pull

unset 的原因是因為 git 自動執行  post-receive 的時候 GIT_DIR 是設定在 proj.git,但是我們現在的 git directory 應該要是 proj。

以上這些步驟有一點麻煩,因此我把這些步驟都寫成一個 bash script,之後只要一行指令就可以灌完了!

Local 設定

設定完遠端後,理論上我們只要

git remote add origin ssh://user@ip:port/home/user/proj.git/

就可以把 local remote 連結起來。但這樣還是會有一個問題,就是不同主機的 code 還是相等的。我們應該要有不同的 git tree 去 track 不同主機改動的 code,然後每次都 deploy 那部份 code 就好了,各個主機之間的 code 不要打架。

這樣的話我們要在 local 的 proj 裡新增一個 .deploy_git  directory。千萬記得 .gitignore 要加上 .deploy_git 。

mkdir .deploy_git
mkdir .deploy_git/ip1/ && cd .deploy_git/ip1/ && git init
git remote add origin ssh://user@ip1:port/home/user/proj.git/

只要有新的一台主機,就開新的資料夾。接著我們要寫一個 shell script 名叫 deploy.sh。當我們小改完程式碼,輸入 ./deploy.sh <dir_name>,就會把當下的程式碼,全部複製到特定的 directory 下,然後 deploy。以下是 deploy.sh 的程式碼,在 deploy 的時候,會參考 .deployignore 列的篩選條件,篩掉不要 deploy 的檔案和資料夾。

if [ -d ".deploy_git/$1" ] && [ -n "$1" ]; then
    undeploy=$(cat .deployignore | xargs | sed "s: :\|:g; s:\.:\\\.:g;")'|^\.$|^\.\.$'
    ls -a | grep -Ev $undeploy | xargs -I % sh  -c "cp -r % .deploy_git/$1/"
    cd .deploy_git/$1
    git add .
    git commit -m "`date '+%Y-%m-%d %H:%M:%S'`"
    git push --set-upstream origin master
else
    echo "No Such Directory"
fi

至於免密碼 ssh 登入,可以參考這一篇教學,寫得非常清楚!

結語

做完這些步驟,就可以實現一鍵 deploy 了,而且還可以 deploy 到指定的主機去。當程式碼確定穩定後,就把這個程式碼提交到 Github 上儲存,這樣一來,不僅程式碼乾淨,也很方便管理各主機的程式碼,更棒的是,所有跑過的實驗記錄、設定檔和實驗時間,也都各自會記錄在遠端的 git server 裡。

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s