SEMS-system-guardian/SEMS-system-guardian.ps1

339 lines
12 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#$UPDATE_SOURCE = "C:\SEMS-development" #如果为http开头则是网络更新否则则是本地路径更新
$UPDATE_SOURCE = "https://1.u1227383.nyat.app:23587/api/v1/repos/zhanpeng"
$TOCKEN = "e9aaae4b5f7756d0a2977764dbcbdfeb68bb2e13"
$PRODUCTION_FOLDER = "C:\SEMS-production"
# $RAWDATA_FOLDER = "C:\tmp"
# try{
# $errorNetAdapter = Get-PnpDevice -Status ERROR -Class Net
# $errorNetAdapter | Disable-PnpDevice -Confirm:$false
# $errorNetAdapter | Enable-PnpDevice -Confirm:$false
# }catch{
# }
try {
$errorDevices = Get-CimInstance -Query "SELECT * FROM Win32_PnPEntity WHERE PNPClass = 'Net' AND Status = 'Error'"
if ( $null -eq $errorDevices -or $errorDevices.Count -eq 0) {
Write-Host "没有找到状态为ERROR的网络设备。"
}
else {
Write-Host "以下网络设备状态为ERROR 正在重启:"
$errorDevices | ForEach-Object {
Write-Host $_.DeviceID
}
$errorNetAdapter | Disable-PnpDevice -Confirm:$false
$errorNetAdapter | Enable-PnpDevice -Confirm:$false
}
}
catch [Microsoft.Management.Infrastructure.CimException] {
if ($_.Exception.Message -like '*No matching Win32_PnPEntity objects found*') {
Write-Host "没有找到状态为ERROR的网络设备。"
}
else {
Write-Host "执行命令时发生错误: $_"
}
}
catch {
Write-Host "执行命令时发生未知错误: $_"
}
if (Test-Path -Path $PRODUCTION_FOLDER -PathType Container) {
Write-Output "[初始化]生产环境文件夹存在:$PRODUCTION_FOLDER"
}
else {
New-Item -Path $PRODUCTION_FOLDER -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
Write-Output "[初始化]生产环境文件夹不存在,已新建:$PRODUCTION_FOLDER"
}
Write-Output "[初始化]程序更新源路径为:$UPDATE_SOURCE"
function UpdateProgram {
param (
$name #程序名称
)
#在生产部署文件夹中找以$name命名的文件夹其中包含了版本信息
$nowVersion = Get-ChildItem -Path $PRODUCTION_FOLDER -Directory | Where-Object { $_.Name -like "*$name*" } #当前部署的版本,是一个文件夹对象,可能为空
#判断是否为网络更新,网络更新在生产环境中用,本地更新便于开发时测试
if ($UPDATE_SOURCE.Contains("http")) {
#尝试获取最新版本信息,若获取不到则停止更新
try {
$response = Invoke-RestMethod -Uri "$UPDATE_SOURCE/$name/releases/latest?token=$TOCKEN"
#判断最新版本号是否大于当前部署版本号
if ($response.name -gt $nowVersion.name) {
#新建缓存文件夹
New-Item -Path "$PRODUCTION_FOLDER/caches" -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
foreach ($asset in $response.assets) {
if ($asset.name.Contains("zip")) {
Write-Output "[更新]正在下载安装包$($asset.name.Replace(".zip",'')): $($asset.browser_download_url)"
#要把安装包保存的路径
$latestFile = "$PRODUCTION_FOLDER\caches\$($asset.name)"
Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $latestFile
#把路径字符串转换为文件对象,便于后续处理
$latestFile = Get-Item -Path $latestFile
Write-Output "[更新]下载完成,保存在$latestFile"
}
else {
Write-Output "[更新]正在下载配置文件$($asset.name): $($asset.browser_download_url)"
#要把配置文件保存的路径
$latestConfigFile = "$PRODUCTION_FOLDER\$($asset.name)"
Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $latestConfigFile
Write-Output "[更新]下载完成,保存在$latestConfigFile"
#把路径字符串转换为文件对象,便于后续处理
$latestConfigFile = Get-Item -Path $latestConfigFile
}
}
# Write-Output "[更新]正在下载$($response.assets.name.Replace(".zip",'')): $($response.assets.browser_download_url)"
# #要把安装包保存的路径
# $latestFile = "$PRODUCTION_FOLDER\$($response.assets.name)"
# Invoke-WebRequest -Uri $response.assets.browser_download_url -OutFile $latestFile
# Write-Output "[更新]下载完成,保存在$latestFile"
}
else {
Write-Output "[更新] $name 不需要更新,部署版本为$($nowVersion.name), 最新版本为$($response.name)"
Return
}
}
catch {
Write-Output "[更新]最新版本请求失败,跳过处理。错误信息:$_"
Return
}
}
else {
$latestFile = Get-ChildItem -Path $UPDATE_SOURCE -File -Depth 3 | Where-Object { $_.Name -like "*$name*.zip" } | Sort-Object -Property Name | Select-Object -Last 1
#判断最新版本号是否大于当前部署版本号
if ($latestFile.BaseName -gt $nowVersion.Name) {
Write-Output "[更新]正在复制$($latestFile.FullName)$PRODUCTION_FOLDER\$($latestFile.Name)"
Copy-Item -Path $latestFile.FullName -Destination $PRODUCTION_FOLDER\$($latestFile.Name) -Force
$latestFile = Get-Item -Path $PRODUCTION_FOLDER\$($latestFile.Name)
}
else {
Write-Output "[更新] $name 不需要更新,部署版本为$($nowVersion.name), 最新版本为$($latestFile.BaseName)"
Return
}
}
#停止运行程序
if ($name -eq "SEMS-data-collection") {
$process = Get-Process -Name "SEMS-data-collection" -ErrorAction SilentlyContinue
if ($process) {
# 检查进程是否存在,若存在则杀掉
Stop-Process -Id $process.Id -Force
Write-Output "[更新] $name 进程存在,已执行终止命令"
}
else {
Write-Output "[更新] $name 进程不存在"
}
}
if ($name.ToLower() -eq "sems-on-device-server" -or $name.ToLower() -eq "sems-model-inference" ) {
$container = docker inspect -f "{{.State.Running}}" $name.ToLower()
if ($container -eq "true") {
Write-Output "[更新] 容器 $($name.ToLower()) 正在运行, 正在执行终止命令"
docker stop $name.ToLower()
}
else {
Write-Output "[更新] 容器 $($name.ToLower()) 不在运行"
}
}
Write-Output "[更新]${name}程序有更新:$($latestFile.BaseName.Replace("$name-", ''))"
#删除当前部署的旧版本
if (-not [string]::IsNullOrEmpty($nowVersion.FullName)) {
Remove-Item -Path $nowVersion.FullName -Recurse -Force
Write-Output "[更新]已删除旧版本${name}程序:$($nowVersion.Name.Replace("$name-", '')) "
}
#解压安装包到生产部署文件夹
if ($name -eq "SEMS-data-collection") {
$destinationPath = $PRODUCTION_FOLDER
}
else {
$destinationPath = "$PRODUCTION_FOLDER\$($latestFile.BaseName)"
}
Expand-Archive -Path $latestFile.FullName -DestinationPath $destinationPath -Force
#删除安装包
Remove-Item -Path $latestFile.FullName -Force
Write-Output "[更新]已更新${name}程序到:$PRODUCTION_FOLDER\$($latestFile.BaseName), 并删除安装包 $($latestFile.FullName)"
#判断配置是否有更新,若有更新
if (![string]::IsNullOrEmpty($latestConfigFile)) {
Write-Output "[更新]正在更新${name}的配置文件:$($latestConfigFile.BaseName)"
#此功能需要进一步撰写如何实现对比两个yaml文件分别为新文件与旧文件若新文件中有旧文件中没有则添加若新旧文件中都有则不做任何改动若新文件中没有旧文件中有则删除。若旧文件为空或不存在则直接用新文件覆盖。请将上述功能封装为一个函数输入为新旧两个文件的路径
}
}
#######################
# 更新生产环境程序 #
######################
UpdateProgram -name "SEMS-data-collection"
UpdateProgram -name "SEMS-model-inference"
UpdateProgram -name "SEMS-on-device-server"
#################################################
# 检查程序是否在运行,若不在运行则重启 #
##################################################
Write-Output "[状态]准备开始检查程序运行状态"
# 检查 Docker Desktop 服务状态
$process = Get-Process -Name "Docker Desktop" -ErrorAction SilentlyContinue
if ($process) {
Write-Output "[状态]Docker Desktop 正在运行"
}
else {
Write-Output "[状态]Docker Desktop运行正常不在运行正在启动请等待10s"
Start-Process -FilePath "C:\Program Files\Docker\Docker\Docker Desktop.exe"
Start-Sleep -Seconds 10 # 等待 Docker Desktop 启动
$process = Get-Process -Name "Docker Desktop" -ErrorAction SilentlyContinue
if ($process) {
Write-Output "[状态]Docker Desktop已成功运行"
}
else {
Write-Output "[状态]Docker Desktop启动失败"
}
}
function Set-PermanentEnvFromDotEnv {
param (
[string]$envFilePath = ".env",
[System.EnvironmentVariableTarget]$scope = [System.EnvironmentVariableTarget]::User
)
if (-Not (Test-Path $envFilePath)) {
Write-Error "File '$envFilePath' not found."
return
}
Get-Content $envFilePath | ForEach-Object {
$line = $_.Trim()
if ($line -and -not $line.StartsWith("#")) {
$parts = $line -split "=", 2
if ($parts.Length -eq 2) {
$key = $parts[0].Trim()
$value = $parts[1].Trim()
[System.Environment]::SetEnvironmentVariable($key, $value, $scope)
# ${ENV}:$key = $value
Set-Item -Path "ENV:$key" -Value $value
}
}
}
}
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
Write-Output "[初始化]环境变量 $scriptDir\.env"
Set-PermanentEnvFromDotEnv -envFilePath "$scriptDir\.env" -scope User
$folders = Get-ChildItem -Path $PRODUCTION_FOLDER -Directory
$folderDataCollection = $folders | Where-Object { $_.Name -like "*SEMS-data-collection*" }
Write-Output $folderDataCollection.Name
$folderModelInference = $folders | Where-Object { $_.Name -like "*SEMS-model-inference*" }
Write-Output $folderModelInference.Name
$folderOnDeviceServer = $folders | Where-Object { $_.Name -like "*SEMS-on-device-server*" }
Write-Output $folderOnDeviceServer.Name
$process = Get-Process -Name "SEMS-data-collection" -ErrorAction SilentlyContinue
$restart_flag = "false"
if ($process) {
# 检查进程是否正在运行
if ($process.Responding) {
Write-Output "[状态]进程 'SEMS-data-collection' 正在运行"
}
else {
$restart_flag = "true"
Write-Output "[状态]进程 'SEMS-data-collection' 存在但未响应"
}
}
else {
$restart_flag = "true"
Write-Output "[状态]进程 'SEMS-data-collection' 不存在"
}
if ($restart_flag -eq "true") {
$exeFile = Get-ChildItem -Path "$folderDataCollection" -Recurse -File -Depth 2 -Filter "SEMS-data-collection.exe"
Write-Output "[状态]启动进程 $($exeFile.FullName)"
Start-Process -FilePath $exeFile.FullName
}
$container = docker inspect -f "{{.State.Running}}" sems-on-device-server
if ($container -eq "true") {
Write-Output "[状态]容器 'sems-model-inference' 正在运行"
}
else {
Write-Output "[状态]容器 'sems-model-inference' 不在运行,正在启动"
docker run --rm -d -p "22111:22111" -v "$($folderModelInference.FullName):/app" --name sems-model-inference sems-model-inference:latest
}
Write-Output "[状态]数据集路径 $env:RAWDATA_Folder"
if ($container -eq "true") {
Write-Output "[状态]容器 'sems-on-device-server' 正在运行"
}
else {
Write-Output "[状态]容器 'sems-on-device-server' 不在运行,正在运行"
docker run --rm -d -p "22110:22110" -v "$($folderOnDeviceServer.FullName):/app" -v "$ENV:RAWDATA_Folder:/data" --env-file "C:\SEMS-production\configs\.env" --name sems-on-device-server --link sems-model-inference sems-on-device-server:latest
}