我們公司asp.net的項目都是使用FTP進行上傳下載來發布和更新的。盡管我們在發布修改之前都在本地進行進行測試,但本地的開發環境始終和外網上的實際環境還是有差別的(特別在一些數據上的差別),所以有時不可避免地出現在本地測試時沒有Bug,但上傳到外網就出現Bug的情況。
很多時候我們在ftp后如果出現bug,第一個反應就是馬上還原回更新前的狀態,也就是將舊問題替換回去。但這樣也就需要在ftp上傳前先將舊文件備份。但因為這樣做太繁瑣,有時候更新量大而且文件分散,備份舊文件就變成一件還是挺煩人的事情。雖然ftp工具都有簡單的自動提示功能,例如filezilla就可以設定同名文件的處理方式,但功能薄弱。而我也找過一些文件自動備份軟件,例如大名鼎鼎的alway sync ,但感覺它不是專門為這種情況而設計的,用起來沒有那么方便。例如:我需要搜索某一段時間里對某個更新進行備份的文件,並將這些文件批量恢復回去。
(注:當然,我覺得:
1假如有這種需求,應該會有這類型成熟的軟件,這是我不知道。有經驗的朋友可以分享一下。
2: 或者我每次更新都是用ftp來手動上傳下載是一種比較落后的做法,感覺是一種較為作坊式的項目管理方式,用收工ftp的整個過程根本不可控不可管理。公司的php項目組在發布是將文件提交至生產服務器上的svn,通過svn的鈎子對文件進行更新的。也就是說,業界可能有很多更成熟的發布做法。希望有經驗的朋友分享一下。)
基於希望能對FTP上傳文件自動備份的問題,我前一段時間使用FileSystemWatcher類編寫了一個小程序,自動的監視某個目錄,當該目錄的文件被修改后對文件作備份。注意這里是"修改后",並不是"修改前"。FileSystemWatcher里的事件都是在原文件被修改后才觸發的,並不是我們希望的在操作系統對文件修改前暫停修改操作並觸發事件,等我們備份了文件再繼續修改操作。我開始也很困惑,甚至去找一些"修改前觸發事件"的api,但發現就算c++也好像沒有這類方案(使用鈎子應該可以,但沒試過)。后來覺得微軟這樣設計也是合理的,因為對文件進行修改是操作系統的工作,而備份是出於操作系統上層的應用程序的工作,為了保持操作系統的工作的連貫性,當然不希望上層應用中斷操作系統的操作(這點純碎是個人猜測)
所以,使用FileSystemWatcher來實現監視和備份,都是備份修改過的最新文件的。這也是可以接受的,因為除了第一次更改前的舊文件不能被備份外,后續每次更改的文件都會有一份對應的備份,第二次及以后的更改都可以找回前一份文件。
1.該工具可以監視某一個目錄(可以設定是否監視子目錄),當文件被更改后(文件內容被更改,或者重命名),該文件會被自動備份到一個指定的備份目錄中。由於是”更改后觸發事件“,因為並沒有對刪除操作進行備份,因為一個文件被刪除了,在deleted事件中是找不到原來的文件的,而且通常來說,被刪除的文件在刪除前早就被備份過了。
2.文件每次被更新,其備份文件都會帶有更改時間和更改類型作為標識,以便日后區分是什么時候和什么操作導致的備份,方便記錄。
3.可以對備份文件進行按文件名,更改時間,更改類型的條件查找。並對文件進行恢復(批量將備份文件還原回去,恢復更改前的狀態)
4.可以包含子目錄監視並在備份時自動創建於被監視目錄相同的目錄結構。比如:被監視的目錄是c:\a ,備份目錄是c:\b,當c:\a\d\e\f\somefile.txt被修改后,將會在c:\b\d\e\f\somefile.txt
5.可以開機自動啟動並回復關機前的監視狀態。因為有時候軟件所在服務器可能會關機,在重新啟動后就可以自動啟動軟件並回復上次的監視狀態,減少人工干預。
6.可以自己編寫記錄備份和搜索備份的模塊(代碼里面預定義了接口),原來是將備份文件名以更改時間和更改動作,搜索時使用File在文件系統上搜索文件。但同事給的意見是:最好可以提供記錄在數據庫的方式,利用數據庫強大的檢索功能。於是就定義了兩個接口,允許自己編寫保存和查找的代碼。
這個程序核心就是FileSystemWatcher類了。我自定義了一個繼承FileSystemWatcher的子類XWXFileSystemWatcher,封裝父類,添加了一些方法和一些事件。
程序中維護着一個XWXFileSystemWatcher的列表:List<XWXFileSystemWatcher> watcherList,並與程序運行過程中的監視項的同步。
此外,程序中還定義了一個事件OnWatchSettingChanged。每個導致監視變化的操作都觸發該事件,例如開始/暫停監視,改變文件更改類型以及選擇是否包含子目錄。在該事件的事件處理函數里面同時將監視的詳細信息通過序列化的方式保持到文件中,以便下次啟動可以加載並反序列化該文件,達到恢復上次監視狀態。
程序中定義了一個可序列化的模型類WatchInfo,用來封裝一個監視項的信息,包括:監視目錄,備份目錄,更改類型,運行狀態和是否包括子目錄。如上面說的,在每次對監視項進行設置,都會觸發OnWatchSettingChanged事件去將監視項實時進行保存。
對於備份記錄的保存,默認的是以 @yyyy-mm-dd.changeType的后綴來命名備份文件,而查找備份文件也同樣的是對備份文件名的“@yyyy-mm-dd.changeType”進行分析以識別備份文件是什么時候對哪種操作進行備份的。但程序中也定義了兩個接口:IRecord和ISearchBackupFiles。可以通過繼承這兩個接口來實現自己的保存備份記錄和查找備份記錄的模塊。程序中使用了工廠模式+配置文件反射的方式來加載這些模塊。
其他具體的請見源代碼。由於個人精力與水平限制,程序中可能存在一些bug,歡迎斧正。