自動化運維-【版本流程管理】


什么是版本控制系統(VCS)

版本控制系統 (VCS) 是一個軟件,幫助軟件開發人員團隊工作並維持他們完整的工作歷史。 下面是版本控制系統(VCS) 的目標

  • 允許開發者們同時工作
  • 不會重寫每個人的改變
  • 維持每個版本的全部的歷史

VCS 被分成兩種

  • 集中版本控制系統 (CVCS) 
  • 分散或不集中的版本控制系統 (DVCS)

學習svn用到的術語

倉庫: 倉庫是任何一個版本系統的核心,它是開發者們保存工作的總部,倉庫不止處理文件還有歷史記錄,它需要訪問網絡,扮演服務器的角色,版本控制工具扮演客戶端的角色,客戶端可以連接倉庫,那么他們就可以從倉庫中存儲或者提取。通過保存這些更改,一個客戶端的更改可以被其他人檢索到,一個客戶端可以讓其他人的更改作為一個工作副本。

主干:trunk 是主要開發所在的目錄,經常被項目開發者們查看。

標簽:tags 目錄用於儲存項目中被命名的快照,標簽操作允許給予對倉庫中特定版本一個描述和一個難忘的名字。比如,LAST_STABLE_CODE_BEFORE_EMAIL_SUPPORT 比 Repository UUID: 7ceef8cb-3799-40dd-a067-c216ec2e5247 和Revision: 13 更令人難忘。

分支:分支操作用於創建開發的另一條線,當你想把開發進程復制進兩個不同的方向是很有用的。比如,當你發布 5.0 版本時,你可能想從 5.0 的 bug 修復中分離出來創建一個開發 6.0 功能的分支。

工作副本:工作副本是倉庫的一個快照。這個倉庫被所有的成員共享,但人們不直接修改它,相反每個開發者檢查這個工作副本,工作副本是一個私人的工作空間,這里開發者可以獨立於其他成員做自己的工作。

提交更改:提交是一個保存更改的過程,從私人工作空間到中央服務器。提交后,更改對全部成員可用,通過更新工作副本其他開發者提取這些更改。提交是一個原子操作,要么全部提交成功要么回滾,用戶絕不會看到一半完成提交。

svn

1.SVN

1.1簡介

SVN是Subversion的簡稱,是一個開放源代碼的跨平台的開源的版本控制系統,相較於RCS、CVS,它采用了分支管理系統,它的設計目標就是取代CVS。互聯網上很多版本控制服務已從CVS遷移到Subversion。說得簡單一點SVN就是用於多個人共同開發同一個項目,共用資源的目的
svn版本管理工具管理隨着時間改變的各種數據,這些數據放置在一個中央資料檔案庫中,svn會備份並記錄每個文件每一次的修改變動,這樣我們就可以把任意一個時間點的檔案恢復到一個舊的版本。

svn相關站點:
  svn客戶端:http://www.tortoisesvn.net
  官方手冊:http://svnbook.red-bean.com

svn與git的區別
  svn:是集中式的版本控制系統,存在一個中央版本庫,所有開發人員本地開發所使用的代碼都是來源版本庫,提交代碼也必須要提交到這個版本庫
     svn的備份要備份所有代碼數據,以及所有更改的版本記錄,也可以直接備份中央代碼庫
  git:是分布式的版本控制系統,在git中,已經沒有了中央版本庫的說法了,但是有遠程和本地的完整的git倉庫,用來開發小組的代碼共享
     其中本地和遠程倉庫中的代碼是等價的,沒有主從之分

1.2 運行方式,訪問方式和數據存儲

svn服務器有3種運行方式:
  獨立服務器 :svn://svn.test.com/object
  apache運行:http://svn.test.com/object
    1.單獨安裝svn和apache服務器
    2.第二種是csvn(apache+svn),是一個單獨整合個軟件,帶web界面的svn軟件
  svn服務器本地直接訪問:file:///application/svndata/sadoc

