jenkins +.net 3.1 windows openssh 部署
jenkins shell 脚本
#!/bin/bash echo "========================================" echo "Jenkins ETL项目构建 (Linux)" echo "========================================" echo "项目名称: DingGC Material ETL" echo "工作空间: ${WORKSPACE}" echo "构建编号: ${BUILD_NUMBER}" echo "构建时间: $(date '+%Y-%m-%d %H:%M:%S')" echo "========================================" # 项目配置 DOTNET_PROJECT="DingGC.Material.ETL" PROJECT_FILE="${DOTNET_PROJECT}/${DOTNET_PROJECT}.csproj" PUBLISH_DIR="publish" BUILD_CONFIG="Release" echo "构建配置:" echo " .NET项目: ${DOTNET_PROJECT}" echo " 项目文件: ${PROJECT_FILE}" echo " 发布目录: ${PUBLISH_DIR}" echo " 构建配置: ${BUILD_CONFIG}" echo " .NET SDK版本: $(dotnet --version)" echo "========================================" # 验证项目文件 if [ ! -f "${PROJECT_FILE}" ]; then echo "❌ 错误:找不到项目文件 ${PROJECT_FILE}" echo "当前目录内容:" ls -la exit 1 fi echo "✅ 项目文件验证通过" # 0. 配置 NuGet 源 echo "" echo "0. 配置 NuGet 源..." # 清除现有源(避免冲突) dotnet nuget remove source nuget.org 2>/dev/null || true dotnet nuget remove source dinggc 2>/dev/null || true # 添加公司私有 NuGet 源 dotnet nuget add source https://nuget.dinggc.com/nuget -n dinggc if [ $? -eq 0 ]; then echo "✅ 添加公司私有源: https://nuget.dinggc.com/nuget" else echo "⚠️ 添加公司私有源失败,将继续尝试构建" fi # 添加官方 NuGet 源 dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org if [ $? -eq 0 ]; then echo "✅ 添加官方源: https://api.nuget.org/v3/index.json" else echo "⚠️ 添加官方源失败,将继续尝试构建" fi echo "当前可用的 NuGet 源:" dotnet nuget list source # 1. 清理之前构建 echo "" echo "1. 清理之前构建..." rm -rf "${PUBLISH_DIR}" 2>/dev/null || true # 清理 obj 和 bin 目录 find . -name "obj" -type d -exec rm -rf {} + 2>/dev/null || true find . -name "bin" -type d -exec rm -rf {} + 2>/dev/null || true # 4. 发布项目 echo "" echo "4. 发布项目..." /usr/local/dotnet-sdk-3.1/dotnet publish "${PROJECT_FILE}" \ -c "${BUILD_CONFIG}" \ -o "${PUBLISH_DIR}" \ -r win-x64 \ -f netcoreapp3.1 \ --no-self-contained \ if [ $? -eq 0 ]; then echo "✅ 项目发布成功" # 显示主要文件 echo "" echo "发布目录内容:" ls -la "${PUBLISH_DIR}/" # 检查关键文件是否存在 echo "" echo "关键文件检查:" if [ -f "${PUBLISH_DIR}/DingGC.Material.ETL.dll" ]; then echo "✅ 主程序集: DingGC.Material.ETL.dll" echo " 文件大小: $(du -h "${PUBLISH_DIR}/DingGC.Material.ETL.dll" | cut -f1)" else echo "❌ 缺少主程序集: DingGC.Material.ETL.dll" fi if [ -f "${PUBLISH_DIR}/appsettings.json" ]; then echo "✅ 配置文件: appsettings.json" else echo "⚠️ 缺少配置文件: appsettings.json" fi else echo "❌ 项目发布失败" exit 1 fi # 5. 创建压缩包 echo "" echo "5. 创建发布包..." PACKAGE_NAME="DingGC-Material-ETL-$(date '+%Y%m%d%H%M%S')-${BUILD_NUMBER}.tar.gz" tar -czf "${PACKAGE_NAME}" -C "${PUBLISH_DIR}" . if [ $? -eq 0 ]; then echo "✅ 压缩包创建成功: ${PACKAGE_NAME}" echo " 压缩包大小: $(du -h "${PACKAGE_NAME}" | cut -f1)" # 创建制品目录并复制 ARTIFACTS_DIR="${WORKSPACE}/artifacts" mkdir -p "${ARTIFACTS_DIR}" mv "${PACKAGE_NAME}" "${ARTIFACTS_DIR}/" echo "✅ 制品保存到: ${ARTIFACTS_DIR}/" # 同时保留一份副本到工作空间根目录 cp "${ARTIFACTS_DIR}/${PACKAGE_NAME}" "${WORKSPACE}/" 2>/dev/null || true else echo "❌ 压缩包创建失败" # 如果 tar 失败,尝试使用 zip echo "尝试使用 zip 打包..." cd "${PUBLISH_DIR}" && zip -r "../${PACKAGE_NAME%.tar.gz}.zip" . && cd .. if [ $? -eq 0 ]; then echo "✅ ZIP包创建成功: ${PACKAGE_NAME%.tar.gz}.zip" fi fi echo "" echo "========================================" echo "构建完成!" echo "========================================" echo "发布目录: ${WORKSPACE}/${PUBLISH_DIR}" echo "压缩包: ${WORKSPACE}/artifacts/${PACKAGE_NAME}" echo "构建时间: $(date '+%Y-%m-%d %H:%M:%S')" echo "========================================"
配置 Source files artifacts/DingGC-Material-ETL-*.tar.gz
Remote directory D:\workspace\${PIPELINE_CODE}\
Exec command cmd /c "D:\ETL-Deploy\deploy-pipeline.bat ${PIPELINE_CODE} ${DEPLOY_MODE} ${PROJECT_NAME}"
服务器脚本 deploy-pipeline.bat
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
:: 参数:%1=管道代码,%2=部署模式(full/quick),%3=项目目录(可选)
set PIPELINE_CODE=%~1
set DEPLOY_MODE=%~2
set PROJECT_DIR=%~3
if "%PIPELINE_CODE%"=="" (
echo 错误:需要管道代码参数
echo 用法: deploy.bat [管道代码] [部署模式] [项目目录]
echo 示例: deploy.bat ODW_Material full DingGC.Material.ETL
)
if "%DEPLOY_MODE%"=="" set DEPLOY_MODE=full
if "%PROJECT_DIR%"=="" set PROJECT_DIR=DingGC.Material.ETL
:: NSSM 路径
set "NSSM_PATH=D:\ETL-Deploy\nssm.exe"
if not exist "%NSSM_PATH%" (
echo 错误:找不到 nssm.exe 在 %NSSM_PATH%
)
echo 开始部署...
echo 管道: %PIPELINE_CODE%
echo 模式: %DEPLOY_MODE%
echo 项目目录: "%PROJECT_DIR%"
:: 读取配置文件
set "CONFIG_FILE=D:\ETL-Deploy\mapping.ini"
if not exist "%CONFIG_FILE%" (
echo 错误:找不到配置文件 %CONFIG_FILE%
exit /b 1
)
echo 正在读取配置文件...
set FOLDER_NAME=
set SERVICE_NAME=
set IN_SECTION=0
:: 读取INI格式配置文件 - 已加@
for /f "usebackq delims=" %%a in ("%CONFIG_FILE%") do @(
set "LINE=%%a"
:: 去除首尾空格
for /f "tokens=*" %%b in ("!LINE!") do set "LINE=%%b"
:: 跳过空行和注释
if not "!LINE!"=="" (
if not "!LINE:~0,1!"=="#" (
:: 检查是否是 [PIPELINE_MAPPING] 节
if "!LINE!"=="[PIPELINE_MAPPING]" (
set IN_SECTION=1
) else if "!LINE:~0,1!"=="[" (
set IN_SECTION=0
) else if !IN_SECTION! equ 1 (
:: 解析键值对:管道代码=文件夹|服务
for /f "tokens=1,2 delims==" %%b in ("!LINE!") do @(
set "KEY=%%b"
set "VALUE=%%c"
:: 去除KEY的空格
for /f "tokens=*" %%d in ("!KEY!") do set "KEY=%%d"
if /i "!KEY!"=="%PIPELINE_CODE%" (
:: 分割VALUE:文件夹|服务
for /f "tokens=1,2 delims=|" %%e in ("!VALUE!") do @(
for /f "tokens=*" %%f in ("%%e") do set "FOLDER_NAME=%%f"
for /f "tokens=*" %%f in ("%%f") do set "SERVICE_NAME=%%f"
)
)
)
)
)
)
)
echo 文件夹: [!FOLDER_NAME!]
echo 服务: [!SERVICE_NAME!]
if "!FOLDER_NAME!"=="" (
echo 错误:配置文件中找不到管道 %PIPELINE_CODE%
echo 配置文件内容:
type "%CONFIG_FILE%"
)
:: 设置路径
set "SOURCE_DIR=D:\workspace\%PIPELINE_CODE%"
set "TARGET_DIR=D:\Project\%PROJECT_DIR%\!FOLDER_NAME!"
set "BACKUP_DIR=D:\ETL-Backup"
echo 源目录: !SOURCE_DIR!
echo 目标目录: !TARGET_DIR!
echo 备份目录: !BACKUP_DIR!
:: 检查源目录是否存在
if not exist "!SOURCE_DIR!\" (
echo 错误:源目录不存在 !SOURCE_DIR!
)
:: 查找最新的tar.gz文件
echo 正在查找最新的构建包...
set "LATEST_FILE="
:: 简单方法:使用最近修改的文件 - 已加@
for /f "delims=" %%f in ('dir /b /o-d /tw "!SOURCE_DIR!\*.tar.gz" 2^>nul') do @(
set "LATEST_FILE=!SOURCE_DIR!\%%f"
goto :file_found
)
:file_found
if "!LATEST_FILE!"=="" (
echo 错误:找不到tar.gz文件
dir "!SOURCE_DIR!\"
)
echo 找到构建包: !LATEST_FILE!
set "SOURCE_FILE=!LATEST_FILE!"
:: 显示文件信息
echo 文件信息:
for %%F in ("!SOURCE_FILE!") do @(
echo 文件名: %%~nxF
echo 文件大小: %%~zF bytes
echo 修改时间: %%~tF
)
:: 创建临时解压目录
set "TEMP_DIR=%TEMP%\%PIPELINE_CODE%_%RANDOM%"
mkdir "!TEMP_DIR!" 2>nul
echo 临时解压目录: !TEMP_DIR!
:: 解压文件
echo 正在解压文件...
tar -xzf "!SOURCE_FILE!" -C "!TEMP_DIR!"
if errorlevel 1 (
echo 错误:解压失败
rmdir /s /q "!TEMP_DIR!" 2>nul
exit /b 1
)
:: 检查解压后的内容
echo 检查解压文件...
set "FILE_COUNT=0"
for /f %%i in ('dir "!TEMP_DIR!" /b /a-d ^| find /c /v ""') do set "FILE_COUNT=%%i"
if !FILE_COUNT! equ 0 (
echo 错误:解压后目录为空
rmdir /s /q "!TEMP_DIR!" 2>nul
exit /b 1
)
echo 解压完成,找到 !FILE_COUNT! 个文件
:: 检查服务是否存在
echo 检查服务状态...
set SERVICE_EXISTS=0
sc query "!SERVICE_NAME!" >nul 2>&1 && set SERVICE_EXISTS=1
:: 检查是否有exe文件 - 已加@
echo 检查是否有exe文件...
set "MAIN_EXE="
for %%f in ("!TEMP_DIR!\*.exe") do @(
set "MAIN_EXE=%%~nxf"
goto :found_exe
)
:found_exe
if "!MAIN_EXE!"=="" (
echo 错误:解压包中没有找到exe文件!
echo 请确保构建时生成了exe文件
rmdir /s /q "!TEMP_DIR!" 2>nul
exit /b 1
)
echo 找到exe文件: !MAIN_EXE!
if !SERVICE_EXISTS! equ 1 (
echo 服务已存在: !SERVICE_NAME!
:: 停止服务(如果是完整部署)
if /i "!DEPLOY_MODE!"=="full" (
echo 停止服务: !SERVICE_NAME!...
"%NSSM_PATH%" stop "!SERVICE_NAME!" confirm >nul 2>&1
timeout /t 10 /nobreak >nul
:: 确认服务已停止
sc query "!SERVICE_NAME!" | find "STOPPED" >nul
if errorlevel 1 (
echo 警告:服务可能未完全停止,等待5秒...
timeout /t 5 /nobreak >nul
)
echo 服务已停止
)
) else (
echo 服务不存在: !SERVICE_NAME! (首次部署)
)
:: 创建备份目录
echo 创建备份...
set "BACKUP_DATE=%date:~0,4%%date:~5,2%%date:~8,2%"
set "BACKUP_TIME=%time:~0,2%%time:~3,2%%time:~6,2%"
set "BACKUP_PATH=!BACKUP_DIR!\!BACKUP_DATE!\!PIPELINE_CODE!_!BACKUP_TIME!"
set "BACKUP_PATH=!BACKUP_PATH: =0!"
if not exist "!BACKUP_PATH!\" (
mkdir "!BACKUP_PATH!"
)
:: 备份当前版本
if exist "!TARGET_DIR!\" (
echo 备份目标目录(排除log和logs)...
:: 复制文件
for /f "delims=" %%a in ('dir "!TARGET_DIR!" /b /a-d') do (
copy "!TARGET_DIR!\%%a" "!BACKUP_PATH!\" >nul
)
:: 复制子目录(排除log和logs)
for /f "delims=" %%a in ('dir "!TARGET_DIR!" /b /ad') do (
if /i not "%%a"=="log" if /i not "%%a"=="logs" (
xcopy "!TARGET_DIR!\%%a" "!BACKUP_PATH!\%%a\" /S /E /H /I /Y >nul
)
)
echo 备份完成"
) else (
echo 目标目录不存在,无需备份
)
:: 部署文件到目标目录
echo 部署文件到 !TARGET_DIR!...
if not exist "!TARGET_DIR!\" (
mkdir "!TARGET_DIR!"
echo 创建目标目录
)
echo 正在复制文件(排除配置文件模板)...
:: 从临时目录复制所有文件到目标目录 - 已加@
for %%f in ("!TEMP_DIR!\*") do @(
set "filename=%%~nxf"
set "ext=%%~xf"
:: 检查是否是配置文件
set "is_config=0"
if not "!filename:appsettings=!"=="!filename!" set "is_config=1"
if "!ext!"==".config" set "is_config=1"
if "!ext!"==".json" if not "!filename:appsettings=!"=="!filename!" set "is_config=1"
if !is_config! equ 0 (
>nul 2>&1 xcopy "%%f" "!TARGET_DIR!\" /Y
) else (
echo 跳过配置文件: !filename!
)
)
echo 文件复制完成"
:: 清理临时目录
rmdir /s /q "!TEMP_DIR!" 2>nul
:: 处理服务
echo 处理服务..."
set "TARGET_EXE=!TARGET_DIR!\!MAIN_EXE!"
if not exist "!TARGET_EXE!" (
echo 错误:目标目录中没有找到exe文件 !MAIN_EXE!
echo 请检查构建包是否包含exe文件
exit /b 1
)
if !SERVICE_EXISTS! equ 1 (
:: 服务存在,启动服务(如果是完整部署)
if /i "!DEPLOY_MODE!"=="full" (
echo 启动服务: !SERVICE_NAME!...
"%NSSM_PATH%" start "!SERVICE_NAME!" >nul 2>&1
timeout /t 10 /nobreak >nul
:: 检查服务状态
"%NSSM_PATH%" status "!SERVICE_NAME!" >nul 2>&1
if errorlevel 1 (
echo 错误:服务启动失败!
:: 尝试使用系统命令启动
echo 尝试使用系统命令启动服务...
net start "!SERVICE_NAME!" >nul 2>&1
:: 再次检查状态
sc query "!SERVICE_NAME!" | find "RUNNING" >nul
if errorlevel 1 (
echo 严重错误:服务无法启动,请手动检查!
) else (
echo 服务已通过系统命令启动
)
) else (
echo 服务运行正常
)
) else (
echo 快速部署模式,不重启服务
echo 注意:需要手动重启服务以应用更改
)
) else (
:: 服务不存在,创建服务(如果是完整部署)
if /i "!DEPLOY_MODE!"=="full" (
echo 创建新服务: !SERVICE_NAME!...
:: 使用 NSSM 创建服务
echo 使用NSSM创建服务,指向exe文件: !MAIN_EXE!
"%NSSM_PATH%" install "!SERVICE_NAME!" "!TARGET_EXE!"
:: 设置服务描述
"%NSSM_PATH%" set "!SERVICE_NAME!" Description "ETL Service for %PIPELINE_CODE%"
:: 设置工作目录
"%NSSM_PATH%" set "!SERVICE_NAME!" AppDirectory "!TARGET_DIR!"
:: 设置启动类型为自动
>nul sc config "!SERVICE_NAME!" start= auto
:: 启动服务
"%NSSM_PATH%" start "!SERVICE_NAME!" >nul 2>&1
echo 服务创建并启动完成
) else (
echo 快速部署模式,不创建新服务
)
)
echo.
echo ========================================
echo 部署完成!
echo ========================================
echo 管道代码: %PIPELINE_CODE%
echo 目标文件夹: !FOLDER_NAME!
echo 服务名称: !SERVICE_NAME!
echo EXE文件: !MAIN_EXE!
endlocal
配置文件 mapping.ini
# 格式:管道代码 = 目标文件夹 | 服务名称 [PIPELINE_MAPPING] ODW_Material=01DingGC.Material.ETL 同步ODW材料|MaterialETLService同步ODW材料 ODW_Brand=02DingGC.Material.ETL 同步ODW品牌|MaterialETLService同步ODW品牌 ODW_Project=03DingGC.Material.ETL 同步ODW项目|MaterialETLService同步ODW项目 DGC_Material=04DingGC.Material.ETL 同步DGC材料|MaterialETLService同步DGC材料 DGC_Brand=05DingGC.Material.ETL 同步DGC品牌|MaterialETLService同步DGC品牌 DGC_Project=06DingGC.Material.ETL 同步DGC项目材料|MaterialETLService同步DGC项目材料 DGC_ProjectBOQ=07DingGC.Material.ETL 同步DGC项目BOQ|MaterialETLService同步DGC项目BOQ

浙公网安备 33010602011771号