CI / CD的採用改變了開發人員和測試人員如何發佈軟體。
老陳獨白
2021年1月19日 星期二
持續整合、持續交付、持續部署(CI/CD)簡介
概述:
一 、持續整合
從上圖可以看到,持續整合應該至少包括以下幾部分:
- 自動化構建Continuous Build
- 自動化測試Continuous Test
- 自動化整合Continuous Intergration
- 自動化構建
包括以下過程:
- 將原始碼編譯成為二進位制碼
- 打包二進位制碼
- 執行自動化測試
- 生成文件
- 生成分發媒體(例如:Debian DEB、Red Hat RPM或者Windows MSI檔案)
所以,自動化構建,從功能角度分,最關鍵的是三部分:版本控制工具、構建工具、CI伺服器。而其中最核心的又是構建工具。其他開源的、與持續整合相關的工具也有很多,但大多數是輔助性的工具。
(1)版本控制工具
有時,版本控制又稱為配置管理(SCM),所以版本控制工具同時也是配置管理工具。在各類版本控制的開源軟體中,最著名的莫過於CVS、SVN(Subversion)、GIT三個了。
這三個工具各有千秋。其中,GIT支援離線工作,更適合開源軟體或者開發人員不能集中辦公情況下的版本管理工作。同時,SVN和GIT可以配合使用。
(2)構建工具
構建工具是持續整合的核心,它對原始碼進行自動化編譯、測試、程式碼檢查,以及打包程式、部署(釋出)到應用伺服器上。從配置管理工具上下載最新原始碼後,所有的後續工作幾乎都可以通過構建工具完成。
在java開發中,比較有名的構建工具就是Ant、Maven、Gradle。在PHP開發中,Phing(基於Ant)也比較有名。同樣的,Maven也可通過相關的PHP-Maven外掛完成對PHP開發構建的支援。
(3)CI伺服器
CI伺服器的主要作用就是提供一個平臺,用於整合版本控制和構建工作,並管理、控制自動化的持續整合。
開源軟體中,比較有名的CI伺服器包括Jenkins、CruiseControl、Continuum。而比較有名的商業化CI伺服器是TeamCity、Bamboo、Pulse等。
(4)其他工具
很多工具可以通過與構建工具、CI工具相結合(當然,其中有很多工具也可以單獨工作),來完成更多的自動測試、報告生成等工作。根據工具不同,其具體的結合方法也不同,但大體都是通過外掛形式進行結合的。例如:
- Maven中通過依賴和plugin方式引入第三方工具
- Jenkins主要通過各類外掛引入第三方工具
這些工具種類實在太多,可以根據實際工作需要進行選擇。
2.自動化測試
自動化測試是持續整合必不可少的一部分,基本上,沒有自動化測試的持續整合,都很難稱之為真正的持續整合。我們希望持續整合能夠儘早的暴露問題,但這遠非配置一個 Hudson/Jenkins伺服器那麼簡單,只有真正用心編寫了較為完整的測試用例,並一直維護它們,持續整合才能孜孜不倦地執行測試並第一時間報告問題。
測試自動化是使用特定的軟體(獨立於被測試的軟體)來控制測試的執行以及比較實際輸出與預期輸出。測試自動化可以將某些重複但必要的任務自動化,或者執行某些難以手動執行的額外測試。
自動化測試還包括單元測試、整合測試、系統測試、驗收測試、效能測試等,在不同的場景下,它們都能為軟體開發帶來極大的價值。
二、持續交付
三、持續部署
在持續交付的實踐中,交付的目標是QA,但是實際上,軟體最終是要交付到客戶手上的。在SaaS領域裡,持續部署採用得比較廣泛,因為服務比較容易做到靜默升級。
採用持續部署的前提是自動化測試的覆蓋率足夠高。
採用持續部署的好處是能減少運維的工作量,縮短新特性從開發到實際交付的週期
四、CI/CD具體實現
常見CI/CD工具及其比較:
這裡的支援,意思應該是直接的支援,例如Jenkins,其實和git結合也很簡單,通過指令碼就可以實現。
五、持續整合工具集之 Jenkins簡介
Jenkins 是一個可擴充套件的持續整合引擎。
1.主要用於:
- 持續、自動地構建/測試軟體專案。
- 監控一些定時執行的任務。Jenkins擁有的特性包括:
2.Jenkins擁有的特性包括:
- 易於安裝-只要把jenkins.war部署到servlet容器,不需要資料庫支援。
- 易於配置-所有配置都是通過其提供的web介面實現。
- 整合RSS/E-mail通過RSS釋出構建結果或當構建完成時通過e-mail通知。
- 生成JUnit/TestNG測試報告
- 分散式構建支援Jenkins能夠讓多臺計算機一起構建/測試。
- 檔案識別:Jenkins能夠跟蹤哪次構建生成哪些jar,哪次構建使用哪個版本的jar等。
- 外掛支援:支援擴充套件外掛,你可以開發適合自己團隊使用的工具。
3.Jenkins的出現
目前持續整合(CI)已成為當前許多軟體開發團隊在整個軟體開發生命週期內側重於保證程式碼質量的常見做法。它是一種實踐,旨在緩和和穩固軟體的構建過程。並且能夠幫助您的開發團隊應對如下挑戰:
- 軟體構建自動化 :配置完成後,CI系統會依照預先制定的時間表,或者針對某特定事件,對目標軟體進行構建。
- 構建可持續的自動化檢查 :CI系統能持續地獲取新增或修改後簽入的原始碼,也就是說,當軟體開發團隊需要週期性的檢查新增或修改後的程式碼時,CI系統會不斷確認這些新程式碼是否破壞了原有軟體的成功構建。這減少了開發者們在檢查彼此相互依存的程式碼中變化情況需要花費的時間和精力。
- 構建可持續的自動化測試 :構建檢查的擴充套件部分,構建後執行預先制定的一套測試規則,完成後觸發通知(Email,RSS等等)給相關的當事人。
- 生成後後續過程的自動化 :當自動化檢查和測試成功完成,軟體構建的週期中可能也需要一些額外的任務,諸如生成文件、打包軟體、部署構件到一個執行環境或者軟體倉庫。這樣,構件才能更迅速地提供給使用者使用。
部署一個CI系統需要的最低要求是,一個可獲取的原始碼的倉庫,一個包含構建指令碼的專案。
下圖概括了CI系統的基本結構:
4.使用Jenkins的一些理由:
該系統的各個組成部分是按如下順序來發揮作用的:
- 開發者檢入程式碼到原始碼倉庫。
- CI系統會為每一個專案建立了一個單獨的工作區。當預設或請求一次新的構建時,它將把原始碼倉庫的原始碼存放到對應的工作區。
- CI系統會在對應的工作區內執行構建過程。
- (配置如果存在)構建完成後,CI系統會在一個新的構件中執行定義的一套測試。完成後觸發通知(Email,RSS等等)給相關的當事人。
- (配置如果存在)如果構建成功,這個構件會被打包並轉移到一個部署目標(如應用伺服器)或儲存為軟體倉庫中的一個新版本。軟體倉庫可以是CI系統的一部分,也可以是一個外部的倉庫,諸如一個檔案伺服器或者像Java.NET、 SourceForge之類的網站。
- CI系統通常會根據請求發起相應的操作,諸如即時構建、生成報告,或者檢索一些構建好的構件。
Jenkins就是這麼一個CI系統。之前叫做Hudson。
- 是所有CI產品中在安裝和配置上最簡單
- 基於Web訪問,使用者介面非常友好、直觀和靈活,在許多情況下,還提供了AJAX的即時反饋。
- Jenkins是基於Java開發的(如果你是一個Java開發人員,這是非常有用的),但它不僅限於構建基於Java的軟體。
- Jenkins擁有大量的外掛。這些外掛極大的擴充套件了Jenkins的功能;它們都是開源的,而且它們可以直接通過web介面來進行安裝與管理。
5.Jenkins的目標
Jenkins的主要目標是監控軟體開發流程,快速顯示問題。所以能保證開發人員以及相關人員省時省力提高開發效率。
CI系統在整個開發過程中的主要作用是控制:當系統在程式碼儲存庫中探測到修改時,它將執行構建的任務委託給構建過程本身。如果構建失敗了,那麼CI系統將通知相關人員,然後繼續監視儲存庫。它的角色看起來是被動的;但它確能快速反映問題。
特別是它具有以下優點:
- Jenkins一切配置都可以在web介面上完成。有些配置如MAVEN_HOME和Email,只需要配置一次,所有的專案就都能用。當然也可以通過修改XML進行配置。
- 支援Maven的模組(Module),Jenkins對Maven做了優化,因此它能自動識別Module,每個Module可以配置成一個job。相當靈活。
- 測試報告聚合,所有模組的測試報告都被聚合在一起,結果一目瞭然,使用其他CI,這幾乎是件不可能完成的任務。
- 構件指紋(artifact fingerprint),每次build的結果構件都被很好的自動管理,無需任何配置就可以方便的瀏覽下載。
2015年10月19日 星期一
10 lsof Command Examples in Linux
1. List all Open Files with lsof Command
# lsof COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME init 1 root cwd DIR 253,0 4096 2 / init 1 root rtd DIR 253,0 4096 2 / init 1 root txt REG 253,0 145180 147164 /sbin/init init 1 root mem REG 253,0 1889704 190149 /lib/libc-2.12.so init 1 root 0u CHR 1,3 0t0 3764 /dev/null init 1 root 1u CHR 1,3 0t0 3764 /dev/null init 1 root 2u CHR 1,3 0t0 3764 /dev/null init 1 root 3r FIFO 0,8 0t0 8449 pipe init 1 root 4w FIFO 0,8 0t0 8449 pipe init 1 root 5r DIR 0,10 0 1 inotify init 1 root 6r DIR 0,10 0 1 inotify init 1 root 7u unix 0xc1513880 0t0 8450 socket
- cwd current working directory
- rtd root directory
- txt program text (code and data)
- mem memory-mapped file
- r for read access.
- w for write access.
- u for read and write access.
- DIR – Directory
- REG – Regular file
- CHR – Character special file.
- FIFO – First In First Out
2. List User Specific Opened Files
# lsof -u tecmint
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1838 tecmint cwd DIR 253,0 4096 2 /
sshd 1838 tecmint rtd DIR 253,0 4096 2 /
sshd 1838 tecmint txt REG 253,0 532336 188129 /usr/sbin/sshd
sshd 1838 tecmint mem REG 253,0 19784 190237 /lib/libdl-2.12.so
sshd 1838 tecmint mem REG 253,0 122436 190247 /lib/libselinux.so.1
sshd 1838 tecmint mem REG 253,0 255968 190256 /lib/libgssapi_krb5.so.2.2
sshd 1838 tecmint mem REG 253,0 874580 190255 /lib/libkrb5.so.3.3
3. Find Processes running on Specific Port
# lsof -i TCP:22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1471 root 3u IPv4 12683 0t0 TCP *:ssh (LISTEN)
sshd 1471 root 4u IPv6 12685 0t0 TCP *:ssh (LISTEN)
4. List Only IPv4 & IPv6 Open Files
# lsof -i 4 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rpcbind 1203 rpc 6u IPv4 11326 0t0 UDP *:sunrpc rpcbind 1203 rpc 7u IPv4 11330 0t0 UDP *:954 rpcbind 1203 rpc 8u IPv4 11331 0t0 TCP *:sunrpc (LISTEN) avahi-dae 1241 avahi 13u IPv4 11579 0t0 UDP *:mdns avahi-dae 1241 avahi 14u IPv4 11580 0t0 UDP *:58600 # lsof -i 6 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rpcbind 1203 rpc 9u IPv6 11333 0t0 UDP *:sunrpc rpcbind 1203 rpc 10u IPv6 11335 0t0 UDP *:954 rpcbind 1203 rpc 11u IPv6 11336 0t0 TCP *:sunrpc (LISTEN) rpc.statd 1277 rpcuser 10u IPv6 11858 0t0 UDP *:55800 rpc.statd 1277 rpcuser 11u IPv6 11862 0t0 TCP *:56428 (LISTEN) cupsd 1346 root 6u IPv6 12112 0t0 TCP localhost:ipp (LISTEN)
5. List Open Files of TCP Port ranges 1-1024
# lsof -i TCP:1-1024
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 1203 rpc 11u IPv6 11336 0t0 TCP *:sunrpc (LISTEN)
cupsd 1346 root 7u IPv4 12113 0t0 TCP localhost:ipp (LISTEN)
sshd 1471 root 4u IPv6 12685 0t0 TCP *:ssh (LISTEN)
master 1551 root 13u IPv6 12898 0t0 TCP localhost:smtp (LISTEN)
sshd 1834 root 3r IPv4 15101 0t0 TCP 192.168.0.2:ssh->192.168.0.1:conclave-cpp (ESTABLISHED)
sshd 1838 tecmint 3u IPv4 15101 0t0 TCP 192.168.0.2:ssh->192.168.0.1:conclave-cpp (ESTABLISHED)
sshd 1871 root 3r IPv4 15842 0t0 TCP 192.168.0.2:ssh->192.168.0.1:groove (ESTABLISHED)
httpd 1918 root 5u IPv6 15991 0t0 TCP *:http (LISTEN)
httpd 1918 root 7u IPv6 15995 0t0 TCP *:https (LISTEN)
6. Exclude User with ‘^’ Character
# lsof -i -u^root
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 1203 rpc 6u IPv4 11326 0t0 UDP *:sunrpc
rpcbind 1203 rpc 7u IPv4 11330 0t0 UDP *:954
rpcbind 1203 rpc 8u IPv4 11331 0t0 TCP *:sunrpc (LISTEN)
rpcbind 1203 rpc 9u IPv6 11333 0t0 UDP *:sunrpc
rpcbind 1203 rpc 10u IPv6 11335 0t0 UDP *:954
rpcbind 1203 rpc 11u IPv6 11336 0t0 TCP *:sunrpc (LISTEN)
avahi-dae 1241 avahi 13u IPv4 11579 0t0 UDP *:mdns
avahi-dae 1241 avahi 14u IPv4 11580 0t0 UDP *:58600
rpc.statd 1277 rpcuser 5r IPv4 11836 0t0 UDP *:soap-beep
rpc.statd 1277 rpcuser 8u IPv4 11850 0t0 UDP *:55146
rpc.statd 1277 rpcuser 9u IPv4 11854 0t0 TCP *:32981 (LISTEN)
rpc.statd 1277 rpcuser 10u IPv6 11858 0t0 UDP *:55800
rpc.statd 1277 rpcuser 11u IPv6 11862 0t0 TCP *:56428 (LISTEN)
7. Find Out who’s Looking What Files and Commands?
# lsof -i -u tecmint
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1839 tecmint cwd DIR 253,0 12288 15 /etc
ping 2525 tecmint cwd DIR 253,0 12288 15 /etc
8. List all Network Connections
# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 1203 rpc 6u IPv4 11326 0t0 UDP *:sunrpc
rpcbind 1203 rpc 7u IPv4 11330 0t0 UDP *:954
rpcbind 1203 rpc 11u IPv6 11336 0t0 TCP *:sunrpc (LISTEN)
avahi-dae 1241 avahi 13u IPv4 11579 0t0 UDP *:mdns
avahi-dae 1241 avahi 14u IPv4 11580 0t0 UDP *:58600
rpc.statd 1277 rpcuser 11u IPv6 11862 0t0 TCP *:56428 (LISTEN)
cupsd 1346 root 6u IPv6 12112 0t0 TCP localhost:ipp (LISTEN)
cupsd 1346 root 7u IPv4 12113 0t0 TCP localhost:ipp (LISTEN)
sshd 1471 root 3u IPv4 12683 0t0 TCP *:ssh (LISTEN)
master 1551 root 12u IPv4 12896 0t0 TCP localhost:smtp (LISTEN)
master 1551 root 13u IPv6 12898 0t0 TCP localhost:smtp (LISTEN)
sshd 1834 root 3r IPv4 15101 0t0 TCP 192.168.0.2:ssh->192.168.0.1:conclave-cpp (ESTABLISHED)
httpd 1918 root 5u IPv6 15991 0t0 TCP *:http (LISTEN)
httpd 1918 root 7u IPv6 15995 0t0 TCP *:https (LISTEN)
clock-app 2362 narad 21u IPv4 22591 0t0 TCP 192.168.0.2:45284->www.gov.com:http (CLOSE_WAIT)
chrome 2377 narad 61u IPv4 25862 0t0 TCP 192.168.0.2:33358->maa03s04-in-f3.1e100.net:http (ESTABLISHED)
chrome 2377 narad 80u IPv4 25866 0t0 TCP 192.168.0.2:36405->bom03s01-in-f15.1e100.net:http (ESTABLISHED)
9. Search by PID
# lsof -p 1
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 253,0 4096 2 /
init 1 root rtd DIR 253,0 4096 2 /
init 1 root txt REG 253,0 145180 147164 /sbin/init
init 1 root mem REG 253,0 1889704 190149 /lib/libc-2.12.so
init 1 root mem REG 253,0 142472 189970 /lib/ld-2.12.so
10. Kill all Activity of Particular User
# kill -9 `lsof -t -u tecmint`