svn客戶端的訪問方式:

  數據存儲

    svn存儲版本數據也有2種方式:BDB(一種事務安全型表類型)和FSFS(一種不需要數據庫的存儲系統)。因為BDB方式在服務器中斷時,有可能鎖住數據,所以還是FSFS方式更安全一點。

    在svn1.2以前的版本使用BDB,1.2以后使用FSFS

    SVN是基於關系數據庫的(BerkleyDB)或一系列二進制文件的(FS_FS)。一方面這解決了許多問題 (例如,並行讀寫共享文件)以及添加了許多新功能(例如運行時的事務特性。)。然而另一方面,數據存儲由此變得不透明。

 1.3 svn版本系統邏輯架構原理

 1.4 集中式管理工作的流程圖

集中式代碼管理的核心是服務器,所有開發者在開始新一天的工作之前必須從服務器獲取代碼,然后開發,最后解決沖突,提交。所有的版本信息都放在服務器上。如果脫離了服務器,開發者基本上可以說是無法工作的。下面舉例說明:
開始新一天的工作:
1、從服務器下載項目組最新代碼。
2、進入自己的分支,進行工作,每隔一個小時向服務器自己的分支提交一次代碼,很多人都有這個習慣。因為有時候自己對代碼改來改去,最后又想還原到前一個小時的版本,或者看看前一個小時自己修改了哪些代碼,就需要這樣做了。
3、下班時間快到了,把自己的分支合並到服務器主分支上,一天的工作完成,並反映給服務器。
這就是經典的svn工作流程,從流程上看,有不少缺點,但也有優點。優缺點參考

集中式管理工作的流程圖

2.配置SVN服務

2.1查看系統環境

[root@node1 /]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
[root@node1 /]# uname -a
Linux node1 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[root@node1 /]# uname -r
3.10.0-693.el7.x86_64
[root@node1 /]# uname -m
x86_64
[root@node1 /]# 

2.2安裝svn(subversion)

檢查是否安裝了svn
[root@node1 /]# svn --version
-bash: svn: command not found

安裝svn
[root@node1 /]# yum install subversion -y

yum安裝rpm包本地不清除的方法
[root@node1 /]# cat /etc/yum.conf
keepcache=0 #0修改為1,rpm包下載后不清除

查看版本
[root@node1 /]# rpm -qa subversion
subversion-1.7.14-14.el7.x86_64

配置並啟動
  1.建立svn版本庫數據存儲的目錄(svndata)及用戶,密碼權限目錄(svnpassword)
    [root@node1 /]# mkdir -p application/svndata #數據存儲的根目錄
    [root@node1 /]# mkdir -p application/svnpasswd #用戶密碼權限目錄
  2.使用命令svnserve啟動服務
    [root@node1 /]# svnserve -d -r /application/svndata || pkill svnserve 停止svn服務
      
svnserve -d -r 目錄 --listen-port 端口號
      -d:表示啟動以守護進程的方式啟動
      -r:配置方式決定了版本庫訪問方式
      
--listen-port:指定SVN監聽端口,不加此參數,SVN默認監聽3690
      --listen-host:指定SVN監聽的host,不加此參數,默認全部監聽
      --pid-file:存放進程號文件
  更多svnserve參數:man svnserve
  3.查看是否啟動,端口為3690
    
[root@node1 /]# ps -ef |grep svn
    root 16304 1 0 18:59 ? 00:00:00 svnserve -d -r /application/svndata/
  4.創建版本庫(可以創建多個,放置不同的代碼)
    [root@node1 /]# svnadmin create /application/svndata/sadoc
    svnadmin --help 可以查看svnadmin用法
  5.調整svn配置文件及權限文件
    [root@node1 conf]# cd /application/svndata/sadoc/conf #版本庫的配置文件目錄
    [root@node1 conf]# ll
    total 12
    -rw-r--r-- 1 root root 1080 Nov 8 20:03 authz #用戶權限驗證文件
    -rw-r--r-- 1 root root 309 Nov 8 20:03 passwd #用戶密碼文件
    -rw-r--r-- 1 root root 3090 Nov 8 20:03 svnserve.conf #sadoc版本庫主配置文件,並且包含上面兩個配置文件
    修改之前要做備份 tar -zcvf ./back_tar.gz . 
    編輯svnserve.conf修改以下四項:注意修改后要重新啟動
      anon-access = none #不允許匿名訪問,read是允許匿名訪問
      auth-access = write #是否支持用戶可寫
      password-db = /application/svnpasswd/passwd #指定用戶密碼數據庫,方便統一管理
      authz-db = /application/svnpasswd/authz #用戶權限數據庫
    將用戶模板copy到配置文件指定的路徑里面
      [root@node1 conf]# cp authz passwd /application/svnpasswd/
    進入/application/svnpasswd
