本文最早發佈於 Rootrl's Blog
緣起
我們公司開發環境很特殊,一台本機伺服器,然後分配多個ssh賬戶給開發人員。平時上傳代碼只能ftp/sftp串連上傳(以前用過samba共用,但被關了。。)。所以我們平時是在Phpstorm上用sftp遠程開啟伺服器上的項目,然後設定自動上傳。這樣一般工作沒問題。但是有個坑:Phpstorm無法捕獲類似git checkout這些變更檔的變化。。所以也就無法讓本地代碼跟伺服器保持一致了。所以也就誕生了想寫個這個同步機制的念頭,這種情境Golang很適合。於是就開始擼起來。。
項目地址:https://github.com/rootrl/Mancy
實現
大致思路是監測一個檔案夾的變化(本地程式碼程式庫),如果有變化就通過sftp上傳到伺服器上。
監測檔案變化用的是golang的fsnotify package,它提供的監測變化類型如下:
const ( FSN_CREATE = 1 FSN_MODIFY = 2 FSN_DELETE = 4 FSN_RENAME = 8 FSN_ALL = FSN_MODIFY | FSN_DELETE | FSN_RENAME | FSN_CREATE)
但是fsnotify有個坑就是只能監測一層檔案夾的變化,多層檔案夾需要自己遍曆掛載事件。後續建立檔案夾,重新命名這種也要手動加事件。
其中每個事件都對應一個處理通道,我的想法是讓檔案處理者和事件解耦,因為後面不一定是sftp來處理上傳,也可能是rsync,也可能其他處理方式。所以後續處理者只用監聽對應事件通道,處理者這裡我用了golang的select實現了一個逾時機制,有事件就處理,無事件有個幾秒的等待時間。
fsnotify這塊代碼見: https://github.com/rootrl/Man...
sftp hanlder見: https://github.com/rootrl/Man...
sftp用的是github.com/pkg/sftp這個庫,用起來還是挺順手,但都是寫底層的api,所以我單獨封裝了個sftp_util: https://github.com/rootrl/Man... 有一些常見的上傳檔案/檔案夾,刪除檔案/檔案夾等操作
以上基本能實現主要功能了,然後我還定義了個設定檔結構,通過對應Json字元可以把欄位自動對應到這個結構上,供後續使用。這也是golang json包的方便之處。
總結
寫這個項目主要是用來練手golang的,剛開始階段,代碼可能寫得有點垃圾。。比如sftpClent用戶端這些目前是用全域變數實現的,能用,但是不夠優雅。。後續慢慢改進。。(可能永遠不會。。)
總之,Golang還是挺不錯的!