Jenkins持續部署-Windows環境持續部署探究1
目錄
Jenkins持續集成學習-Windows環境進行.Net開發1
Jenkins持續集成學習-Windows環境進行.Net開發2
Jenkins持續集成學習-Windows環境進行.Net開發3
Jenkins持續集成學習-Windows環境進行.Net開發4
Jenkins持續集成學習-搭建jenkins問題匯總
Jenkins持續部署-Windows環境持續部署探究1
前言
在之前的文章中,對Windows環境下的持續集成方案進行探究,接下來對Windows環境下持續部署的方案進行學習與研究。
目的
當jenkins集成編譯成功后,將文件上傳到指定的服務器FTP目錄。本文將介紹關於持續部署需要的一些技術方案的實現,在后續文章中繼續對持續集成具體的邏輯進行細化梳理。
方案流程
當jenkins編譯完成之后,我們需要處理以下事項完成持續部署。

- jenkins編譯成功,則將所有的exe和dll文件先壓縮打包,文件名可以命名為Job名稱或者版本號
- 壓縮完成后將壓縮文件上傳到指定的FTP
- 上傳完成后,則需要關閉服務器上的指定服務
- 關閉完成后替換原始的程序目錄下的文件
- 啟動服務
這里暫時不探討服務可用性的具體細節,也不討論服務升級失敗的回退工作等具體細節。
技術實現
可以分析出上述流程中涉及到的技術要點。
- 調用腳本對指定的文件進行壓縮,在windows上使用PowerShell執行腳本再合適不過了。
- 通過FTP上傳到服務器,可以通過jenkins的FTP插件或者通過PowerShell腳本將文件上傳到指定服務器上。
- 關閉服務器上的指定服務,這里就需要支持遠程調用,在windows上可以通過winrm執行遠程服務調用。
PowerShell
Windows PowerShell 是專門為系統管理員設計的 Windows 命令行 Shell。 Windows PowerShell 包括可以單獨或組合使用的交互提示和腳本編寫環境。這里不探討PowerShell的使用細節,因為這不是本篇文章的關注重點,具體的關於PowerShell的介紹可以看微軟的官方文檔Windows PowerShell 入門
FTP上傳插件
jenkins上有支持的FTP插件,比如Publish Over FTP Plugin,下載之后安裝重啟jenkins。
插件配置
在系統管理-系統設置下找到Publish over FTP項的設置,添加FTP服務的地址,端口,用戶名和密碼等相關配置,然后點擊TestConfiguration按鈕,若顯示Success表示配置成功。可以手工添加多個FTP配置。

點擊Advanced按鈕修改端口或超時時間等配置

配置完成后到Job中添加FTP上傳功能,在Build中點擊Add Build step選擇Send file over FTP

在Name通過下拉選擇前面配置的FTP站點,在Transfers配置需要上傳的文件和上傳到遠程的目錄。

Source files:支持通配符,如上傳所有文件*.*,或bin/Release/下的所有文件
Remove prefix:表示上傳文件去除前綴,FTP默認會將文件的相對路徑一起上傳,若不需要bin/Release則可以配置去除該相對路徑,如bin/Release/Test.exe上傳到FTP上若沒有指定FTP遠程相對路徑,則為FTP根目錄下的Test.exe文件。
Remote directory:表示上傳到FTP目錄下的哪個相對目錄中,一般來說我們可以按Job名稱分文件夾,可以通配置Jenkins內置的環境變量,如$JOB_NAME/
上傳FTP前需要保證FTP上目錄結構存在,否則會上傳失敗。因此上傳FTP前需要通過腳本到服務器的FTP目錄上創對應的文件夾路徑。
一般來說我們編譯完成后需要將程序按版本號分目錄存在,比如1.0.X的存放到1.0的目錄中。2.0.X的存放到2.0的目錄中。因此我們可以在Remote directory填寫${JOB_NAME}/$PROCESS_VERSION,如下圖所示

而$PROCESS_VERSION變量的值我們需要在前面的腳本中獲取,由於在jenkinsBuild步驟中創建的每個powershell腳本塊,jenkins都會將其保存到臨時的XXXX.ps1腳本文件中,因此不同的步驟產生的變量是在不同的腳本文件中,也就是在不同的作用域中。因此在前面創建的腳本獲取到的版本號,無法直接在下一個腳本中獲取。
關於powershell的變量作用域可以查看Powershell變量的作用域。
如下圖所示,第一個腳本中賦值的$PROCESS_VERSION在后面的腳本以及FTP目錄中都是獲取不到該變量的。