修改文件屬性,增加安全性,只有root用戶可讀
      [root@node1 svnpasswd]# chmod 700 *
    編輯passwd添加賬號密碼,因為賬號密碼是明文的,所以上一步修改文件權限,修改后不用重新啟動
      [root@node1 svnpasswd]# vim passwd 
      p0st = 123456
      shuang = 123456

    配置用戶權限文件
    注意:
      權限配置文件中出現的用戶名必須是已在用戶配置文件中定義過的
      對權限配置文件的修改立即生效,不必重新啟動svn

      [groups] #gtoups下面的變量就是組名,后面可抱哈你多個用戶名,用逗號隔開
      # harry_and_sally = harry,sally
      # harry_sally_and_joe = harry,sally,&joe
      ett_wang = p0st,shuang

      # [repository:/baz/fuz] 版本庫:/版本庫項目/項目目錄 #所以這里既可以給整個組賦權限,也可以給單個用戶賦權限
      # @harry_and_sally = rw 用戶組名:權限
      # * = r 用戶名:權限

      [sadoc:/]
      @ett_wang = rw
      p0st = rw
      shuang = r

      其中方括號內部有很多種寫法
      [/],表示根目錄及以下,這里的根目錄指的是svnserve啟動時指定的,[/]就表示對全部版本庫的設置權限
      [svndata:/]表示對版本庫svndata設置權限
      [svndata:/sadoc]表示對版本庫svndata中的sadoc設置權限
      [svndata:/sadoc/test]表示對版本庫svndata中的sadoc項目的test項目設置權限

      權限主體可以是用戶組,用戶,或者*,用戶組在前面加@。*表示全部用戶
      權限可以是w,r,wr和空,空代表沒有任何權限
      對於組,要以@開頭,用戶不需要@開頭

      使用diff authz authz.bak 可以進行對比,查看文件不同

  6.重啟svn服務:
    [root@node1 svnpasswd]# pkill svnserve
    [root@node1 svnpasswd]# svnserve -d -r /application/svndata/
    注意: 更改svnserve.conf需要重啟svn,更改authz、passwd文件時不需要重啟;
    檢查3690端口是否處於監聽狀態,至此svn服務器搭建完成;下面是svn客戶端的安裝與使用;
    只有更改了
svnserve.conf才需要重啟服務,剩下的更改都是立即生效的不需要重啟

2.3svn啟動方式

svnserve -d -r 目錄 --listen-port 端口號
-r: 配置方式決定了版本庫訪問方式。
--listen-port: 指定SVN監聽端口,不加此參數,SVN默認監聽3690

方式一:-r直接指定到版本庫(稱之為單庫svnserve方式)
svnserve -d -r /opt/svn/runoob
在這種情況下,一個svnserve只能為一個版本庫工作。
authz配置文件中對版本庫權限的配置應這樣寫:[groups]
admin=user1
  dev=user2
  [/]
  @admin=rw
  user2=r
使用類似這樣的URL:svn://192.168.0.1/ 即可訪問runoob版本庫

方式二:指定到版本庫的上級目錄(稱之為多庫svnserve方式)
svnserve -d -r /opt/svn
這種情況,一個svnserve可以為多個版本庫工作
authz配置文件中對版本庫權限的配置應這樣寫:
[groups]
admin=user1
dev=user2
[runoob:/]
@admin=rw
user2=r

[runoob01:/]
@admin=rw
user2=r
如果此時你還用[/],則表示所有庫的根目錄,同理,[/src]表示所有庫的根目錄下的src目錄。
使用類似這樣的URL:svn://192.168.0.1/runoob 即可訪問runoob版本庫。

2.3 連接svn服務器

