【脚本】一键部署脚本

发布于:2025-05-28 ⋅ 阅读:(22) ⋅ 点赞:(0)

背景:现场实施同事部署项目步骤繁琐、配置项容易搞错并且容易更错软件包;所以在想能不能写一个跨平台Shell/PowerShell脚本,自动完成Jdk安装、配置文件替换、服务启动等10+步骤等;经过一周的编写加调试,终于搞定,经实施同事确认,单次部署时间从2小时(人工)缩短至5分钟(脚本),实施效率提升24倍;部署流程标准化率100%,新员工培训成本至少减少70%;

deploy-wms.ps1

param(
    [string]$ConfigFile = "wms-config.ps1"
)

# Error handling
$ErrorActionPreference = "Stop"

# Load configuration file
if (-Not (Test-Path $ConfigFile)) {
    throw "Error: Configuration file $ConfigFile not found!"
}
. (Resolve-Path $ConfigFile)

# Validate required parameters
$requiredVars = @(
    "DeployPath",
	"MySqlUrl",
    "BackendPackage",
    "FrontendPackage",
	"H5Package",
    "NginxPath",
    "BackendURL",
	"NginxListenPort"
)

foreach ($var in $requiredVars) {
    if (-Not (Get-Variable -Name $var -ErrorAction SilentlyContinue)) {
        throw "Error: Missing required configuration parameter $var"
    }
}

# [1/9]创建部署目录
Write-Host "[1/9] Creating deployment directory..."
$directories = @(
    "$DeployPath/backend",
    "$DeployPath/frontend",
    "$DeployPath/h5",
    "$DeployPath/nginx"
)
$directories | ForEach-Object {
    New-Item -Path $_ -ItemType Directory -Force | Out-Null
}
# [2/9]安装JDK
Write-Host "[2/9] Install JDK..."
$jdkInstalled = $false
$javaVersion = (Get-Command java -ErrorAction SilentlyContinue).Version

if ($javaVersion) {
    Write-Host "JDK is already installed, version: $javaVersion"
    $jdkInstalled = $true
} else {
    Write-Host "JDK not detected, starting installation..."
}

# If JDK is not installed, proceed with installation
if (-not $jdkInstalled) {
    # Specify the path to the already downloaded JDK installer
    $installerPath = ".\jdk\jdk-8u291-windows-x64.exe"

    if (-Not (Test-Path $installerPath)) {
        Write-Host "JDK installer not found, please check the path: $installerPath"
        exit 1
    }

    # Install JDK
    Start-Process -FilePath $installerPath -ArgumentList "/s" -Wait

    # Configure environment variables
    $javaHome = "C:\Program Files\Java\jdk-8"
    [System.Environment]::SetEnvironmentVariable("JAVA_HOME", $javaHome, [System.EnvironmentVariableTarget]::Machine)
    $env:JAVA_HOME = $javaHome

    $path = [System.Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::Machine)
    $newPath = "$javaHome\bin;" + $path
    [System.Environment]::SetEnvironmentVariable("Path", $newPath, [System.EnvironmentVariableTarget]::Machine)
    $env:Path = "$javaHome\bin;" + $env:Path

    Write-Host "JDK installation complete and environment variables configured"
}
# [3/9]安装MySql
Write-Host "[3/9] Install MySQL..."
$mysqlInstalled = $false
if (Get-Service -Name "MySQL*" -ErrorAction SilentlyContinue) {
    Write-Host "The MySQL service already exists"
    $mysqlInstalled = $true
} elseif (Get-Command mysql -ErrorAction SilentlyContinue) {
    Write-Host "The MySQL client has been installed。"
    $mysqlInstalled = $true
}