因此我們可以通過將變量保存到文件,然后重新載入到Jenkins的環境變量中,Jenkins的環境變量在Jenkins當前Job中都可以獲取到。
環境變量插件
使用Jenkins的環境變量插件EnvInject Plugin實現上述功能。安裝完插件之后重啟Jenkins。
如果我們多個Job需要用到同樣的參數常量,那我們可以將參數直接在Jenkins配置中注入到環境變量中,然后可以通過環境變量$Env:XXXX獲取到我們配置的變量值。
配置全局環境變量
在系統管理-系統設置下找到Global properties項,勾選環境變量,后即可設置全局的環境變量。這樣當這些變量修改后,只需要在設置中修改一次,而無需修改每個Job中的腳本變量值。

使用環境變量
我們現在可以直接在Job中使用配置好的全局環境變量。在構建之后,可以在當前構建項的Environment Variables查看到已加載的環境變量
、
從文件注入環境變量
現在我們就可以將將版本號信息存入到文件中,然后重新加載到全局環境變量中了。
首先在通過腳本獲取到程序的版本號,將它保存到文件中,保存格式為變量名=變量值,如將PROCESS_VERSION="1.0.0.0"保存到Version.txt文件中。
然后通過環境變量注入插件從文本中讀取環境變量,在Build中添加Inject environment variables步驟,在Properties File Path中填寫Version.txt,則會從文本中讀取環境變量,多個環境變量通過換行分割。

