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

  

 

posted @ 2026-01-23 17:05  ''Crazy  阅读(2)  评论(0)    收藏  举报