windows:
  下載tortoisesvn(windos上面svn工具),安裝,如果英文看不懂,可以安裝中文包漢化
  輸入用戶名和密碼,復選框能讓tortoisesvn的缺省目錄:%APPDATA%\Subversion\auth的三個子目錄內保存認證信息
  svn.simple:里面包含了進本的認證方式所需的認證信息,注意,密碼是通過wincrpty的api加密的不是明文
  svn.ssl.server:里面包含了ssl服務器認證
  svn.username:里面包含了用戶名的認證信息(不需要提供密碼)
  新建一個文件夾用來接收svn現在的內容,在文件夾上右鍵就有很多功能了
linux:
  在linux使用svn時,要安裝svn

   查看svn中的數據
   svn list svn://192.168.10.231/sadoc --username=p0st --password=123456
   svn ls svn://192.168.10.231/sadoc --username=p0st --password=123456
   svn ls svn://192.168.10.231/sadoc --username=p0st --password=123456 --verbose #可以顯示詳細的信息
   svn cat svn://192.168.10.231/sadoc/hosts --username=p0st --password=123456 #可以查看文件內容

   checkout:檢出文件到本地
   svn checkout svn://192.168.10.231/sadoc /tmp --username=p0st --password=123456
   命令 下載 地址 下載到哪里(本地服務器) 賬號密碼

   add:往版本庫中添加新的文件,但是還沒提交進去
   svn add hosts

   將添加或者改動的文件提交到版本庫
   svn commit -m “LogMessage“ [-N] [--no-unlock] PATH(如果選擇了保持鎖,就使用–no-unlock開關)
   svn commit -m hosts
   備注:提交多個文件中間用空格隔開如 svn ci -m "哈哈~~" test.php test2.php style.css

   如果出現編碼錯誤的話,需要制定utf-8的編碼方式
   export LC_CTYPE="en_US.UTF-8"
   export LC_ALL=
   locale

   導入svn原始目錄樹 trunk(主干) branch(分支)tag(確定之后的版本號)
   svn import
   mkdir -p /svn/trunk /svn/branch /svn/tag
   svn import /svn file:////application/svndata/ -m "import"
   svn import /svn svn://192.168.10.231/sadoc/ --username=p0st --password=123456 -m “import是注釋”

   將主干保存為分支
   svn copy svn://192.168.10.231/sadoc/trunk svn://192.168.10.231/sadoc/branch/branch_cms_110623 -m "create a branch by p0st"

   查看當前svn版本庫的信息svn info
   svn://192.168.10.231/sadoc --username=p0st --password=123456 

  注意:要是用svn help 或者svn help add 等命令來查看怎么使用

  其他命令

3.svn鈎子腳本

3.1鈎子簡介

鈎子腳本的具體寫法就是操作系統中shell腳本程序的寫法,所謂鈎子就是與一些版本庫事件觸發的程序,例如新修訂版本的創建,或是未版本化屬性的修改。每個鈎子都會被告知足夠多的信息,包括那是什么事件,所操作的對象,和觸發事件的用戶名。通過鈎子的輸出或返回狀態,
鈎子程序能讓工作繼續、停止或是以某種方式掛起。類似inotify和sersync

對每種Subversion版本庫支持的鈎子的都有一個模板,通過查看這些腳本的內容,你能看到是什么事件觸發了腳本及如何給傳腳本傳遞數據。同時,這些模版也是如何使用這些腳本,結合Subversion支持的工具來完成有用任務的例子。要實際安裝一個可用的鈎子,
你需要在 repos/hooks目錄下安裝一些與鈎子同名(如 start-commit或者post-commit)的可執行程序或腳本。

提示:
  由於安全原因,Subversion版本庫在一個空環境中執行鈎子腳本—就是沒有任何環境變量,甚至沒有$PATH或%PATH%。由於這個原因,許多管理員會感到很困惑,它們的鈎子腳本手工運行時正常,可在Subversion中卻不能運行。
  要注意,必須在你的鈎子中設置好環境變量或為你的程序指定好絕對路徑。
  必須要去掉項目里面鈎子的后綴名

3.2鈎子腳本

注意:svn鈎子的目錄在/application/svndata/sadoc/hooks下,該目錄已經提供了幾個鈎子的模板

常用的鈎子腳本

post-commint:在提交完成成功之后執行該鈎子,提交已經完成不會更改,因此,本腳本的返回值被忽略,不可更改,提交完成時觸發事物   

  1.svn更新自動周知,msn,郵件或者短信

  2.svn更新觸發checkount程序,然后rsync實時推送到服務器等 