默認PowerShell保存的格式是含有BOM的Unicode編碼,而Jenkins讀取ASCII編碼格式。因此需要指定文本輸出編碼為ASCII
腳本執行
通過Powershell腳本也可以調用.Net庫將文件壓縮或上傳,這里暫時不討論腳本編寫細節問題。后續文章將給出完整的解決方案。
遠程調用
在Linux環境下可以通過SSH進行遠程調用,而在Windows環境下則可以使用Windows 遠程管理 (Windows Remote Management,簡稱WinRM)。
WinRM是微軟實現的WS-Management協議的, 這是一種基於標准的簡單對象訪問協議(SOAP), 由於它是基於防火牆友好的協議, 因此允許來自不同供應商的硬件和操作系統交互。關於WinRM具體的介紹可以查看Windows Remote Management
我們可以理解為WinRM提供了一個服務端,同時向外暴露了相關的API,而同時Powershell可以與WinRM進行交互,即Powershell本身就是一個遠程調用的客戶端,通過Powershell執行相關的命令與WinRM交互,從而實現遠程調用,執行自定義腳本,甚至是執行服務器上的指定路徑下的腳本。
因此我們若需要進行遠程調用,首先在對應的服務器上需要開啟WinRM的相關功能。
啟用WinRM服務
-
快速配置
微軟為了簡化WinRM的配置,提供了一個快捷命令進行默認的快速配置。通過調用
winrm quickconfig進行快速配置。也可以跳過該步驟,直接運行第二步驟開啟WinRM服務。
如下返回則為正常配置成功
PS C:\Users\Administrator> winrm quickconfig 在此計算機上,WinRM 已設置為接收請求。 WinRM 沒有設置成為了管理此計算機而允許對其進行遠程訪問。 必須進行以下更改: 在 HTTP://* 上創建 WinRM 偵聽程序接受 WS-Man 對此機器上任意 IP 的請求 啟用 WinRM 防火牆異常。 配置 LocalAccountTokenFilterPolicy 以遠程向本地用戶授予管理權限。 進行這些更改嗎[y/n]? y WinRM 已經進行了更新,以用於遠程管理。 在 HTTP://* 上創建 WinRM 偵聽程序接受 WS-Man 對此機器上任意 IP 的請求 WinRM 防火牆異常已啟用。 已配置 LocalAccountTokenFilterPolicy 以遠程向本地用戶授予管理權限。需要注意的是,在我本地win10環境,無法執行快速配置,提示說網絡連接類型是公用。
PS C:\Users\Dm_ca> winrm quickconfig 已在此計算機上運行 WinRM 服務。 WSManFault Message ProviderFault WSManFault Message = 由於此計算機上的網絡連接類型之一設置為公用,因此 WinRM 防火牆例外將不運行。 將網絡連接類型更改為域或專用,然后再次嘗試。 錯誤編號: -2144108183 0x80338169 由於此計算機上的網絡連接類型之一設置為公用,因此 WinRM 防火牆例外將不運行。 將網絡連接類型更改為域或專用,然后再次嘗試。通過
Get-NetConnectionProfile命令可以看到網絡類型(和網絡和Internet設置中看到的是一樣的)其中NetworkCategory : Public即顯示該網絡的種類。PS C:\WINDOWS\system32> Get-NetConnectionProfile Name : Seven InterfaceAlias : WLAN InterfaceIndex : 17 NetworkCategory : Private IPv4Connectivity : Internet IPv6Connectivity : NoTraffic Name : 未識別的網絡 InterfaceAlias : vEthernet (Default Switch) InterfaceIndex : 29 NetworkCategory : Public IPv4Connectivity : NoTraffic IPv6Connectivity : NoTraffic通過管理員權限運行
Set-NetConnectionProfile -NetworkCategory Private將所有網絡設置為專用網絡類型后
再次嘗試快速配置。PS C:\WINDOWS\system32> Set-NetConnectionProfile -NetworkCategory Private PS C:\WINDOWS\system32> Get-NetConnectionProfile Name : Seven InterfaceAlias : WLAN InterfaceIndex : 17 NetworkCategory : Private IPv4Connectivity : Internet IPv6Connectivity : NoTraffic Name : 未識別的網絡 InterfaceAlias : vEthernet (Default Switch) InterfaceIndex : 29 NetworkCategory : Private IPv4Connectivity : NoTraffic IPv6Connectivity : NoTrafficwinrm qc是winrm quickconfig縮寫
-
啟用遠程服務
通過輸入
Enable-PSRemoting –Force啟用Powershell遠程調用功能。若沒有-Force會有若干選項需要你進行確認。輸入了-Force則自動會確認,建議帶上該參數。PS C:\Users\Administrator> Enable-PSRemoting –Force 在此計算機上,WinRM 已設置為接收請求。 WinRM 已經進行了設置,以用於在此計算機上進行遠程管理。若第一步驟
winrm qc存在網絡類型為公網無法進行配置時,當前命令添加SkipNetworkProfileCheck跳過網絡類型檢查,完整命令為Enable-PSRemoting -SkipNetworkProfileCheck -Force。若輸入
Enable-PSRemoting,則可以不再輸入winrm qc進行配置。前者做的工作已經包含了后者所做的所有工作。 -
查看WinRM服務監聽
通過
winrm enumerate winrm/config/listener可以查看WinRM服務的當前監聽信息PS C:\Users\Administrator> winrm enumerate winrm/config/listener Listener Address = * Transport = HTTP Port = 5985 Hostname Enabled = true URLPrefix = wsman CertificateThumbprint ListeningOn = 10.60.45.239, 127.0.0.1, XXXXXXXXXXX若上一步WINRM配置沒有成功,則會返回以下信息
PS C:\Users\Dm_ca> winrm enumerate winrm/config/listener WSManFault Message ProviderFault WSManFault Message = 拒絕訪問。 -
啟用Powershell本地腳本執行
若需要在服務上執行本地腳本,則需要啟用本地腳本執行權限。通過執行
set-ExecutionPolicy RemoteSigned允許本地腳本執行。PS C:\Users\Administrator> set-ExecutionPolicy RemoteSigned 執行策略更改 執行策略可以防止您執行不信任的腳本。更改執行策略可能會使您面臨 about_Execution_Policies 幫助主題中所述的安全風險。是否要更改執行策略? [Y] 是(Y) [N] 否(N) [S] 掛起(S) [?] 幫助 (默認值為“Y”): y -
獲取winrm客戶端配置信息
通過上述4個步驟,服務端的遠程調用已經開啟,由於winrm本身有白名單安全策略,因此需要配置以下客戶端的配置,允許指定的ip執行遠程調用。通過輸入
winrm get winrm/config/client獲取客戶端配置。PS C:\Users\Administrator> winrm get winrm/config/client Client NetworkDelayms = 5000 URLPrefix = wsman AllowUnencrypted = false Auth Basic = true Digest = true Kerberos = true Negotiate = true Certificate = true CredSSP = false DefaultPorts HTTP = 5985 HTTPS = 5986 TrustedHostsGet-Item WSMan:\localhost\Client\TrustedHosts效果也一樣。 -
設置白名單地址
TrustedHosts表示的是白名單地址。
通過Set-Item wsman:\localhost\client\trustedhosts *設置允許所有IP調用。
通過Set-Item wsman:\localhost\client\trustedhosts "127.0.0.1,127.0.0.2"設置允許指定IP調用cmd下可以輸入winrm set winrm/config/client @{TrustedHosts="*"},測試了powershell下不支持該命令Set-Item wsman:\localhost\client\trustedhosts "127.0.0.1,127.0.0.2" WinRM 安全配置。 此命令修改 WinRM 客戶端的 TrustedHosts 列表。TrustedHosts 列表中的計算機可能不會經過身份驗證。該客戶端可能會向這些計算機發送憑據信息。是否確實要修改此列表? [Y] 是(Y) [N] 否(N) [S] 暫停(S) [?] 幫助 (默認值為“Y”): y PS C:\WINDOWS\system32> winrm get winrm/config/client Client NetworkDelayms = 5000 URLPrefix = wsman AllowUnencrypted = false Auth Basic = true Digest = true Kerberos = true Negotiate = true Certificate = true CredSSP = false DefaultPorts HTTP = 5985 HTTPS = 5986 TrustedHosts = 127.0.0.1,127.0.0.2 -
客戶端遠程調用
當設置好上述配置我們就可以測試以下遠程調用是否完成,通過在d盤放一個
hellworld.ps1腳本,填寫以下內容。hello world!然后就可以在本地powershell中輸入以下指令測試遠程調用是否正常返回hello world!
$account = "administrator" $password = "test1" $address="127.0.0.1" $secpwd = convertto-securestring $password -asplaintext -force $cred = new-object System.Management.Automation.PSCredential -argumentlist $account,$secpwd invoke-command -computername $address -Credential $cred -command {d:helloworld.ps1}- 其中需要輸入服務器的用戶名和密碼。通過
convertto-securestring將明文密碼轉換為安全字符串,這樣避免了明文密碼在網絡上傳輸泄露。 - 然后通過用戶名和密碼創建一個身份授權對象。
- 最終通過
invoke-command將服務器地址傳入以及授權對象傳入即可執行遠程腳本調用。
想更詳細的了解啟用遠程服務的細節可以查看Enable Powershell Remoting
需要注意的是,若使用域賬戶用戶名進行遠程調用時,用戶名需要使用
域名\用戶名,而使用非域賬戶用戶名進行遠程調用時,用戶名需要使用\用戶名。否則可能出現如下的錯誤信息

