兩臺(tái)服務(wù)器,我這邊都是windows的:
創(chuàng)新互聯(lián)建站是一家以網(wǎng)站建設(shè)公司、網(wǎng)頁設(shè)計(jì)、品牌設(shè)計(jì)、軟件運(yùn)維、成都網(wǎng)站推廣、小程序App開發(fā)等移動(dòng)開發(fā)為一體互聯(lián)網(wǎng)公司。已累計(jì)為VR全景等眾行業(yè)中小客戶提供優(yōu)質(zhì)的互聯(lián)網(wǎng)建站和軟件開發(fā)服務(wù)。
Jenkins,除了默認(rèn)插件外,額外需要手動(dòng)安裝插件:
OpenSSH
Git
其他的java
、maven
、npm
等工具
服務(wù)器A
中安裝jenkins
,由于我這邊還是舊的windows server 2012
,對docker
支持不好,所以直接安裝的msi文件,具體安裝步驟參考官方文檔,安裝完成后再安裝上述的幾個(gè)插件。服務(wù)器A
安裝Git
,方便從github等代碼工具中遠(yuǎn)程拉取代碼,具體安裝步驟可以自行網(wǎng)上搜索,由于我們后期會(huì)用到ssh
和tar
等工具,所以需要將安裝目錄\Git\usr\bin
此路徑加入到windows環(huán)境變量中,這樣就可以用里面的各種工具了,如果是npm項(xiàng)目,需要在服務(wù)器B
中也要安裝,主要是為了用tar
打包命令,如果用其他打包方式也可以不安裝。服務(wù)器A
安裝java
、maven
、npm
,最好與開發(fā)服務(wù)上版本保持一致,并將其加入到windows環(huán)境變量中,這樣的話jenkins
就可以直接使用。服務(wù)器B
安裝openssh
,安裝流程查看官方文檔:Install Win32 OpenSSH,同樣需要將此路徑加入環(huán)境變量,且需要按照文檔開啟端口、開機(jī)自啟動(dòng)等整體的流程就是服務(wù)器B
相當(dāng)于服務(wù)端,服務(wù)器A
相當(dāng)于客戶端,我們需要用客戶端通過ssh鏈接到服務(wù)端,然后傳輸部署的文件過去,所以需要在客戶端中生成私鑰和公鑰,公鑰會(huì)給到服務(wù)端中,私鑰則還是留在客戶端,這樣ssh鏈接時(shí)通過私鑰和公鑰驗(yàn)證通過鏈接到一起就可以傳輸文件了。
在服務(wù)器A
生成密鑰,需要注意的是jenkins
的Publish Over SSH
不支持最新的密鑰格式,只支持舊的pem格式的,所以需要加一些參數(shù)才行,在剛安裝的git命令工具中輸入ssh-keygen -m PEM -t rsa -b 4096
,按照提示一步步執(zhí)行,生成的會(huì)放在~/.ssh
文件下:
xxx_rsa #私鑰
xxx_rsa.pub #公鑰
在服務(wù)器B
可以先啟動(dòng)一下openssh
服務(wù)然后關(guān)閉,此時(shí)會(huì)自動(dòng)生成C:\Program Data\ssh
目錄,然后我們配置此目錄下的sshd_config
文件,改動(dòng)如下:
PubkeyAcceptedKeyTypes=+ssh-rsa #由于上方說了用的舊的格式密鑰,新版本默認(rèn)已不支持了,所以這里需要額外配置增加支持
PubkeyAuthentication yes #原先是注釋來著,打開并設(shè)置為yes,表示開啟密鑰驗(yàn)證
PasswordAuthentication no #原先注釋來著,打開并設(shè)置為no, 關(guān)閉密碼驗(yàn)證,否則不安全
將服務(wù)器A
生產(chǎn)的公鑰放到服務(wù)B
中,這里需要注意,服務(wù)器B
的用戶是管理員用戶,則需要放到C:\ProgramData\ssh\administrators_authorized_keys
文件中,如果是普通用戶,則需要放到C:\Users\用戶名\.ssh\authorized_keys
文件中,通過這里我們也可以發(fā)現(xiàn)密鑰實(shí)際上是和用戶名沒有關(guān)系的,放到哪個(gè)用戶名下,是根據(jù)位置來的,如果這個(gè)用戶有權(quán)限訪問到這個(gè)密鑰實(shí)際上就是可以用這個(gè)用戶名來登陸的。
測試聯(lián)通性,可以在服務(wù)器A
的~/.ssh/config
中配置:
Host b_name #服務(wù)器B隨便起個(gè)名字
HostName 192.168.0.31 #服務(wù)器B的IP地址
IdentityFile ~/.ssh/xxx_rsa #自身生成的私鑰
User administrator #服務(wù)器B的登陸用戶名
Port 22 #沒改端口的話默認(rèn)22
ServerAliveInterval 60
然后可以ssh b_name
來測試是否可以聯(lián)通
在jenkins
的Publish Over SSH
插件配置中并測試聯(lián)通性,位置Manage Jenkins
->Configure System
->SSH Servers
中:
點(diǎn)擊測試,看是否聯(lián)通成功,如果出現(xiàn)類似Fail Auth
等錯(cuò)誤,可以參考此解決方法來解決:Jenkins Publish over ssh authentification failed with private key
服務(wù)器A
中同上創(chuàng)建私鑰和公鑰,但是github只支持最新版本的,可以不用加那些參數(shù)了,具體參考官方文檔:新增 SSH 密鑰到 GitHub 帳戶 - GitHub DocsSetting
->SSH AND GPG keys
->SSH keys
中新增,將生成的公鑰粘貼到github中的字段中就可以了gitee
等原理基本一樣如果不熟悉jenkins
的pipeline
相關(guān)的話,請先按照官方文檔demo操作一遍:Build a Java app with Maven
官方文檔demo中都是用的docker,我這邊沒有,所以不太一樣,而且官方文檔沒有回滾等操作,所以這邊給出參考的Jenkinsfile
:
pipeline {
agent any //沒有用docker
parameters {//這個(gè)是參數(shù)化構(gòu)建
choice choices: ['deploy', 'rollback'], description: '', name: 'action'
string description: 'rollback ID (only number)', name: 'version'
}
stages {
stage('Build') {
when {//如果是部署
expression { params.action == 'deploy' }
}
steps {//maven打包
bat 'mvn -B -DskipTests clean package'//linux下是用sh,windows下則bat
}
}
stage('Archive') {
when {//如果是部署
expression { params.action == 'deploy' }
}
steps {//將打包出來的jar包歸檔,方便回滾時(shí)用到
archiveArtifacts artifacts: '自身相關(guān)路徑/target/*.jar', followSymlinks: false, onlyIfSuccessful: true
}
}
stage('Rollback') {
when {//如果是回滾
expression { params.action == 'rollback' }
}
steps {//回滾就不需要打包了,直接將原先版本的歸檔復(fù)制到打包出來的路徑
bat 'xcopy /s /f /y "%JENKINS_HOME%\\jobs\\%JOB_NAME%\\builds\\%version%\\archive\\自身相關(guān)路徑\\target" 自身相關(guān)路徑\\target'
}
}
stage('Publish') {
steps {//publish over ssh插件相關(guān)參數(shù),verbose為true,則jenkins_deploy.bat腳本的執(zhí)行信息會(huì)返回
sshPublisher(publishers: [sshPublisherDesc(configName: '剛才設(shè)置的ssh的名稱', sshRetry: [retries: 3, retryDelay: 5000], transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'cmd /c E:\\服務(wù)器B相關(guān)部署路徑\jenkins_deploy.bat $BUILD_NUMBER', execTimeout: , flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '服務(wù)器B相關(guān)路徑', remoteDirectorySDF: false, removePrefix: '自身相關(guān)路徑/target', sourceFiles: '自身相關(guān)路徑/target/*.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
}
}
}
}
上方代碼一些注解:
上方的參數(shù)化構(gòu)建
、歸檔
、publish over ssh
語法都是可以由可視化界面生成的,隨便點(diǎn)開一個(gè)job后在左側(cè)有流水線語法
這個(gè)選項(xiàng),點(diǎn)開后頁面在左側(cè) Declarative Directive Generator
中選擇parameters:Parameters
可以生成參數(shù)化構(gòu)建片段;而左側(cè)片段生成器
中archiveArtifacts archive the artifacts
用來生成歸檔片段,sshPublishers: Send build artifacts over SSH
則用來生成發(fā)布的片段,這些具體的使用,可以參考官方文檔也可以自行搜索更詳細(xì)的用法文章。
參數(shù)化構(gòu)建如果在pipeline中寫了后,不需要在界面中再配置,只需要運(yùn)行一次后會(huì)自動(dòng)從pipeline中獲取,下次再構(gòu)建就發(fā)現(xiàn)有參數(shù)需要填寫了,要想回滾則選擇rollback
然后輸入回滾的構(gòu)建數(shù)字運(yùn)行則會(huì)回滾:
一些全局變量,可以參考官方文檔:Using a Jenkinsfile,需要注意的是在linux中可以$JENKINS_HOME
,但是在windows中就必須%JENKINS_HOME%
這樣了,需要注意的是publish over ssh
給jenkins_deploy.bat
傳遞參數(shù)的 $BUILD_NUMBER
則還是用$
才行,用%%
不起作用,且執(zhí)行windows腳本時(shí)需要用cmd /c
開頭。
服務(wù)器B
端的結(jié)構(gòu)及腳本:
項(xiàng)目結(jié)構(gòu):
abc:
├─backup
│ └─test_2022_06_27__3.jar #在服務(wù)端也備份一份,格式:名稱+日期+構(gòu)建號+jar
└─prod
│ └─test.jar #生產(chǎn)文件
└─jenkins_deploy.bat
jenkins_deploy.bat
腳本:
@echo off
::設(shè)置utf8編碼運(yùn)行
chcp
::移動(dòng)到當(dāng)前目錄
cd /d E:\abc
::設(shè)置時(shí)間變量,需要注意的是utf編碼和ansi編碼所取時(shí)間的位數(shù)不一樣
set "Ymd=%date:~3,4%_%date:~8,2%_%date:~11,2%_%time:~0,2%%time:~3,2%%time:~6,2%"
::將時(shí)間的空格用0補(bǔ)齊;將參數(shù)可能攜帶的引號去掉
set "param=%1"
::%Ymd: =0%是將空格轉(zhuǎn)為0,%param:"=%是將"去掉
set backup_name=%Ymd: =0%_%param:"=%
::將現(xiàn)有的移到backup中
copy prod\test.jar backup\test_%backup_name%.jar
echo 'prod中的備份到backup中'
::關(guān)閉服務(wù)
net stop test
::將最新的移動(dòng)到生產(chǎn)目錄中
move /y test.jar prod\test.jar
echo '最新的移動(dòng)到prod中'
::開啟服務(wù)
net start test
@echo on
上方腳本一些注釋:
utf8
和ansi
中取值是不一樣的,需要注意.1%
是bat語法中第一個(gè)參數(shù),就是上方的$BUILD_NUMBER
構(gòu)建號,但傳遞過來可能后面帶引號,例如2"
,所以要把"
也去掉%Ymd: =0%
意思是將其中的空格轉(zhuǎn)為0,%param:"=%
意思是將其中的"
去掉test.jar
改成用服務(wù)的方式運(yùn)行,最好也要有優(yōu)雅關(guān)閉,可以參考:spring boot不同版本的優(yōu)雅關(guān)閉(graceful shutdown)和在windows下winsw服務(wù)方式運(yùn)行的配置整體流程和maven一樣,同樣官方也有參考demo,Build a Node.js and React app with npm,這里只給出參考的文件:
Jenkinsfile
:
pipeline {
agent any
parameters {
choice choices: ['deploy', 'rollback'], description: '', name: 'action'
string description: 'rollback ID (only number)', name: 'version'
}
stages {
stage('Install') {
when {
expression { params.action == 'deploy' }
}
steps {//install
bat 'npm ci --registry https://registry.npm.taobao.org'
}
}
stage("Build"){
when {
expression { params.action == 'deploy' }
}
steps {//build
bat 'npm run build'
}
}
stage("Archive"){
when {
expression { params.action == 'deploy' }
}
steps {//先打包成壓縮文件,再歸檔,同時(shí)也方便傳輸
bat 'tar -zcvf dist.tar.gz -C dist .'
archiveArtifacts artifacts: '*.tar.gz', followSymlinks: false, onlyIfSuccessful: true
}
}
stage('rollback') {
when {
expression { params.action == 'rollback' }
}
steps {//將壓縮文件拷貝到正常打包后的位置
bat 'copy /y "%JENKINS_HOME%\\jobs\\%JOB_NAME%\\builds\\%version%\\archive\\dist.tar.gz" dist.tar.gz'
}
}
stage("Publish"){
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: '剛才設(shè)置的ssh的名稱', sshRetry: [retries: 3, retryDelay: 5000], transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'cmd /c E:\\服務(wù)器B相關(guān)部署路徑\\jenkins_deploy.bat $BUILD_NUMBER', execTimeout: , flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '服務(wù)器B相關(guān)部署路徑', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'dist.tar.gz')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
}
}
}
}
服務(wù)器B的jenkins_deploy.bat
腳本,結(jié)構(gòu)和maven項(xiàng)目差不多。
項(xiàng)目結(jié)構(gòu):
abc:
├─backup
│ └─test_2022_06_27__3.tar.gz #在服務(wù)端也備份一份,格式:名稱+日期+構(gòu)建號+tar.gz
└─prod
│ ├─static
│ └─index.html
└─jenkins_deploy.bat
jenkins_deploy.bat
腳本:
@echo off
::設(shè)置utf8編碼運(yùn)行
chcp
::移動(dòng)到當(dāng)前目錄
cd /d E:\abc
::設(shè)置時(shí)間變量,需要注意的是utf編碼和ansi編碼所取時(shí)間的位數(shù)不一樣
set "Ymd=%date:~3,4%_%date:~8,2%_%date:~11,2%_%time:~0,2%%time:~3,2%%time:~6,2%"
::獲取第一個(gè)參數(shù)
set "param=%1"
::將時(shí)間的空格用0補(bǔ)齊;將參數(shù)可能攜帶的引號去掉
set backup_name=%Ymd: =0%_%param:"=%
::將現(xiàn)有的打包后移到backup中
tar -zcvf test_%backup_name%.tar.gz -C prod .
move test_%backup_name%.tar.gz backup\test_%backup_name%.tar.gz
echo 'prod中內(nèi)容打包到backup中'
::清空prod文件夾,然后將傳遞過來的解壓到prod中
del /q prod\*
for /d %%x in (prod\*) do @rd /s /q "%%x"
tar -zxvf dist.tar.gz -C prod
echo '最新的解壓到prod中'
::刪除傳遞過來的
del dist.tar.gz
echo '刪除傳遞過來的文件'
@echo on
小程序
主要是利用官方的miniprogram-ci來完成,此類庫可以實(shí)現(xiàn)預(yù)覽和上傳(上傳后還是需要登陸小程序平臺(tái)來設(shè)置體驗(yàn)版或者是提交正式版本),這個(gè)類庫是nodejs
寫的,所以需要大體了解下nodejs
腳本的寫法,可以參考Node.js 入門教程
小程序用miniprogram-ci
上傳前需要先到小程序平臺(tái)“開發(fā)管理”->"開發(fā)設(shè)置"->"小程序代碼上傳"中生成小程序代碼上傳密鑰
,實(shí)際上就和ssh的密鑰類似,在編寫腳本時(shí)會(huì)用到此密鑰,此密鑰不要放到和代碼一起的版本控制中,否則太不安全了,有兩種方式,一種是直接放到j(luò)enkins所在服務(wù)器的某個(gè)路徑,然后在腳本時(shí)直接引;一種是放到j(luò)enkins的密鑰管理中,類似github的密鑰一樣,然后在pipeline
通過withCredentials
可以獲取到,這里采用的是后一種方法,在jinkins
中新建credentials
,選擇SSH Username with private key
,其中id
則為Jenkinsfile
中引用的名稱,用戶名可以隨便填寫,Private Key
則從小程序端下載的key文件中直接復(fù)制過來填入即可。
jenkins所在服務(wù)器安裝nodejs
(最好與開發(fā)的版本一致),同時(shí)在 jenkins插件管理中安裝nodejs
插件并在全局配置中設(shè)置nodejs版本(安裝插件后會(huì)多出此選項(xiàng));需要在項(xiàng)目中引入miniprogram-ci
庫:npm install miniprogram-ci --save
,項(xiàng)目結(jié)構(gòu)如下所示,腳本放到ci\upload.js
下
xxx:
├─ci
│ └─upload.js #腳本路徑
└─dist
│ └─...
└─public
│ └─...
└─src
│ └─...
└─JenkinsFile
upload.js
const ci = require('miniprogram-ci');//小程序類庫
const path = require('path');
const fs = require("fs");
const argv = require('minimist')(process.argv.slice(2));//此類庫主要用于解析參數(shù),實(shí)現(xiàn)--version 12,則argv.version就為12,如果系統(tǒng)沒有自帶,則npm安裝下
const manifest = require('../src/manifest.json');//用的uniapp,直接從這里取appid,需要確保manifest.json不要有注釋,或者自己新建個(gè)json文件也行
const appDirectory = fs.realpathSync(process.cwd());//當(dāng)前命令行路徑,主要用于獲取絕對路徑
let projectPath = path.resolve(appDirectory, './dist/build/mp-weixin');//組裝項(xiàng)目路徑
let qrCodeImg = path.resolve(appDirectory, './qrcode.jpg');//組裝二維碼路徑
let type = argv.type;//參數(shù)預(yù)覽還是上傳
let privateKeyPath = argv.key;//傳遞upload的私鑰路徑
let version = argv.version ? argv.version : argv.number;//版本號,如果有傳遞則用,沒傳遞則用構(gòu)建號
let desc = argv.desc ? argv.desc : '暫無描述';//描述
//配置
const project = new ci.Project({
appid: manifest["mp-weixin"].appid,
type: 'miniProgram',
projectPath: projectPath,
privateKeyPath: privateKeyPath,
ignores: ['node_modules/**/*'],
});
if (type === 'preview') {
//預(yù)覽
(async () => {
await ci.preview({
project,
desc: desc,
setting: {
es6: true,
es7: true
},
qrcodeFormat: 'image',
qrcodeOutputDest: qrCodeImg,
onProgressUpdate: console.log,
});
})();
} else if (type === 'upload') {
//上傳
(async () => {
await ci.upload({
project,
version: version,
desc: desc,
setting: {
es6: true,
es7: true
},
onProgressUpdate: console.log,
});
})();
}
JenkinsFile(cmd版本),小程序自帶回退上一版本的功能,所以這里就沒有做回退選項(xiàng),如果想做可參考上方的實(shí)現(xiàn),是同一個(gè)邏輯
pipeline {
agent any
parameters {
string description: 'version (example: 1.0.0)', name: 'version'
string description: 'description', name: 'desc'
}
stages {
stage('Install') {
steps {
bat 'npm ci --registry https://registry.npm.taobao.org'
}
}
stage("Build"){
steps {
bat 'npm run build:mp-weixin'//用的uniapp
}
}
stage("Preview"){
steps {//先掉用預(yù)覽來生成二維碼圖片,用于歸檔后在jenkins中查看,這一步也可以不用
withCredentials([sshUserPrivateKey(credentialsId: '小程序密鑰在jenkins保存后的id', keyFileVariable: 'identity')]) {
bat 'node ci\\upload.js --type=preview --desc="%desc%" --key="%identity%"'
}
}
}
stage("Archive"){
steps {//同時(shí)將二維碼也歸檔,方便在jenkins中查看,如果是jenkins外網(wǎng)可以訪問,還可以將歸檔后的預(yù)覽二維碼發(fā)送到釘釘?shù)韧ㄖぞ咧?,或者?nèi)網(wǎng)也可以用oss自帶的cli工具上傳到oss中供外網(wǎng)訪問,此二維碼有效時(shí)間是25分鐘
bat 'tar -zcvf dist.tar.gz -C dist\\build\\mp-weixin .'
archiveArtifacts artifacts: '*.tar.gz,qrcode.jpg', followSymlinks: false, onlyIfSuccessful: true
}
}
stage("Publish"){
steps {//上傳,這里將version和BUILD_NUMBER都傳遞過去,如果version沒有填寫,則用構(gòu)建號作為小程序版本號
withCredentials([sshUserPrivateKey(credentialsId: '小程序密鑰在jenkins保存后的id', keyFileVariable: 'identity')]) {
bat 'node ci\\upload.js --type=upload --version="%version%" --number="%BUILD_NUMBER%" --desc="%desc%" --key="%identity%"'
}
}
}
}
}
jenkinsFile(powershell版本)
pipeline {
agent any
parameters {
string description: 'version (example: 1.0.0)', name: 'version'
string description: 'description', name: 'desc'
}
stages {
stage('Install') {
steps {
powershell 'npm ci --registry https://registry.npm.taobao.org'
}
}
stage("Build"){
steps {
powershell 'npm run build:mp-weixin'
}
}
stage("Preview"){
steps {
withCredentials([sshUserPrivateKey(credentialsId: '小程序密鑰在jenkins保存后的id', keyFileVariable: 'identity')]) {
//這個(gè)參數(shù)中如果有空格會(huì)解析參數(shù)不完整,所以必須加引號
powershell "node ci\\upload.js --type=preview --desc='$desc' --key='$identity'"
}
}
}
stage("Archive"){
steps {
powershell 'tar -zcvf dist.tar.gz -C dist\\build\\mp-weixin .'
archiveArtifacts artifacts: '*.tar.gz,qrcode.jpg', followSymlinks: false, onlyIfSuccessful: true
}
}
stage("Publish"){
steps {
withCredentials([sshUserPrivateKey(credentialsId: '小程序密鑰在jenkins保存后的id', keyFileVariable: 'identity')]) {
powershell "node ci\\upload.js --type=upload --version='$version' --number='$BUILD_NUMBER' --desc='$desc' --key='$identity'"
}
}
}
}
}
maven的powershell寫法
jenkinsfiles
pipeline {
agent any //沒有用docker
parameters {//這個(gè)是參數(shù)化構(gòu)建
choice choices: ['deploy', 'rollback'], description: '', name: 'action'
string description: 'rollback ID (only number)', name: 'version'
}
stages {
stage('Build') {
when {//如果是部署
expression { params.action == 'deploy' }
}
steps {//maven打包
powershell 'mvn -B -DskipTests clean package'
}
}
stage('Archive') {
when {//如果是部署
expression { params.action == 'deploy' }
}
steps {//將打包出來的jar包歸檔,方便回滾時(shí)用到
archiveArtifacts artifacts: '自身相關(guān)路徑/target/*.jar', followSymlinks: false, onlyIfSuccessful: true
}
}
stage('Rollback') {
when {//如果是回滾
expression { params.action == 'rollback' }
}
steps {//回滾就不需要打包了,直接將原先版本的歸檔復(fù)制到打包出來的路徑
powershell 'copy-item -path "$JENKINS_HOME\\jobs\\$JOB_NAME\\builds\\$version\\archive\\自身相關(guān)路徑\\target\\*" -destination 自身相關(guān)路徑\\target\\ -recurse -force'
}
}
stage('Publish') {
steps {//publish over ssh插件相關(guān)參數(shù),verbose為true,則jenkins_deploy腳本的執(zhí)行信息會(huì)返回
sshPublisher(publishers: [sshPublisherDesc(configName: '剛才設(shè)置的ssh的名稱', sshRetry: [retries: 3, retryDelay: 5000], transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'powershell E:\\服務(wù)器B相關(guān)部署路徑\jenkins_deploy.sp1 -number $BUILD_NUMBER', execTimeout: , flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '服務(wù)器B相關(guān)路徑', remoteDirectorySDF: false, removePrefix: '自身相關(guān)路徑/target', sourceFiles: '自身相關(guān)路徑/target/*.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
}
}
}
}
jenkins_deploy.ps1
#獲取參數(shù)
param (
[string]$number
)
#移動(dòng)到當(dāng)前目錄
Set-Location E:\abc
#設(shè)置時(shí)間變量
$date=(get-date).ToString('yyyy_MM_dd_HHmmss')
#備份文件名
$backup_name = 'test_'+$date+'_'+$number+'.jar'
#將現(xiàn)有的復(fù)制backup中
Copy-Item -path prod\test.jar -destination backup\$backup_name -force
Write-Output 'backup end'
#關(guān)閉服務(wù)
net stop test
#將最新的移動(dòng)到生產(chǎn)目錄中
Move-Item -path test.jar -destination prod\test.jar -force
Write-Output 'move new to prod'
#開啟服務(wù)
net start test
Write-Output 'finished'
npm的powershell寫法
jenkinsfiles
pipeline {
agent any
parameters {
choice choices: ['deploy', 'rollback'], description: '', name: 'action'
string description: 'rollback ID (only number)', name: 'version'
}
stages {
stage('Install') {
when {
expression { params.action == 'deploy' }
}
steps {//install
powershell 'npm ci --registry https://registry.npm.taobao.org'
}
}
stage("Build"){
when {
expression { params.action == 'deploy' }
}
steps {//build
powershell 'npm run build'
}
}
stage("Archive"){
when {
expression { params.action == 'deploy' }
}
steps {//先打包成壓縮文件,再歸檔,同時(shí)也方便傳輸
powershell 'tar -zcvf dist.tar.gz -C dist .'
archiveArtifacts artifacts: '*.tar.gz', followSymlinks: false, onlyIfSuccessful: true
}
}
stage('rollback') {
when {
expression { params.action == 'rollback' }
}
steps {//將壓縮文件拷貝到正常打包后的位置
powershell 'copy-item -path "$JENKINS_HOME\\jobs\\$JOB_NAME\\builds\\$version\\archive\\dist.tar.gz" -destination dist.tar.gz -force'
}
}
stage("Publish"){
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: '剛才設(shè)置的ssh的名稱', sshRetry: [retries: 3, retryDelay: 5000], transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: 'powershell E:\\服務(wù)器B相關(guān)部署路徑\\jenkins_deploy.ps1 -number $BUILD_NUMBER', execTimeout: , flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '服務(wù)器B相關(guān)部署路徑', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'dist.tar.gz')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: true)])
}
}
}
}
jenkins_deploy.ps1
#獲取參數(shù)
param (
[string]$number
)
#移動(dòng)到當(dāng)前目錄
Set-Location E:\abc
#設(shè)置時(shí)間變量
$date=(get-date).ToString('yyyy_MM_dd_HHmmss')
#備份文件名
$backup_name = 'test_'+$date+'_'+$number+'.tar.gz'
#將現(xiàn)有的打包
tar -zcvf $backup_name -C prod .
#將打包后的移動(dòng)到backup中
Move-Item -path $backup_name -destination backup\$backup_name -force
Write-Output 'backup end'
#清空prod文件夾
Remove-Item -path prod\* -recurse -force
#將最新的解壓到prod中
tar -zxvf dist.tar.gz -C prod
Write-Output 'extra to prod'
#刪除傳遞過來的
Remove-item -path dist.tar.gz -force
Write-Output 'finished'
powershell
各種方法的調(diào)用會(huì)更現(xiàn)代、簡單一些,個(gè)人更推薦,需要大體了解下相關(guān)語法,參考PowerShell 在線教程或者PowerShell教程 。例如如果tar
沒有加入環(huán)境變量,需要這樣寫才行& "xxxx\git\usr\bin\tar.exe" -zcvf xxxx
才行。
windows下jenkins
和cmd
、powershell
的編碼也是費(fèi)勁,目前powershell
腳本文件不管是設(shè)置成ansi
,utf8-bom
,utf8
在jenkins中都是中文亂碼,但是在本地運(yùn)行ansi
,utf8-bom
格式不是亂碼,但是utf8
格式是亂碼,貌似windows powershell 5.1
如果用utf8
則必須用帶bom
的,但最新的powershell 7
則改成不帶bom
的utf8
。jenkins
也是,改了編碼配置命令行展示正常了,但另一個(gè)地方又出現(xiàn)亂碼,壓根是沖突的,所以目前能寫英文的都寫英文的,就這樣系統(tǒng)報(bào)錯(cuò)的話還是亂碼,真是一堆的坑。
目前針對powershell
還算正常的方式是:
ps1
腳本文件編碼為utf8-bom
,可以用notepad++
等軟件來轉(zhuǎn)換下。powershell
軟件本身的編碼為utf8
,具體操作是打印$profile
可得到配置文件所在位置名稱,在配置文件內(nèi)(沒有則自己新建個(gè)同名的)輸入:$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
,保存后再次打開powershell
默認(rèn)就是utf8
展示了。jenkins
的編碼為utf8
,在其安裝目錄下的jenkins.xml
文件中在java
啟動(dòng)項(xiàng)中增加-Dfile.encoding=UTF-8
,重啟即可。