#此腳本是在commit之后,svn版本庫進行更新,並且將版本庫里面的內容通過rsync推送到/oldboy備份

#!/bin/bash
#REPOS='$1'
#REV='$2'
#export LANG=en_US.UTF-8
#export LC_ALL=
#LOGPATH="/app/log.log"
#[ ! d $LOGPATH ] && mkdir ${LOGPATH} -p
#update content from svn
SVN=/usr/bin/svn
$SVN update --username p0st --password 123456 /tmp --no-auth-cache

#$SVN update --username p0st --password 123456 /tmp --no-auth-cache  >>$LOGPATH 2>&1
if [[ $? -eq 0 ]]; then
/usr/bin/rsync -az --delete /tmp /oldboy/
fi

注意:
  1.鈎子使用時,要去掉后綴名,可以cp post-commit.tmpl post-commit
  2.如果是在windos寫的腳本,在linux上執行腳本要進行轉換格式 dos2unix  post-commint 或者使用編輯器打開時:set ff=unix,然后:wq
  3.鈎子要有執行權限,通常是700,如果有亂碼,可以將腳本中的文件系統的編碼注釋去掉,特別要注意環境變量的使用,可以查看狗子的模板中是怎么使用的

  重點:常見的鈎子使用方法 鈎子詳解

pre-commit:提交完成前執行該腳本

  1.用作限制文件上傳大小和擴展名,控制提交要輸入的信息等

start-commit:在客戶端還沒有向服務器提交數據之前,即還沒有建立subversion transaction縮寫為(txn)之前,執行該鈎子(腳本)

 

不常用的鈎子腳本

svn通過ldap統一認證

4.大中小企業代碼發布解決方案

4.1svn目錄組織結構說明

[root@node1 svndata]# pwd
/application/svndata
[root@node1 svndata]# ls -al
drwxr-xr-x 6 root root 58 Nov  9 20:06 .
drwxr-xr-x 4 root root 38 Nov  9 17:22 ..
drwxr-xr-x 2 root root  6 Nov  9 20:06 branch #分支,為測試使用,幾天上線的項目必須開分支,測試需要本分支通過,主線合並到分支通過,才能合並到主線進行測試
drwxr-xr-x 6 root root 86 Nov  9 17:23 sadoc #版本庫
drwxr-xr-x 2 root root  6 Nov  9 20:06 tags  #版本記錄使用
drwxr-xr-x 2 root root  6 Nov  9 20:06 trunk #主線,與正式線相對應,當天不上線文件不允許提交

4.2大中小企業上線解決方案

  小型企業上線架構方案

小型企業上線構架方案建議

1.開發人員需在個人電腦上搭建lamp環境測試開發號的網站代碼,並且在辦公室或idc機房的測試環境測試通過,最好有專職的測試人員
2.程序代碼上線要規定時間。例如,三天一上線,如網站需經常更新課每天下午17點上線,這個看網站業務性質而定,原則上就是能最小的影響用戶體驗最好
3.代碼上線之前需要備份。網站程序出了問題方便回退。另外,從上線技巧上講,上傳代碼是盡可能的先上傳到網站的臨時目錄,上傳完整之后一步mv過去,或者通過ln做軟連接,比較嚴格的更新代碼,將服務器從集群下線(平滑下線),然后更新
4.盡量由運維人員管理上線,對於代碼的功能性開發人員更在意,而對於代碼的性能和服務的穩定運維更在意。因此如果網站問題歸運維管,就要讓運維上線,這樣更科學,否則,開發隨意更新,出了問題運維負責,這樣就錯了

  中型企業上線架構方案

中型企業上線構架方案建議

一般是規范運維人員操作步驟,指定統一的上線操作腳本,備份文件名稱,備份文件路徑。使操作人性化,統一化,自動化

  大型企業上線架構方案