比如我要遠程登錄的用戶是非域用戶,用戶名為administrator,則使用\administrator。域賬號是把帳號存儲於域中的某一台服務器,分享給同一個域中的所有計算機使用。
- 其中需要輸入服務器的用戶名和密碼。通過
升級服務
通過powershell與winrm實現遠程調用,服務升級就是將上傳到FTP的程序替換原有的程序即可。
啟動服務
這里需要說明的一點是,控制台程序和含有GUI界面的程序可以通過調用命令殺掉進行實現關閉程序,但是要通過powershell啟用相關的控制他程序或含有用戶界面的程序,則很難做到。主要原因是在windows環境下遠程命令執行和登錄windows用戶一樣,都是基於會話執行。在Windows安全模型設計上,是不支持啟動其他會話的程序。相關問題可以查看Use Powershell to start a GUI program on a remote machine。
換句話說,在會話連接釋放時,則會自動注銷會話相關的資源。因此當WinRM遠程調用結束后則會釋放臨時會話資源。
為了實現啟用GUI程序,可以使用PsExec。PsExec 是一款輕量級的遠程替換設備, 可讓您在其他系統上執行進程, 並為控制台應用程序提供完整的交互功能, 而無需手動安裝客戶端軟件。對於PsExec具體使用暫時沒有驗證過,有時間后面再做探討,這里不進行深究。
另一種方案是Powershell所能實現的是,基於Windows的定時任務,可以設定在1分鍾后啟動GUI的exe文件。(Windows任務最小時間單位是1分鍾)實際上來說服務中斷1分鍾可不是好事,雖然能實現啟動服務,但是不建議使用,不做過多探討。
最好的方式是將服務器上的程序注冊為Windows服務,那么就很好的支持服務的關閉和啟動。
總結
本文對Windows下的持續部署方案所設計到相關的技術進行了簡單介紹,后續的持續集成將完全使用本篇文章設計到的Powershell腳本和遠程調用相關技術實現,后續持續集成唯一的要點就是持續集成邏輯的腳本編寫。在后續文章中,將會介紹powershell的壓縮解壓,ftp腳本上傳,以及通過腳本生成差量更新包等具體工作。
- Windows PowerShell 入門
- Powershell變量的作用域
- Windows Remote Management
- windows服務器遠程執行命令(PowerShell+WinRM)
- winServer-常用winrm命令
- Use Powershell to start a GUI program on a remote machine
- Enable Powershell Remoting
- Enabling PowerShell remoting fails due to Public network connection type
- Automating with Jenkins and PowerShell on Windows - Part 2
微信掃一掃二維碼關注訂閱號傑哥技術分享
本文地址:https://www.cnblogs.com/Jack-Blog/p/10922038.html
作者博客:傑哥很忙
歡迎轉載,請在明顯位置給出出處及鏈接

