The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

使用 MSDeploy 部署網站時如何避免刪除遠端網站的檔案

這陣子都在玩跟網站部署有關的相關技術,其中有一段一定要透過 MSDeploy 手動部署網站上去,但問題是在透過 MSDeploy 批次檔進行手動部署網站時,由於 MSDeploy 會自動比對遠端與本地端的檔案差異執行「雙向同步」,這反而造成了當遠端伺服器裡有新增的檔案(例如在 App_Data 下有動態新增的檔案),每次透過 MSDeploy 部署後那些不存在本地端的檔案全部都會被刪除,這是個大問題,而我也研究了好些時間才找到方法解決這個問題。

我們有個幾年前做的案子,當時是使用 網站專案 (WebSite Project) 的形式,由於這種專案類型無法使用 Visual Studio 2010 的 One-Click Publish (單鍵發行) 功能,所以必須搭配 Visual Studio 2010 Web Deployment Projects (WDP) 將整個網站封裝成 部署套件 (Deployment Package) 然後再透過部署套件裡��� MSDeploy 批次檔進行手動部署作業,雖然麻煩些,但我找不到更好的方式了。

要搭配由 WDP 自動產生的部署批次檔發行網站,可以在指令檔最後加上 MSDeploy.exe 的額外參數,一般來講預設的執行指令範例如下:

發行至本機 IIS 7 / 7.5Default Web Site 站台 ( 備註: /T 要改成 /Y 才會真的執行部署作業 )

DemoSite_Deploy.deploy.cmd /T "-setParam:'IIS Web Application Name'='Default Web Site'" 

如果要避免遠端的檔案被意外刪除的話,可以改成以下指令 ( 需啟用 DoNotDeleteRule 規格 )
備註:由於版面寬度的關係,以下指令範例我將 DemoSite_Deploy.deploy.cmd 改以 {X} 替代。

{X}.cmd /T "-setParam:'IIS Web Application Name'='Default Web Site'" -enableRule:DoNotDeleteRule

只要加上這個參數 ( -enableRule:DoNotDeleteRule ) 就能啟用「不要刪除遠端檔案」這條規格,你在正式機上的檔案也不會再被無故刪除了。

以下是幾個使用 MSDeploy 部署批次檔的使用範例,供各位參考:

透過 Web Deployment Agent Service 執行遠端部署,並指定帳號、密碼

DemoSite_Deploy.deploy.cmd /T /M:172.16.22.33 /U:Administrator /P:P@ssw0rd -enableRule:DoNotDeleteRule "-setParam:'IIS Web Application Name'='Default Web Site'"

事實上在執行 MSDeploy 批次檔的過程中,實際執行的 msdeploy.exe 指令與參數都會顯示在畫面上,你也可以拿這些參數來進行修改後重新執行。

 

 

透過 Web Management Service 執行遠端部署,並指定帳號、密碼

照文件來說,應該可以直接部署網站到遠端的 IIS 7 裡,不過我怎樣測試都無法成功執行,最後研究出來的方法是自行修改 msdeploy.exe 的參數才能成功部署,而且還要使用管理者權限的帳戶才行,以下是指令碼內容,重點的部分我標示為「紫色」,需要替換成實際字串的部分我會標示「紅色」:

"C:\Program Files\IIS\Microsoft Web Deploy V2\msdeploy.exe" -source:package='C:\DemoSite_Deploy\obj\Debug\Package\DemoSite_Deploy.zip' -dest:auto,wmsvc='172.16.22.33',userName='Administrator',password='123123123',includeAcls='False' -verb:sync -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -setParamFile:"C:\DemoSite_Deploy\obj\Debug\Package\DemoSite_Deploy.SetParameters.xml"  -whatif  -enableRule:DoNotDeleteRule -setParam:'IIS Web Application Name'=DemoSite -allowUntrusted

備註:若要使用非管理者權限的帳戶透過 Web Management Service 執行遠端部署的方式我怎樣都試不成功,等日後研究出來後再補充到這篇文章來。

2011-06-02 補充說明

研究、嘗試了十幾個小時後,我終於找到了問題所在,天啊~ 為了找出一個正確的「用法」找了我十多個小時,實在真累人,由此可見寫一份好的技術文件有多麼重要啊!

由 Visual Studio 2010 產生的部署套件目錄中有個 *_Deploy.deploy-readme.txt 說明檔,我也是透過這份文件學習如何使用此工具的,其中有段文字是這樣寫的。

========================================================

選擇性旗標:
--------------------------
根據預設,這個指令碼會用目前的使用者認證,在呼叫這個指令碼的目前電腦上進行部署,不使用代理程式服務。只有進階案例才要傳遞下列值。

/M:<目的伺服器名稱或服務 URL>
    如果未指定這個旗標,封裝會安裝在執行命令的電腦上。服務 URL 可以採用下列格式:
https://<DestinationServer>:8172/MSDeploy.axd
    這種格式要求必須在目的伺服器上安裝 IIS 7,而且必須設定 IIS 7 Web 管理服務 (WMSvc) 和 Web 部署處理常式。
    服務 URL 也可以採用下列格式:
http://<DestinationServer>/MSDeployAgentService
    這種格式要求必須具有目的伺服器上的系統管理權限,而且要求必須在目的伺服器上安裝 Web Deploy 遠端服務 (MsDepSvc)。目的伺服器上不必安裝 IIS 7。

/U:<UserName>
/P:<Password>
/G:<True | False>
    指定封裝是藉由在目的伺服器上建立暫時性接聽程式的方式進行部署。這不需要在目的伺服器上進行任何特殊安裝,但您必須是該伺服器上的系統管理員。這個旗標的預設值是 False。

/A:<Basic | NTLM>
    指定要使用的驗證類型。可能值為 NTLM 和「基本」。如果指定 wmsvc 提供者設定,則預設驗證類型為「基本」,否則預設驗證類型為 NTLM。

========================================================

依據上述說明,我在部署站台時會使用以下指令:

DemoSite_Deploy.deploy.cmd /T "/M:https://172.16.22.33:8172/MSDeploy.axd" /U:Administrator /P:P@ssw0rd -enableRule:DoNotDeleteRule "-setParam:'IIS Web Application Name'='Default Web Site'" -allowUntrusted 

但透過這一行指令,我會得到一個 (401) 未經授權 的錯誤:

我就是為了這個問題闖關了十多小時,最後解答出原來要指定 /A:Basic 才可以正確通過授權!Orz…

為什麼我這十個小時都沒有試出正確的解答嗎?就因為技術文件這樣寫:如果指定 wmsvc 提供者設定,則預設驗證類型為「基本」,否則預設驗證類型為 NTLM。

重點是:Visual Studio 2010 產生的 *_Deploy.deploy.cmd 根本不支援 wmsvc 提供者設定,他這樣寫讓我認為說我只要在指定 /A 參數的時候使用 https://<DestinationServer>:8172/MSDeploy.axd 的型態他會聰明到自己判斷驗證的類型,這實在讓我太受傷了,原來要自己加上 /A:Basic 才可以正確通過授權,只要不加上這段預設就是以 NTLM 進行驗證,而且錯誤訊息永遠是 (401) 未經授權 這麼一般的錯誤!

 

心得分享

為了這個錯誤,我用盡吃奶的力量,挖出畢生絕學努力偵錯,查了所有 WMSvc Log、Event Log、Process MonitorTCPViewNetwork Monitor 3.4Failed Request Tracing… 等相關記錄,還看完了以下所有文章 (這些文章對我這次遇到的問題幾乎都沒幫助):

最後外加數十次的 Try and Error 才找出可用的指令。第一天試到早上 5:00,第二天試到晚上 8:00 才找出答案。

走過這一遭,收穫最大的就是研究出 Web Management Service 與 IIS7 Authentication 的執行細節,對於 MSDeploy.exe 指令的使用也更進一步的瞭解,以後應該是不會再遇到任何困難了,因為實在是刻苦銘心啊,呵呵。

最近我公司內有個開發人員問我,他說他好像找不到一個好的學習方法,經常覺得自己浪費很多時間在嘗試錯誤,每次都卡關到需要問人才能解決。

我跟他說,這個問題必須分成兩個層面來回答:

1. 經常卡關,是因為找不到解決問題的方向,找不到方向的主因除了經驗不足外,基礎知識的缺乏也是主因之一,在學習的過程中必須不斷的充實那些來不及學的知識,打好程式設計的基礎才有可能替未來鋪路,慢慢減緩找不到方向的問題。

2. 在公司裡有人能問是很幸福的事,在台灣當開發人員,有很大部分的人的工作環境都是無人可問的,或者是有人也不見得能問,而且我也跟他說,我的程式生涯十多年,有 80% 以上的問題問不到人,都要靠自己解決,過程也是非常辛苦且無助,難道我花的時間可以算是「浪費時間」嗎?解決問題的過程雖然辛苦,但是在找答案的過程中你是否是真的用心才是你成長的關鍵,在還沒找到答案之前,過程都是學習,用心找答案你會對答案有很深的「感覺」,這份記憶會跟著你一輩子,不容易忘記;問來的答案不容易產生共鳴,只知道這是一種解決辦法,過了一陣子沒用到就會忘記。

所以,身為開發人員,花時間在嘗試錯誤是合理的,但用這種方式學習卻最沒效率,較為正確的學習態度還是要搭配基礎知識的建立才能將自身的能力慢慢的提升到一定的境界,與各位共勉之。:-)

 

相關連結