if (-not $mysqlInstalled) {
    $installerPath = ".\mysql\mysql-installer-community-8.0.34.0.msi"
    if (-not (Test-Path $installerPath)) {
        Write-Host "Error: The installation package cannot be found $installerPath"
        exit 1
    }

    $installArgs = @(
        "/i",
        "`"$installerPath`"",
        "/qn",
        "/L*v `"$env:TEMP\MySQLInstall.log`"",
        "ADDLOCAL=Server,Client",
        "INSTALLDIR=`"C:\Program Files\MySQL\MySQL Server 8.0`"",
        "PORT=3306",
        "ENABLETCPIP=1",
        "AGREETOLICENSE=Yes",
        "/norestart"
    )

    # Carry out the installation
    Start-Process msiexec -ArgumentList $installArgs -Wait

    # Set environment variables
    $mysqlBinPath = "C:\Program Files\MySQL\MySQL Server 8.0\bin"
    [Environment]::SetEnvironmentVariable("Path", "$mysqlBinPath;$env:Path", "Machine")
    $env:Path += ";$mysqlBinPath"

    # Initialize the data directory and start the service
    & "$mysqlBinPath\mysqld" --initialize-insecure --user=mysql
    Start-Service -Name "MySQL80"

    # Set the root password
    & "$mysqlBinPath\mysql" -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456'; FLUSH PRIVILEGES;"
    try {
        mysql -u root -p123456 -e "SELECT @@version;" --silent
        Write-Host "The MySQL installation was successful."
    } catch {
        Write-Host "Connection failed. Please check the log:"
        Get-Content "$env:ProgramData\MySQL\MySQL Server 8.0\Data\*.err" -Tail 20 -ErrorAction SilentlyContinue
        Write-Host "Complete installation log:$env:TEMP\MySQLInstall.log"
        exit 1
    }
}
# [4/9]部署后端服务
Write-Host "[4/9] Deploying backend services..."
if (-Not (Test-Path $BackendPackage)) {
    throw "Error: Backend package $BackendPackage not found!"
}
# Stop existing backend process
$existingProcess = Get-Process -Name java -ErrorAction SilentlyContinue | 
    Where-Object { $_.Id -ne $pid }
if ($existingProcess) {
    $existingProcess | Stop-Process -Force
}
# Clear and extract backend package
Remove-Item -Path "$DeployPath/backend/*" -Recurse -Force -ErrorAction SilentlyContinue
Expand-Archive -Path $BackendPackage -DestinationPath "$DeployPath/backend" -Force

# Check required files
$jarFile = Get-ChildItem "$DeployPath/backend" -Filter *.jar | Select-Object -First 1
if (-Not $jarFile) {
    throw "No JAR file found, please check the backend package content"
}
# update yml configuration
$configFile = Join-Path -Path $DeployPath -ChildPath "backend/config/application.yml"
if (-Not (Test-Path $configFile)) {
    throw "Configuration file application.yml not found"
}
$content = Get-Content -Path $configFile -Raw -Encoding UTF8
$lines = $content -split "`r?`n"
for ($i = 0; $i -lt $lines.Length; $i++) {
    if ($lines[$i] -match "^\s*url:\s*jdbc:mariadb://.*") {
        if ($lines[$i] -match "^\s*") {
            $indentation = $matches[0]
        } else {
            $indentation = ''
        }
        $lines[$i] = "${indentation}url: $MySqlUrl"
    }
}
$updatedContent = [string]::Join("`n", $lines)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($updatedContent)

[System.IO.File]::WriteAllBytes($configFile, $bytes)
Write-Host "Configuration file updated successfully"

# [5/9]启动后端服务
Write-Host "[5/9] Starting backend services..."
$jarFile = Get-ChildItem -Path "$DeployPath\backend" -Filter "*.jar" | Select-Object -First 1

if (-Not $jarFile) {
    Write-Host "No .jar file found in directory: $($DeployPath)\backend"
    exit 1
}
$javaArgs = @(
    "-Dfile.encoding=UTF-8",
    "-Dsun.jnu.encoding=UTF-8",
    "-jar",
    "`"$($jarFile.FullName)`"",
    "--spring.config.location=file:`"$configFile`""
)

# Merge arguments into a string
$javaArgsString = $javaArgs -join " "

# Print arguments for debugging
Write-Host "Java Arguments: $javaArgsString"

# Define a script block to start the Java application with logging
$scriptBlock = {
    param($javaArgsString, $DeployPath)
    
    # Create logs directory
    $logDir = Join-Path $DeployPath "backend/logs"
    New-Item -ItemType Directory -Path $logDir -Force | Out-Null
    
    # Generate timestamp for log files
    $stdoutLog = Join-Path $logDir "stdout_logFile.log"
    $stderrLog = Join-Path $logDir "stderr_logFile.log"
    
    # Start Java process with output redirection
    Start-Process -FilePath "java" `
        -ArgumentList $javaArgsString `
        -NoNewWindow `
        -PassThru `
        -RedirectStandardOutput $stdoutLog `
        -RedirectStandardError $stderrLog
}

# Start the background job with parameters
$job = Start-Job -ScriptBlock $scriptBlock -ArgumentList $javaArgsString, $DeployPath

# Wait for a moment to ensure the process starts
Start-Sleep -Seconds 5

# Get the process ID
$process = Get-Process java -ErrorAction SilentlyContinue | 
    Where-Object { $_.Id -ne $pid } | 
    Select-Object -First 1

# Check and output status
if ($null -ne $process -and -not $process.HasExited) {
    $process.Id | Out-File "$DeployPath/backend/backend.pid"
    Write-Host "Backend service started (PID: $($process.Id))"
    Write-Host "Logs directory: $DeployPath/backend/logs/"
} else {
    Write-Host "Failed to start the backend process."
    exit 1
}
# Output process ID to file
$process.Id | Out-File "$DeployPath/backend/backend.pid"

# [6/9]部署前端服务
Write-Host "[6/9] Deploying frontend services..."
if (-Not (Test-Path $FrontendPackage)) {
    throw "Error: Frontend package $FrontendPackage not found!"
}

Remove-Item -Path "$DeployPath/frontend/*" -Recurse -Force -ErrorAction SilentlyContinue
Expand-Archive -Path $FrontendPackage -DestinationPath "$DeployPath/frontend" -Force

# Deploy H5
if (-Not (Test-Path $H5Package)) {
    throw "Error: Frontend package $H5Package not found!"
}
Remove-Item -Path "$DeployPath/h5/*" -Recurse -Force -ErrorAction SilentlyContinue
Expand-Archive -Path $H5Package -DestinationPath "$DeployPath/h5" -Force
#配置前端文件
$configJs = "$DeployPath/frontend/config.js"
$configH5Js = "$DeployPath/h5/static/config.js"
if (Test-Path $configJs) {
    Write-Host "Configuring front-end parameters..."
    try {
        $originalContent = [System.Text.Encoding]::UTF8.GetString([System.IO.File]::ReadAllBytes($configJs))
        $newContent = $originalContent -replace 'backendURL:.*', "backendURL: '$BackendURL',"
        [System.IO.File]::WriteAllBytes($configJs, [System.Text.Encoding]::UTF8.GetBytes($newContent))
        Write-Host "Front-end configuration updated successfully."
    } catch {
        Write-Error "Failed to update front-end configuration: $_"
    }
} else {
    Write-Warning "Front-end configuration file config.js not found"
}
if (Test-Path $configH5Js) {
    Write-Host "Configuring h5 parameters..."
    try {
        $originalContent = [System.Text.Encoding]::UTF8.GetString([System.IO.File]::ReadAllBytes($configH5Js))
        $newContent = $originalContent -replace 'backendURL:.*', "backendURL: '$BackendURL',"
        [System.IO.File]::WriteAllBytes($configH5Js, [System.Text.Encoding]::UTF8.GetBytes($newContent))
        Write-Host "h5 configuration updated successfully."
    } catch {
        Write-Error "Failed to update h5 configuration: $_"
    }
} else {
    Write-Warning "h5 configuration file config.js not found"
}
# [7/9]部署nginx服务
Write-Host "[7/9] Deploying Nginx services..."
if (-Not (Test-Path $NginxPath)) {
    throw "Error: Nginx package $NginxPath not found!"
}
# Stop old process (enhanced version)
if (Get-Process -Name "nginx" -ErrorAction SilentlyContinue) {
    taskkill /IM "nginx.exe" /F 2>&1 | Out-Null
}
# Clear and extract Nginx
Remove-Item -Path "$DeployPath/nginx/*" -Recurse -Force -ErrorAction SilentlyContinue
Expand-Archive -Path $NginxPath -DestinationPath "$DeployPath/nginx" -Force

#前端配置目录移到nginx目录下的html文件夹下
Copy-Item -Path "$DeployPath/frontend" -Destination "$DeployPath/nginx/nginx-1.24.0/html/PC" -Recurse -Force
Copy-Item -Path "$DeployPath/h5" -Destination "$DeployPath/nginx/nginx-1.24.0/html/PDA" -Recurse -Force

# [8/9]配置niginx
Write-Host "[8/9] Configuring Nginx services..."

# Normalize paths
$nginxLogsPath = "$DeployPath\nginx\nginx-1.24.0\logs" -replace '\\', '\'
$nginxConfPath = "$DeployPath\nginx\nginx-1.24.0\conf\wms-nginx.conf"
$nginxExePath = "$DeployPath\nginx\nginx-1.24.0\nginx.exe"
$logsPath = "$DeployPath\logs"
$tempPath = "$DeployPath\temp"
# Create necessary directories
New-Item -Path $nginxLogsPath -ItemType Directory -Force | Out-Null

$logFiles = @("access.log", "error.log", "nginx.pid")
if (-not (Test-Path $logsPath)) {
    New-Item -ItemType Directory -Path $logsPath
}
foreach ($logFile in $logFiles) {
    $logFilePath = "$logsPath\$logFile"
    if (-not (Test-Path $logFilePath)) {
        New-Item -ItemType File -Path $logFilePath
        Write-Host "Created $logFile at: $logFilePath"
    }
}

$tempFolders = @("client_body_temp", "fastcgi_temp", "proxy_temp", "scgi_temp", "uwsgi_temp")
if (-not (Test-Path $tempPath)) {
    New-Item -ItemType Directory -Path $tempPath
}
foreach ($tempFolder in $tempFolders) {
    $tempFolderPath = "$tempPath\$tempFolder"
    if (-not (Test-Path $tempFolderPath)) {
        New-Item -ItemType Directory -Path $tempFolderPath
        Write-Host "Created $tempFolder at: $tempFolderPath"
    }
}
# Generate Nginx configuration file
$nginxConf = @"
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    map `$http_user_agent` `$root_path` {
        default       $NginxDeployPath/nginx/nginx-1.24.0/html/PC;
        ~*(android|iphone|ipad|mobile) $NginxDeployPath/nginx/nginx-1.24.0/html/PDA;
    }

    server {
        listen $NginxListenPort;
        server_name localhost;

        location /static/config.js {
            alias $NginxDeployPath/nginx/nginx-1.24.0/html/PC/config.js;
            add_header 'Access-Control-Allow-Origin' '*' always;
        }

        location / {
            root `$root_path`;
            index index.html index.htm;
			try_files `$uri` `$uri`/ /index.html;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root html;
        }
    }

    server {
        listen 1112;
        server_name $BackendAddress;

        location / {
            root $DeployPath\backend\upload;
            index index.html index.htm;
            autoindex on;
        }
    }
}

"@

# Write configuration file
# Convert string content to byte array (without BOM)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($nginxConf)
# Write byte array to file
[System.IO.File]::WriteAllBytes($nginxConfPath, $bytes)

# Check Nginx executable
if (-not (Test-Path $nginxExePath)) {
    throw "Nginx executable missing at: $nginxExePath"
}

# Test configuration file
& "$nginxExePath" -t -c "$nginxConfPath"
if ($LASTEXITCODE -ne 0) {
    Write-Host "Nginx configuration test failed. Please check the configuration file."
    exit $LASTEXITCODE
} else {
    Write-Host "Nginx configuration test passed."
}
# [9/9]启动nginx服务
Write-Host "[9/9] Starting Nginx services..."
Start-Process -FilePath "$nginxExePath" -ArgumentList "-c $nginxConfPath" -NoNewWindow

# Wait a few seconds to ensure Nginx has enough time to start
Start-Sleep -Seconds 5

# Check Nginx process
$nginxProcess = Get-Process -Name "nginx" -ErrorAction SilentlyContinue

if ($nginxProcess) {
    Write-Output "Nginx has started successfully."
} else {
    Write-Output "Nginx failed to start. Please check the configuration file and logs."
}

Write-Host @"
==========================================
WMS system deployment successfully!
==========================================
"@

wms-config.ps1

# 基础部署路径
$DeployPath = "E:\wms-test-4"
$NginxDeployPath = "E:/wms-test-4"

# 后端数据库配置
$MySqlUrl = "jdbc:mariadb://127.0.0.1:3306/wms_zhixiang_03_10?characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&serverTimezone=Asia/Shanghai"

# 后端包路径
$BackendPackage = ".\wms-service-3.4.4.zhixiang.1-1.zip"

# 前端包路径
$FrontendPackage = ".\wms3.0-frontend.zip"

#前端 H5包路径
$H5Package = ".\h5.zip"

# Nginx安装路径
$NginxPath = ".\nginx-1.24.0.zip"
#后端端口
$serverPort = "8082"
$newPort = "8082"
# 后端服务地址
$BackendURL = "http://10.14.240.208:8081"
$BackendAddress = "10.14.240.208:8081"

# Nginx监听端口(前端端口)
$NginxListenPort = "8842"

网站公告

今日签到

点亮在社区的每一天
去签到