在大型集群環境一般有數台集群機器,因此要分批更新。
下面是java環境代碼上線:
1.本地開發人員從svn中抽取代碼,當天上線的提交到trunk,否則,長期項目單開分支開發,然后合並主線(trunk)
2.辦公內網開發測試時,由開發人員或者配置管理員通過部署jenkins實現統一部署(即在部署平台式控制開發機器從SVN版本庫中checkout代碼,編譯,打包,發布到開發機,idc_dep.war)
3.開發人員和測試人員一起測試程序,沒有出現問題后,打上新的tag標記
4.配置管理員,根據上步的tag標記,checkout出上線代碼,平配置好idc測試環境的所有配置,執行編譯,打包(mvn,ant,php不需要打包),然后發布到idc內的統一分發服務器,這里要注意,不同的配置文件是隨着代碼同時發布的
5.配置管理員或sa上線人員,把分發的程序代碼內容推送到相關的測試服務器(包名如:idc_test.war),然后通知開發及測試人員進行測試,如果有問題向上回滾到內網開發測試從新測試修改
6.如果測試沒有問題,繼續打好tag標記,此時配置管理員根據上步的tag標記,checkout出測試好的代碼,並配置好idc正式環境的所有配置,執行編譯,打包(mvn,ant),然后發布到idc內的統一分發服務器主機上,准備批量發布
7.配置管理員和sa上線人員,把分發的內容推送到相關的正式服務器(包名:idc_product.war),然后通知開發以及測試人員進行測試,如果有問題,直接發布回滾指令

注意:idc正式上線的過程對於java程序來說,可以將集群上的服務器分為ab兩組分批上線的思路,即在流量較少的時候平滑下線一半的服務器,在測試集群掛上服務器。然后進行代碼測試,無問題后,在正式集群掛上服務器,同時在平滑下線另一半的服務器,然后發布更新代碼測試(或者直接發布就上線)如果前端有dns智能解析,上線還可以分地區的若干服務器,逐漸普及到全國的服務器,這個稱為灰度發布

 4.3大中小企業上線注意事項

 
         

代碼上線解決方案注意事項:
1.上線的流程里,辦公測試環境->idc測試環境->正式生產環境,所有的環境中所有的軟件版本統一,盡量單一。例如:操作系統,web服務器,jdk版本,php,tomcat,resin等版本
2.開發團隊小組辦公內部測試環境測試(該測試環境屬於開發小組維護,或定時自動更新代碼),代碼有問題返回給開發人員重新開發
3.有專門的測試工程師,程序有問題直接返回給開發人員(此時返回的一般為程序的bug,稱為bug庫),無問題則進行idc測試
4.idc測試有測試人員和運維人員參與,叫idctest,進行程序的壓力測試,有問題直接返回給開發人員,無問題直接環境上線
5.書台服務器代碼分發上線(java程序)
1)假設有六台服務器,將服務器分為ab兩組,a三台,b三台,先對a組從負載均衡服務器上平滑下線,b組正常提供服務器,避免服務器因線上影響業務
2)下線過程中通過腳本將a組服務器從集群中踢出,避免負載均衡器將請求發給a組服務器
3)將代碼發到a租服務器的站點目錄下,對a組服務器在測試負載均衡器上線並重啟,並有專門的測試人員進行訪問測試,測試成功后,在正式負載均衡器上掛上a租服務器的同事,下線b組服務器,b組服務器做和a組等同操作,期間也要及時觀察上線服務器的裝魯昂,有問題及時回滾
6.如果php上線:發布代碼時,可以直接發布到正式服務器的臨時目錄,然后mv或者直接link的方式發布到正式線目錄,不需要重啟服務,當然測試也是少不了的,測試出了測試是否正常以外,還需要測試各個相關業務接口
7.大多數門戶網站的前端都已經靜態化或者cache了,因此動態的部分訪問平時就不會特別多,流量低谷時就號了,再加上是平滑上下線,用戶感知更小

php程序上線的具體方案 對於php上線:發布代碼時,可以直接發布到正式服務器的臨時目錄,然后mv或者直接link的方式發布到正式線目錄,不需要重啟服務

 4.4svn服務器上到底要包含什么?

 1)svn上存放代碼(不含資源,大公司的網站資源和程序都是分離的),在上線的時候盡可能要全量上線,因為我們要保證svn的代碼是最新的
 2)存放服務的配置文件(lamp環境等配置)
     開發小組測試使用的配置文件
     辦公環境測試使用的配置文件
     idc環境測試使用的配置文件
     線上應用使用的配置文件

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM