added installer
This commit is contained in:
parent
1d04e2a4e8
commit
ce741133d8
12 changed files with 2226 additions and 0 deletions
72
.gitignore
vendored
Normal file
72
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Windows Agent Installation Artifacts
|
||||
# These files should not be committed to the repository
|
||||
|
||||
# Generated Config Files
|
||||
OGP64/OGP/Cfg/Config.pm
|
||||
OGP64/OGP/Cfg/Preferences.pm
|
||||
OGP64/OGP/Cfg/bash_prefs.cfg
|
||||
|
||||
# Runtime Files
|
||||
OGP64/OGP/ogp_agent.log
|
||||
OGP64/OGP/*.pid
|
||||
OGP64/OGP/ogp_agent_run.pid
|
||||
OGP64/OGP/OGP.pid
|
||||
OGP64/var/run/*.pid
|
||||
|
||||
# Screenlogs (server console output)
|
||||
OGP64/OGP/screenlogs/
|
||||
|
||||
# Startup Hints
|
||||
OGP64/OGP/startups/
|
||||
|
||||
# Runtime Status Files
|
||||
OGP64/OGP/runtime_status/
|
||||
|
||||
# Temporary and Cache Files
|
||||
OGP64/OGP/tmp/
|
||||
OGP64/OGP/shared/
|
||||
*.tmp
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# SteamCMD Cache
|
||||
OGP64/OGP/steamcmd/linux32/
|
||||
OGP64/OGP/steamcmd/steamapps/
|
||||
|
||||
# Extracted Portable Git (included as 7z but not extracted)
|
||||
tools/PortableGit/
|
||||
|
||||
# Logs and Backups (created at C:\GSP during installation)
|
||||
logs/
|
||||
backups/
|
||||
|
||||
# Windows-specific files
|
||||
Thumbs.db
|
||||
*.lnk
|
||||
.DS_Store
|
||||
|
||||
# Editor and IDE Files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
*.sublime-workspace
|
||||
|
||||
# Installer Artifacts (if extracted locally)
|
||||
Installer/PortableGit-*/
|
||||
|
||||
# Agent Home Directories (customer servers)
|
||||
home/
|
||||
|
||||
# Cygwin runtime (if accidentally committed)
|
||||
OGP64/bin/
|
||||
OGP64/lib/
|
||||
OGP64/etc/
|
||||
OGP64/sbin/
|
||||
OGP64/usr/
|
||||
|
||||
# Do NOT ignore these important files
|
||||
!Installer/PortableGit-2.54.0-64-bit.7z.exe
|
||||
!
|
||||
250
Installer/Configure-GSP-WindowsAgent.ps1
Normal file
250
Installer/Configure-GSP-WindowsAgent.ps1
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
# GSP Windows Agent Configuration Script
|
||||
# This script processes Cfg/*.default files and creates proper Perl configs
|
||||
|
||||
param(
|
||||
[string]$AgentPath = "C:\GSP\Agent",
|
||||
[string]$InstallPath = "C:\GSP"
|
||||
)
|
||||
|
||||
$Script:CfgDir = Join-Path $AgentPath "OGP64\OGP\Cfg"
|
||||
$Script:LogsDir = Join-Path $InstallPath "logs"
|
||||
$Script:ConfigLogFile = Join-Path $Script:LogsDir "config.log"
|
||||
|
||||
function Log-Message {
|
||||
param([string]$Message, [switch]$IsError = $false)
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logLine = "[$timestamp] $Message"
|
||||
|
||||
if ($IsError) {
|
||||
Write-Host $logLine -ForegroundColor Red
|
||||
} else {
|
||||
Write-Host $logLine
|
||||
}
|
||||
|
||||
Add-Content -Path $Script:ConfigLogFile -Value $logLine -Force
|
||||
}
|
||||
|
||||
function Read-ConfigDefaults {
|
||||
param([string]$FilePath)
|
||||
|
||||
if (-not (Test-Path $FilePath)) {
|
||||
return @{}
|
||||
}
|
||||
|
||||
$content = Get-Content $FilePath -Raw
|
||||
$config = @{}
|
||||
|
||||
# Parse Perl hash syntax: key => 'value',
|
||||
if ($content -match '%Cfg::\w+\s*=\s*\((.*)\);') {
|
||||
$hashContent = $matches[1]
|
||||
|
||||
# Match key => 'value' or key => value patterns
|
||||
$regex = "(\w+)\s*=>\s*['\"]?([^'\"]*)['\"]?(?:,|$)"
|
||||
[regex]::Matches($hashContent, $regex) | ForEach-Object {
|
||||
$key = $_.Groups[1].Value
|
||||
$value = $_.Groups[2].Value.Trim()
|
||||
$config[$key] = $value
|
||||
}
|
||||
}
|
||||
|
||||
return $config
|
||||
}
|
||||
|
||||
function Ask-ConfigValue {
|
||||
param(
|
||||
[string]$Key,
|
||||
[string]$DefaultValue,
|
||||
[string]$Description = ""
|
||||
)
|
||||
|
||||
$prompt = $Key
|
||||
if ($DefaultValue) {
|
||||
$prompt += " [default: $DefaultValue]"
|
||||
}
|
||||
$prompt += ": "
|
||||
|
||||
if ($Description) {
|
||||
Write-Host $Description -ForegroundColor Cyan
|
||||
}
|
||||
|
||||
$value = Read-Host $prompt
|
||||
|
||||
if ([string]::IsNullOrEmpty($value)) {
|
||||
return $DefaultValue
|
||||
}
|
||||
|
||||
return $value
|
||||
}
|
||||
|
||||
function Configure-ConfigPm {
|
||||
Log-Message "Configuring Config.pm..."
|
||||
|
||||
$defaultFile = Join-Path $Script:CfgDir "Config.pm.default"
|
||||
$configFile = Join-Path $Script:CfgDir "Config.pm"
|
||||
|
||||
if (-not (Test-Path $defaultFile)) {
|
||||
Log-Message "ERROR: Config.pm.default not found" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
# If config already exists, preserve it
|
||||
if (Test-Path $configFile) {
|
||||
Log-Message "Config.pm already exists, preserving it"
|
||||
return $true
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== Configuring Config.pm ===" -ForegroundColor Green
|
||||
Write-Host "This file contains critical settings for agent communication"
|
||||
Write-Host ""
|
||||
|
||||
# Read defaults
|
||||
$defaults = Read-ConfigDefaults $defaultFile
|
||||
|
||||
# Ask for key values
|
||||
$configs = @{}
|
||||
$configs["listen_ip"] = Ask-ConfigValue "listen_ip" ($defaults["listen_ip"] ?? "0.0.0.0") "Agent listen IP address (0.0.0.0 = all interfaces)"
|
||||
$configs["listen_port"] = Ask-ConfigValue "listen_port" ($defaults["listen_port"] ?? "12679") "Agent listen port"
|
||||
$configs["key"] = Ask-ConfigValue "key" ($defaults["key"] ?? "CHANGE_ME_PANEL_AGENT_KEY") "Encryption key (must match Panel configuration)"
|
||||
|
||||
# Optional settings
|
||||
$configs["logfile"] = "/OGP/ogp_agent.log"
|
||||
$configs["version"] = $defaults["version"] ?? "v1.4"
|
||||
$configs["steam_license"] = $defaults["steam_license"] ?? "Accept"
|
||||
$configs["sudo_password"] = ""
|
||||
$configs["web_admin_api_key"] = ""
|
||||
$configs["web_api_url"] = ""
|
||||
$configs["steam_dl_limit"] = $defaults["steam_dl_limit"] ?? "0"
|
||||
|
||||
# Write config file
|
||||
try {
|
||||
$content = "`%Cfg::Config = (`n"
|
||||
foreach ($key in $configs.Keys | Sort-Object) {
|
||||
$value = $configs[$key]
|
||||
if ($key -eq "key") {
|
||||
# Key is especially important - always show with quotes
|
||||
$content += "`t$key => '$value',`n"
|
||||
} else {
|
||||
$content += "`t$key => '$value',`n"
|
||||
}
|
||||
}
|
||||
$content += ");`n`n1;`n"
|
||||
|
||||
Set-Content -Path $configFile -Value $content -Encoding UTF8
|
||||
Log-Message "Config.pm created successfully"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR creating Config.pm: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Configure-PreferencesPm {
|
||||
Log-Message "Configuring Preferences.pm..."
|
||||
|
||||
$defaultFile = Join-Path $Script:CfgDir "Preferences.pm.default"
|
||||
$configFile = Join-Path $Script:CfgDir "Preferences.pm"
|
||||
|
||||
if (-not (Test-Path $defaultFile)) {
|
||||
Log-Message "WARNING: Preferences.pm.default not found"
|
||||
return $false
|
||||
}
|
||||
|
||||
# If preferences already exist, preserve them
|
||||
if (Test-Path $configFile) {
|
||||
Log-Message "Preferences.pm already exists, preserving it"
|
||||
return $true
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== Configuring Preferences.pm ===" -ForegroundColor Green
|
||||
Write-Host "This file contains optional agent preferences"
|
||||
Write-Host ""
|
||||
|
||||
try {
|
||||
Copy-Item -Path $defaultFile -Destination $configFile -Force
|
||||
Log-Message "Preferences.pm created from defaults"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR creating Preferences.pm: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Configure-BashPrefs {
|
||||
Log-Message "Configuring bash_prefs.cfg..."
|
||||
|
||||
$defaultFile = Join-Path $Script:CfgDir "bash_prefs.cfg.default"
|
||||
$configFile = Join-Path $Script:CfgDir "bash_prefs.cfg"
|
||||
|
||||
if (-not (Test-Path $defaultFile)) {
|
||||
Log-Message "WARNING: bash_prefs.cfg.default not found"
|
||||
return $false
|
||||
}
|
||||
|
||||
# If bash prefs already exist, preserve them
|
||||
if (Test-Path $configFile) {
|
||||
Log-Message "bash_prefs.cfg already exists, preserving it"
|
||||
return $true
|
||||
}
|
||||
|
||||
try {
|
||||
Copy-Item -Path $defaultFile -Destination $configFile -Force
|
||||
Log-Message "bash_prefs.cfg created from defaults"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR creating bash_prefs.cfg: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Main {
|
||||
Log-Message "========================================="
|
||||
Log-Message "GSP Windows Agent Configuration"
|
||||
Log-Message "========================================="
|
||||
Log-Message "Agent Path: $AgentPath"
|
||||
Log-Message "Config Directory: $Script:CfgDir"
|
||||
Log-Message ""
|
||||
|
||||
if (-not (Test-Path $Script:CfgDir)) {
|
||||
Log-Message "ERROR: Configuration directory not found: $Script:CfgDir" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check for necessary permissions
|
||||
try {
|
||||
$testFile = Join-Path $Script:CfgDir ".write_test"
|
||||
"test" | Out-File $testFile
|
||||
Remove-Item $testFile -Force
|
||||
} catch {
|
||||
Log-Message "ERROR: No write permission to config directory" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Configure each file
|
||||
$configResults = @{
|
||||
"Config.pm" = Configure-ConfigPm
|
||||
"Preferences.pm" = Configure-PreferencesPm
|
||||
"bash_prefs.cfg" = Configure-BashPrefs
|
||||
}
|
||||
|
||||
# Summary
|
||||
Log-Message ""
|
||||
Log-Message "========================================="
|
||||
Log-Message "Configuration Complete"
|
||||
Log-Message "========================================="
|
||||
|
||||
$successCount = ($configResults.Values | Where-Object { $_ -eq $true }).Count
|
||||
Write-Host "Successfully configured: $successCount/$($configResults.Count) files"
|
||||
|
||||
foreach ($file in $configResults.Keys) {
|
||||
$status = $configResults[$file] ? "✓" : "✗"
|
||||
Write-Host " $status $file"
|
||||
}
|
||||
|
||||
Log-Message ""
|
||||
Log-Message "Configuration log: $Script:ConfigLogFile"
|
||||
}
|
||||
|
||||
Main
|
||||
466
Installer/Install-GSP-WindowsAgent.ps1
Normal file
466
Installer/Install-GSP-WindowsAgent.ps1
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
# GSP Windows Agent Installer - PowerShell Script
|
||||
# This script handles the complete installation of GSP Windows Agent
|
||||
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
param(
|
||||
[string]$InstallPath = "C:\GSP",
|
||||
[string]$GitRepoUrl = "https://github.com/OpenGamePanel/OGP-Agent-Windows.git",
|
||||
[string]$GitBranch = "master",
|
||||
[string]$PortableGitPath,
|
||||
[switch]$SkipGitExtraction = $false
|
||||
)
|
||||
|
||||
# Get the directory where this script is located
|
||||
$Script:ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
if ([string]::IsNullOrEmpty($PortableGitPath)) {
|
||||
$PortableGitPath = Join-Path $Script:ScriptDir "PortableGit-2.54.0-64-bit.7z.exe"
|
||||
}
|
||||
|
||||
$Script:AgentDir = Join-Path $InstallPath "Agent"
|
||||
$Script:GitDir = Join-Path $InstallPath "tools\PortableGit"
|
||||
$Script:HomeDir = Join-Path $InstallPath "home"
|
||||
$Script:BackupDir = Join-Path $InstallPath "backups\agent"
|
||||
$Script:LogsDir = Join-Path $InstallPath "logs"
|
||||
$Script:InstallLogFile = Join-Path $Script:LogsDir "install.log"
|
||||
|
||||
# Initialize log
|
||||
if (-not (Test-Path $Script:LogsDir)) {
|
||||
New-Item -ItemType Directory -Path $Script:LogsDir -Force | Out-Null
|
||||
}
|
||||
|
||||
function Log-Message {
|
||||
param([string]$Message, [switch]$IsError = $false)
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logLine = "[$timestamp] $Message"
|
||||
|
||||
if ($IsError) {
|
||||
Write-Host $logLine -ForegroundColor Red
|
||||
} else {
|
||||
Write-Host $logLine
|
||||
}
|
||||
|
||||
Add-Content -Path $Script:InstallLogFile -Value $logLine -Force
|
||||
}
|
||||
|
||||
function Test-Administrator {
|
||||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
||||
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
function Create-DirectoryStructure {
|
||||
Log-Message "Creating directory structure at $InstallPath..."
|
||||
|
||||
try {
|
||||
$dirs = @(
|
||||
$InstallPath,
|
||||
(Join-Path $InstallPath "tools"),
|
||||
(Join-Path $InstallPath "backups"),
|
||||
$Script:BackupDir,
|
||||
$Script:HomeDir,
|
||||
$Script:LogsDir
|
||||
)
|
||||
|
||||
foreach ($dir in $dirs) {
|
||||
if (-not (Test-Path $dir)) {
|
||||
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
||||
Log-Message " Created: $dir"
|
||||
} else {
|
||||
Log-Message " Already exists: $dir"
|
||||
}
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR creating directories: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Extract-PortableGit {
|
||||
Log-Message "Extracting Portable Git..."
|
||||
|
||||
if (-not (Test-Path $PortableGitPath)) {
|
||||
Log-Message "ERROR: Portable Git installer not found at: $PortableGitPath" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
if ($SkipGitExtraction) {
|
||||
Log-Message "Skipping Portable Git extraction (--SkipGitExtraction flag set)"
|
||||
return $true
|
||||
}
|
||||
|
||||
try {
|
||||
# Remove existing extraction if present
|
||||
if (Test-Path $Script:GitDir) {
|
||||
Log-Message "Removing existing PortableGit directory..."
|
||||
Remove-Item -Path $Script:GitDir -Recurse -Force
|
||||
}
|
||||
|
||||
# Create parent directory for extraction
|
||||
New-Item -ItemType Directory -Path (Split-Path $Script:GitDir) -Force | Out-Null
|
||||
|
||||
# Extract the 7z archive
|
||||
Log-Message "Running 7z extraction: $PortableGitPath"
|
||||
Log-Message "Extracting to: $Script:GitDir"
|
||||
|
||||
$extractProcess = Start-Process -FilePath $PortableGitPath `
|
||||
-ArgumentList "-o`"$Script:GitDir`" -y" `
|
||||
-Wait -PassThru -NoNewWindow
|
||||
|
||||
if ($extractProcess.ExitCode -ne 0) {
|
||||
Log-Message "ERROR: 7z extraction failed with exit code: $($extractProcess.ExitCode)" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
# Verify git.exe exists
|
||||
$gitExe = Join-Path $Script:GitDir "cmd\git.exe"
|
||||
if (-not (Test-Path $gitExe)) {
|
||||
Log-Message "ERROR: git.exe not found after extraction at: $gitExe" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
Log-Message "Portable Git extracted successfully"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR extracting Portable Git: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Backup-ExistingAgent {
|
||||
Log-Message "Checking for existing agent installation..."
|
||||
|
||||
if (-not (Test-Path $Script:AgentDir)) {
|
||||
Log-Message "No existing agent found"
|
||||
return $true
|
||||
}
|
||||
|
||||
# Check if it's a git-managed installation
|
||||
$gitDir = Join-Path $Script:AgentDir ".git"
|
||||
if (Test-Path $gitDir) {
|
||||
Log-Message "Found existing Git-managed installation"
|
||||
Log-Message "Offering update/reconfigure instead of reinstall"
|
||||
|
||||
$response = Read-Host "Updates available. Do you want to update? (Y/N)"
|
||||
if ($response -eq "Y" -or $response -eq "y") {
|
||||
Log-Message "Proceding with update instead of fresh install"
|
||||
# For now, we'll continue with update logic
|
||||
return $true
|
||||
} else {
|
||||
Log-Message "User cancelled update"
|
||||
return $false
|
||||
}
|
||||
} else {
|
||||
# Backup old manual installation
|
||||
$backupName = "manual-install-backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
||||
$backupPath = Join-Path $Script:BackupDir $backupName
|
||||
|
||||
Log-Message "Backing up existing manual installation..."
|
||||
Log-Message "Backup destination: $backupPath"
|
||||
|
||||
try {
|
||||
Copy-Item -Path $Script:AgentDir -Destination $backupPath -Recurse -Force
|
||||
Log-Message "Backup completed successfully"
|
||||
|
||||
# Preserve specific folders from old installation
|
||||
$preserveFolders = @("Cfg", "steamcmd", "screenlogs", "startups", "tmp", "shared")
|
||||
Log-Message "Marked folders for preservation after clone: $($preserveFolders -join ', ')"
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR creating backup: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Clone-Repository {
|
||||
Log-Message "Cloning Windows Agent repository..."
|
||||
|
||||
$gitExe = Join-Path $Script:GitDir "cmd\git.exe"
|
||||
if (-not (Test-Path $gitExe)) {
|
||||
Log-Message "ERROR: git.exe not found at: $gitExe" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
# Preserve existing folders if agent directory exists
|
||||
$preservedFolders = @{}
|
||||
$preserveFolders = @("Cfg", "steamcmd", "screenlogs", "startups", "tmp", "shared")
|
||||
|
||||
if (Test-Path $Script:AgentDir) {
|
||||
foreach ($folder in $preserveFolders) {
|
||||
$folderPath = Join-Path $Script:AgentDir $folder
|
||||
if (Test-Path $folderPath) {
|
||||
$tempPath = Join-Path $env:TEMP "gsp_preserve_$folder"
|
||||
Log-Message "Preserving existing folder: $folder"
|
||||
Copy-Item -Path $folderPath -Destination $tempPath -Recurse -Force
|
||||
$preservedFolders[$folder] = $tempPath
|
||||
}
|
||||
}
|
||||
|
||||
# Remove old directory to clone fresh
|
||||
Log-Message "Removing old agent directory for fresh clone..."
|
||||
Remove-Item -Path $Script:AgentDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
try {
|
||||
Log-Message "Cloning from: $GitRepoUrl (branch: $GitBranch)"
|
||||
|
||||
$cloneProcess = Start-Process -FilePath $gitExe `
|
||||
-ArgumentList "clone", "--branch", $GitBranch, $GitRepoUrl, $Script:AgentDir `
|
||||
-Wait -PassThru -NoNewWindow -WorkingDirectory $InstallPath
|
||||
|
||||
if ($cloneProcess.ExitCode -ne 0) {
|
||||
Log-Message "ERROR: Git clone failed with exit code: $($cloneProcess.ExitCode)" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
Log-Message "Repository cloned successfully"
|
||||
|
||||
# Restore preserved folders
|
||||
foreach ($folder in $preservedFolders.Keys) {
|
||||
$tempPath = $preservedFolders[$folder]
|
||||
$targetPath = Join-Path $Script:AgentDir $folder
|
||||
|
||||
Log-Message "Restoring preserved folder: $folder"
|
||||
if (Test-Path $targetPath) {
|
||||
Remove-Item -Path $targetPath -Recurse -Force
|
||||
}
|
||||
Copy-Item -Path $tempPath -Destination $targetPath -Recurse -Force
|
||||
Remove-Item -Path $tempPath -Recurse -Force
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR cloning repository: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Create-RequiredRuntimeFolders {
|
||||
Log-Message "Creating runtime folders in agent directory..."
|
||||
|
||||
$runtimeFolders = @(
|
||||
"runtime_status",
|
||||
"screenlogs",
|
||||
"startups",
|
||||
"tmp",
|
||||
"shared"
|
||||
)
|
||||
|
||||
try {
|
||||
foreach ($folder in $runtimeFolders) {
|
||||
$folderPath = Join-Path $Script:AgentDir $folder
|
||||
if (-not (Test-Path $folderPath)) {
|
||||
New-Item -ItemType Directory -Path $folderPath -Force | Out-Null
|
||||
Log-Message " Created: $folder"
|
||||
}
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR creating runtime folders: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Configure-Agent {
|
||||
Log-Message "Configuring agent..."
|
||||
|
||||
try {
|
||||
# Call the configuration script if it exists
|
||||
$configScript = Join-Path $Script:ScriptDir "Configure-GSP-WindowsAgent.ps1"
|
||||
if (Test-Path $configScript) {
|
||||
Log-Message "Running configuration script..."
|
||||
& $configScript -AgentPath $Script:AgentDir -InstallPath $InstallPath
|
||||
} else {
|
||||
Log-Message "WARNING: Configuration script not found, skipping configuration"
|
||||
Log-Message "You can run configuration manually later with: Configure-GSP-WindowsAgent.ps1"
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR during configuration: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Create-ScheduledTask {
|
||||
Log-Message "Creating Windows Task Scheduler entry..."
|
||||
|
||||
try {
|
||||
# Path to the agent start script in the cloned repo
|
||||
$agentStartScript = Join-Path $Script:AgentDir "OGP64\agent_start.bat"
|
||||
|
||||
if (-not (Test-Path $agentStartScript)) {
|
||||
Log-Message "WARNING: agent_start.bat not found at expected location"
|
||||
Log-Message "Task creation skipped - you may need to create the task manually"
|
||||
return $true
|
||||
}
|
||||
|
||||
# Remove existing task if present
|
||||
try {
|
||||
Unregister-ScheduledTask -TaskName "GSP Windows Agent" -Confirm:$false -ErrorAction SilentlyContinue
|
||||
Log-Message "Removed existing task"
|
||||
} catch {
|
||||
# Task doesn't exist or couldn't be removed, continue
|
||||
}
|
||||
|
||||
# Create task action
|
||||
$action = New-ScheduledTaskAction `
|
||||
-Execute $agentStartScript `
|
||||
-WorkingDirectory (Split-Path $agentStartScript)
|
||||
|
||||
# Create task trigger at system startup
|
||||
$trigger = New-ScheduledTaskTrigger -AtStartup
|
||||
|
||||
# Create task settings
|
||||
$settings = New-ScheduledTaskSettingsSet `
|
||||
-AllowStartIfOnBatteries `
|
||||
-DontStopIfGoingOnBatteries `
|
||||
-Compatibility Win7
|
||||
|
||||
# Create and register the task
|
||||
$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
|
||||
|
||||
$task = New-ScheduledTask `
|
||||
-Action $action `
|
||||
-Trigger $trigger `
|
||||
-Principal $principal `
|
||||
-Settings $settings `
|
||||
-Description "GSP Windows Game Server Agent - Auto-start at system boot"
|
||||
|
||||
Register-ScheduledTask -TaskName "GSP Windows Agent" -InputObject $task | Out-Null
|
||||
|
||||
Log-Message "Scheduled task created successfully"
|
||||
Log-Message "Task name: GSP Windows Agent"
|
||||
Log-Message "Trigger: At system startup"
|
||||
Log-Message "Privileges: System (highest)"
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR creating scheduled task: $_" -IsError $true
|
||||
Log-Message "You may need to create the task manually or run with elevated privileges"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Start-Agent {
|
||||
Log-Message "Starting agent..."
|
||||
|
||||
try {
|
||||
$agentStartScript = Join-Path $Script:AgentDir "OGP64\agent_start.bat"
|
||||
|
||||
if (-not (Test-Path $agentStartScript)) {
|
||||
Log-Message "WARNING: agent_start.bat not found"
|
||||
return $false
|
||||
}
|
||||
|
||||
Log-Message "Agent start script located at: $agentStartScript"
|
||||
Log-Message "To start the agent manually, run: $agentStartScript"
|
||||
|
||||
# Note: We don't auto-start the agent here because it needs to run at system startup
|
||||
# via the scheduled task, which handles Cygwin environment setup properly
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR starting agent: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Test-AdminPrivileges {
|
||||
if (-not (Test-Administrator)) {
|
||||
Log-Message "ERROR: This script must be run as Administrator" -IsError $true
|
||||
Log-Message "Please run this script with Administrator privileges"
|
||||
return $false
|
||||
}
|
||||
Log-Message "Administrator privileges verified"
|
||||
return $true
|
||||
}
|
||||
|
||||
# Main installation flow
|
||||
function Main {
|
||||
Log-Message "========================================="
|
||||
Log-Message "GSP Windows Agent Installation"
|
||||
Log-Message "========================================="
|
||||
Log-Message "Install Path: $InstallPath"
|
||||
Log-Message "Git Repository: $GitRepoUrl"
|
||||
Log-Message "Git Branch: $GitBranch"
|
||||
Log-Message ""
|
||||
|
||||
# Check admin
|
||||
if (-not (Test-AdminPrivileges)) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create directory structure
|
||||
if (-not (Create-DirectoryStructure)) {
|
||||
Log-Message "FATAL: Failed to create directory structure" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extract Portable Git
|
||||
if (-not (Extract-PortableGit)) {
|
||||
Log-Message "FATAL: Failed to extract Portable Git" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Backup existing installation if present
|
||||
if (-not (Backup-ExistingAgent)) {
|
||||
Log-Message "Installation cancelled or backup failed" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Clone repository
|
||||
if (-not (Clone-Repository)) {
|
||||
Log-Message "FATAL: Failed to clone repository" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create runtime folders
|
||||
if (-not (Create-RequiredRuntimeFolders)) {
|
||||
Log-Message "WARNING: Failed to create some runtime folders" -IsError $true
|
||||
# Don't exit - these may already exist
|
||||
}
|
||||
|
||||
# Configure agent
|
||||
if (-not (Configure-Agent)) {
|
||||
Log-Message "WARNING: Configuration had errors" -IsError $true
|
||||
# Don't exit - user can configure manually
|
||||
}
|
||||
|
||||
# Create scheduled task
|
||||
if (-not (Create-ScheduledTask)) {
|
||||
Log-Message "WARNING: Failed to create scheduled task" -IsError $true
|
||||
# Don't exit - user can create manually
|
||||
}
|
||||
|
||||
# Start the scheduled task
|
||||
try {
|
||||
Start-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue
|
||||
Log-Message "Scheduled task started"
|
||||
} catch {
|
||||
Log-Message "WARNING: Could not start scheduled task immediately - it will start at next boot"
|
||||
}
|
||||
|
||||
Log-Message ""
|
||||
Log-Message "========================================="
|
||||
Log-Message "Installation Complete!"
|
||||
Log-Message "========================================="
|
||||
Log-Message "Install location: $InstallPath"
|
||||
Log-Message "Agent will start at next system boot"
|
||||
Log-Message "Log file: $Script:InstallLogFile"
|
||||
Log-Message ""
|
||||
Log-Message "To update the agent later, run: update.bat"
|
||||
Log-Message "To rollback to a previous version, run: rollback.bat"
|
||||
Log-Message ""
|
||||
|
||||
Read-Host "Press Enter to close this window"
|
||||
}
|
||||
|
||||
# Run main installation
|
||||
Main
|
||||
BIN
Installer/PortableGit-2.54.0-64-bit.7z.exe
Normal file
BIN
Installer/PortableGit-2.54.0-64-bit.7z.exe
Normal file
Binary file not shown.
334
Installer/README-FIRST.txt
Normal file
334
Installer/README-FIRST.txt
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
================================================================================
|
||||
GSP WINDOWS AGENT INSTALLER
|
||||
================================================================================
|
||||
|
||||
This installer package contains everything needed to deploy the GSP Windows
|
||||
Agent on a Windows server. The agent runs game server processes and provides
|
||||
RPC communication with the OGP Panel.
|
||||
|
||||
================================================================================
|
||||
SYSTEM REQUIREMENTS
|
||||
================================================================================
|
||||
|
||||
- Windows Server 2016 or later (or Windows 10/11 for testing)
|
||||
- Administrator privileges (required to create C:\GSP and Task Scheduler entry)
|
||||
- Network connectivity to Panel server
|
||||
- Sufficient disk space for game server installations
|
||||
|
||||
================================================================================
|
||||
BEFORE YOU START
|
||||
================================================================================
|
||||
|
||||
1. Unzip this installer package to any folder
|
||||
2. You may need to edit the installation path (default: C:\GSP)
|
||||
3. You MUST have the Panel's encryption key (shared key for agent communication)
|
||||
|
||||
================================================================================
|
||||
INSTALLATION STEPS
|
||||
================================================================================
|
||||
|
||||
1. Right-click on install.bat
|
||||
2. Select "Run as Administrator"
|
||||
3. Click "Yes" when prompted for Administrator permission
|
||||
4. Answer the configuration questions:
|
||||
- Installation path (default: C:\GSP)
|
||||
- Git repository URL (can use default)
|
||||
- Git branch (default: master)
|
||||
- Agent listen IP (default: 0.0.0.0)
|
||||
- Agent listen port (default: 12679)
|
||||
- Encryption key (MUST match Panel configuration)
|
||||
|
||||
The installer will:
|
||||
- Create C:\GSP directory structure
|
||||
- Extract Portable Git (included in this package)
|
||||
- Clone the Windows Agent repository
|
||||
- Create configuration files from templates
|
||||
- Set up a Windows Task Scheduler entry
|
||||
- Configure the agent to auto-start at system boot
|
||||
|
||||
================================================================================
|
||||
INSTALLATION DETAILS
|
||||
================================================================================
|
||||
|
||||
Install Layout
|
||||
--------------
|
||||
After installation, you'll have:
|
||||
|
||||
C:\GSP\
|
||||
Agent\ - Git clone of Windows Agent repository
|
||||
.git\ - Git metadata (allows updates)
|
||||
OGP64\ - Bundled Cygwin runtime
|
||||
Cfg\ - Configuration files
|
||||
docs\ - Documentation
|
||||
home\ - Game server files directory (never deleted by installer)
|
||||
tools\
|
||||
PortableGit\ - Bundled Git (for updates/rollback)
|
||||
backups\
|
||||
agent\ - Automatic backups from updates
|
||||
logs\ - Installation, update, and rollback logs
|
||||
|
||||
First Run
|
||||
---------
|
||||
The agent will:
|
||||
1. Start automatically with Windows system startup
|
||||
2. Run under SYSTEM account (highest privileges)
|
||||
3. Execute startup scripts with Cygwin environment
|
||||
4. Listen on the configured IP and port
|
||||
5. Write logs to: C:\GSP\Agent\OGP64\OGP\ogp_agent.log
|
||||
|
||||
Manual Start
|
||||
------------
|
||||
If you need to start the agent manually:
|
||||
1. Open Command Prompt as Administrator
|
||||
2. Run: C:\GSP\Agent\OGP64\agent_start.bat
|
||||
|
||||
Manual Stop
|
||||
-----------
|
||||
To stop the agent:
|
||||
1. Open Command Prompt as Administrator
|
||||
2. Run: C:\GSP\Agent\OGP64\agent_stop.bat
|
||||
|
||||
================================================================================
|
||||
AFTER INSTALLATION
|
||||
================================================================================
|
||||
|
||||
Configure Panel
|
||||
---------------
|
||||
1. Log in to the Panel as admin
|
||||
2. Add the Windows Agent:
|
||||
- IP/Hostname: (the Windows server's IP)
|
||||
- Port: 12679 (or your configured port)
|
||||
- Encryption Key: (use the same key you entered during install)
|
||||
- Shared Key: (same as encryption key)
|
||||
|
||||
Verify Agent Connection
|
||||
-----------------------
|
||||
1. From the Panel, check the agent's status
|
||||
2. Run a test command from the Panel
|
||||
3. Check C:\GSP\Agent\OGP64\OGP\ogp_agent.log for debug output
|
||||
|
||||
================================================================================
|
||||
UPDATING THE AGENT
|
||||
================================================================================
|
||||
|
||||
The bundled Portable Git allows easy updates without requiring system Git.
|
||||
|
||||
To Update
|
||||
---------
|
||||
1. Right-click update.bat (in the original Installer folder)
|
||||
2. Select "Run as Administrator"
|
||||
3. The updater will:
|
||||
- Stop the running agent
|
||||
- Back up the current version
|
||||
- Fetch updates from Git
|
||||
- Restore your configuration and game files
|
||||
- Restart the agent
|
||||
|
||||
Updates preserve:
|
||||
- C:\GSP\home (all game server files)
|
||||
- C:\GSP\Agent\Cfg (agent configuration)
|
||||
- C:\GSP\Agent\screenlogs (server logs)
|
||||
- C:\GSP\Agent\startups (startup flags)
|
||||
- C:\GSP\Agent\OGP64\steamcmd (SteamCMD files)
|
||||
|
||||
================================================================================
|
||||
ROLLING BACK
|
||||
================================================================================
|
||||
|
||||
If an update causes problems, you can restore a previous version.
|
||||
|
||||
To Rollback
|
||||
-----------
|
||||
1. Right-click rollback.bat (in the original Installer folder)
|
||||
2. Select "Run as Administrator"
|
||||
3. The rollback script will:
|
||||
- List available backups (with timestamps)
|
||||
- Let you select which version to restore
|
||||
- Optionally preserve your current configuration
|
||||
- Restore the previous version
|
||||
- Restart the agent
|
||||
|
||||
Available Backups
|
||||
-----------------
|
||||
Backups are stored in: C:\GSP\backups\agent\
|
||||
|
||||
Each backup includes:
|
||||
- Agent binaries and scripts
|
||||
- Perl modules
|
||||
- Cygwin runtime
|
||||
- But NOT game server files or logs
|
||||
|
||||
================================================================================
|
||||
PERMANENT REMOVAL
|
||||
================================================================================
|
||||
|
||||
To Remove Only the Scheduled Task
|
||||
-----------------------------------
|
||||
1. Right-click uninstall-task.bat (in the original Installer folder)
|
||||
2. Select "Run as Administrator"
|
||||
3. This removes only the Task Scheduler entry
|
||||
4. The agent directory and game servers remain intact
|
||||
5. You can manually start the agent later with agent_start.bat
|
||||
|
||||
Full Removal (if needed)
|
||||
------------------------
|
||||
To completely remove the agent:
|
||||
1. Run uninstall-task.bat first
|
||||
2. Manually delete C:\GSP\Agent
|
||||
3. Leave C:\GSP\home (contains your game servers)
|
||||
4. Leave C:\GSP\backups (for recovery)
|
||||
|
||||
WARNING: Do NOT delete C:\GSP\home - it contains your game server installations!
|
||||
|
||||
================================================================================
|
||||
TROUBLESHOOTING
|
||||
================================================================================
|
||||
|
||||
Agent Won't Start
|
||||
-----------------
|
||||
1. Check the log file:
|
||||
C:\GSP\Agent\OGP64\OGP\ogp_agent.log
|
||||
|
||||
2. Try manual start:
|
||||
Right-click C:\GSP\Agent\OGP64\agent_start.bat
|
||||
Select "Run as Administrator"
|
||||
|
||||
3. Verify configuration:
|
||||
Check C:\GSP\Agent\OGP64\OGP\Cfg\Config.pm for encryption key
|
||||
|
||||
4. Check Windows Event Viewer:
|
||||
Windows Logs > System (for Task Scheduler errors)
|
||||
|
||||
Panel Can't Connect
|
||||
-------------------
|
||||
1. Verify the agent is running:
|
||||
tasklist | findstr /i bash
|
||||
|
||||
2. Check Windows Firewall:
|
||||
Allow C:\GSP\Agent\OGP64\bin\bash.exe through firewall
|
||||
Allow TCP port 12679 (or configured port) inbound
|
||||
|
||||
3. Verify Panel encryption key matches:
|
||||
Must match exactly in both Panel and C:\GSP\Agent\OGP64\OGP\Cfg\Config.pm
|
||||
|
||||
4. Check agent log:
|
||||
C:\GSP\Agent\OGP64\OGP\ogp_agent.log
|
||||
|
||||
Installation Failed
|
||||
-------------------
|
||||
1. Check the installation log:
|
||||
C:\GSP\logs\install.log
|
||||
|
||||
2. Verify permissions:
|
||||
Run as Administrator (right-click, "Run as Administrator")
|
||||
|
||||
3. Check free disk space:
|
||||
At least 500MB required for Portable Git and agent
|
||||
|
||||
4. Check Portable Git extraction:
|
||||
Should be at: C:\GSP\tools\PortableGit\cmd\git.exe
|
||||
|
||||
================================================================================
|
||||
ADVANCED TOPICS
|
||||
================================================================================
|
||||
|
||||
Configuration Files (reference only)
|
||||
------------------------------------
|
||||
Important Agent configuration files are in:
|
||||
C:\GSP\Agent\OGP64\OGP\Cfg\
|
||||
|
||||
Main files:
|
||||
Config.pm - Encryption key, listen port/IP
|
||||
Preferences.pm - Optional preferences
|
||||
bash_prefs.cfg - Bash shell preferences
|
||||
|
||||
Do NOT edit these manually unless you understand Perl syntax!
|
||||
|
||||
Manual Git Operations
|
||||
---------------------
|
||||
You can use Portable Git directly:
|
||||
C:\GSP\tools\PortableGit\cmd\git.exe [command]
|
||||
|
||||
Example - Check current branch:
|
||||
cd C:\GSP\Agent
|
||||
C:\GSP\tools\PortableGit\cmd\git.exe status
|
||||
|
||||
Environmental Variables
|
||||
------------------------
|
||||
The following directories are set by the installer:
|
||||
|
||||
C:\GSP\
|
||||
Agent\ - Windows Agent Git clone
|
||||
home\ - Game servers
|
||||
tools\ - Portable Git
|
||||
backups\ - Automatic backups
|
||||
logs\ - Installation logs
|
||||
|
||||
These locations can be changed by editing install.bat parameters.
|
||||
|
||||
================================================================================
|
||||
SUPPORT & DOCUMENTATION
|
||||
================================================================================
|
||||
|
||||
More Information
|
||||
----------------
|
||||
- Main documentation: C:\GSP\Agent\README.md
|
||||
- Agent guide: C:\GSP\Agent\docs\AGENT_ARCHITECTURE.md
|
||||
- Panel documentation: Check your Panel installation
|
||||
|
||||
Getting Help
|
||||
------------
|
||||
1. Check the relevant log file
|
||||
2. Review documentation in C:\GSP\Agent\docs\
|
||||
3. Check Panel logs on the Panel server
|
||||
4. Verify network connectivity between servers
|
||||
|
||||
================================================================================
|
||||
SECURITY NOTES
|
||||
================================================================================
|
||||
|
||||
1. Encryption Key
|
||||
- The encryption key in Config.pm is critical
|
||||
- Must match exactly on Panel and Agent
|
||||
- Treat this key as a production secret
|
||||
- Do NOT commit Config.pm to public Git repositories
|
||||
|
||||
2. Network Security
|
||||
- Agent runs as SYSTEM (highest Windows privileges)
|
||||
- Restrict network access to Panel server IP only
|
||||
- Use Windows Firewall to limit inbound connections
|
||||
- Consider VPN or internal network isolation
|
||||
|
||||
3. File Permissions
|
||||
- C:\GSP\home must be accessible to all game processes
|
||||
- C:\GSP\Agent must be readable by SYSTEM account
|
||||
- Configure Windows ACLs as needed for your environment
|
||||
|
||||
4. Logging
|
||||
- Agent logs contain diagnostic information
|
||||
- Logs may include command parameters
|
||||
- Rotate logs to manage disk space
|
||||
- Archive logs for audit trails if needed
|
||||
|
||||
================================================================================
|
||||
VERSION INFORMATION
|
||||
================================================================================
|
||||
|
||||
Installer Version: GSP Windows Agent 1.0
|
||||
Release Date: June 2026
|
||||
Portable Git Version: 2.54.0 (64-bit)
|
||||
|
||||
Compatible With:
|
||||
- Windows Server 2016+
|
||||
- Windows 10/11 (for testing)
|
||||
- OGP Panel v1.4+
|
||||
- Linux Agent v1.4+ (for comparison)
|
||||
|
||||
================================================================================
|
||||
|
||||
For more information, see:
|
||||
- Installer folder: README.txt (this file)
|
||||
- Agent repository: C:\GSP\Agent\README.md
|
||||
- Documentation folder: C:\GSP\Agent\docs\
|
||||
|
||||
================================================================================
|
||||
260
Installer/Rollback-GSP-WindowsAgent.ps1
Normal file
260
Installer/Rollback-GSP-WindowsAgent.ps1
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
# GSP Windows Agent Rollback - PowerShell Script
|
||||
# This script lets an admin restore a previous agent version from backup
|
||||
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
param(
|
||||
[string]$InstallPath = "C:\GSP"
|
||||
)
|
||||
|
||||
$Script:AgentDir = Join-Path $InstallPath "Agent"
|
||||
$Script:BackupDir = Join-Path $InstallPath "backups\agent"
|
||||
$Script:LogsDir = Join-Path $InstallPath "logs"
|
||||
$Script:RollbackLogFile = Join-Path $Script:LogsDir "rollback.log"
|
||||
|
||||
function Log-Message {
|
||||
param([string]$Message, [switch]$IsError = $false)
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logLine = "[$timestamp] $Message"
|
||||
|
||||
if ($IsError) {
|
||||
Write-Host $logLine -ForegroundColor Red
|
||||
} else {
|
||||
Write-Host $logLine
|
||||
}
|
||||
|
||||
Add-Content -Path $Script:RollbackLogFile -Value $logLine -Force
|
||||
}
|
||||
|
||||
function Test-Administrator {
|
||||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
||||
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
function List-Backups {
|
||||
Log-Message "Listing available backups..."
|
||||
|
||||
if (-not (Test-Path $Script:BackupDir)) {
|
||||
Write-Host "No backups directory found"
|
||||
return @()
|
||||
}
|
||||
|
||||
$backups = Get-ChildItem -Path $Script:BackupDir -Directory | Sort-Object Name -Descending
|
||||
|
||||
if ($backups.Count -eq 0) {
|
||||
Write-Host "No backups available"
|
||||
return @()
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Available backups:" -ForegroundColor Green
|
||||
|
||||
$backupList = @()
|
||||
$index = 1
|
||||
foreach ($backup in $backups) {
|
||||
$path = $backup.FullName
|
||||
$created = $backup.CreationTime
|
||||
$size = (Get-ChildItem -Path $path -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
|
||||
|
||||
Write-Host " [$index] $($backup.Name) (created: $created, size: $([math]::Round($size, 2)) MB)"
|
||||
$backupList += $backup.FullName
|
||||
$index++
|
||||
}
|
||||
|
||||
return $backupList
|
||||
}
|
||||
|
||||
function Select-Backup {
|
||||
param([array]$BackupList)
|
||||
|
||||
if ($BackupList.Count -eq 0) {
|
||||
Write-Host "ERROR: No backups available"
|
||||
return $null
|
||||
}
|
||||
|
||||
if ($BackupList.Count -eq 1) {
|
||||
Write-Host ""
|
||||
$response = Read-Host "Only one backup available. Restore it? (Y/N)"
|
||||
if ($response -eq "Y" -or $response -eq "y") {
|
||||
return $BackupList[0]
|
||||
} else {
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
$choice = Read-Host "Select backup number (1-$($BackupList.Count)) or 'Q' to quit"
|
||||
|
||||
if ($choice -eq "Q" -or $choice -eq "q") {
|
||||
return $null
|
||||
}
|
||||
|
||||
if ($choice -match '^\d+$' -and [int]$choice -ge 1 -and [int]$choice -le $BackupList.Count) {
|
||||
return $BackupList[[int]$choice - 1]
|
||||
} else {
|
||||
Write-Host "Invalid selection"
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-Agent {
|
||||
Log-Message "Stopping agent..."
|
||||
|
||||
try {
|
||||
Stop-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue
|
||||
Log-Message "Scheduled task stopped"
|
||||
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
Get-Process bash,perl -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
try {
|
||||
Stop-Process -Id $_.Id -Force
|
||||
Log-Message "Killed: $($_.Name) (PID: $($_.Id))"
|
||||
} catch {
|
||||
# Already gone
|
||||
}
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "WARNING stopping agent: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Restore-Backup {
|
||||
param([string]$BackupPath)
|
||||
|
||||
Log-Message "Restoring from backup: $BackupPath"
|
||||
|
||||
try {
|
||||
# Stop agent
|
||||
Stop-Agent
|
||||
|
||||
# Preserve current Cfg if user wants
|
||||
$preserveCfg = $false
|
||||
Write-Host ""
|
||||
$response = Read-Host "Preserve current Cfg folder? (Y/N, default: Y)"
|
||||
if ($response -ne "N" -and $response -ne "n") {
|
||||
$preserveCfg = $true
|
||||
}
|
||||
|
||||
$currentCfg = Join-Path $Script:AgentDir "OGP64\OGP\Cfg"
|
||||
$tempCfg = Join-Path $env:TEMP "gsp_preserve_cfg"
|
||||
|
||||
if ($preserveCfg -and (Test-Path $currentCfg)) {
|
||||
Log-Message "Preserving current Cfg folder"
|
||||
if (Test-Path $tempCfg) {
|
||||
Remove-Item $tempCfg -Recurse -Force
|
||||
}
|
||||
Copy-Item -Path $currentCfg -Destination $tempCfg -Recurse -Force
|
||||
}
|
||||
|
||||
# Remove current installation
|
||||
Log-Message "Removing current agent directory"
|
||||
if (Test-Path $Script:AgentDir) {
|
||||
Remove-Item -Path $Script:AgentDir -Recurse -Force
|
||||
}
|
||||
|
||||
# Restore backup
|
||||
Log-Message "Copying backup to $Script:AgentDir"
|
||||
Copy-Item -Path $BackupPath -Destination $Script:AgentDir -Recurse -Force
|
||||
|
||||
# Restore preserved Cfg
|
||||
if ($preserveCfg -and (Test-Path $tempCfg)) {
|
||||
Log-Message "Restoring preserved Cfg folder"
|
||||
$targetCfg = Join-Path $Script:AgentDir "OGP64\OGP\Cfg"
|
||||
if (Test-Path $targetCfg) {
|
||||
Remove-Item -Path $targetCfg -Recurse -Force
|
||||
}
|
||||
Copy-Item -Path $tempCfg -Destination $targetCfg -Recurse -Force
|
||||
Remove-Item -Path $tempCfg -Recurse -Force
|
||||
}
|
||||
|
||||
# Start the task
|
||||
Log-Message "Starting agent"
|
||||
try {
|
||||
Start-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
Log-Message "WARNING: Could not start scheduled task"
|
||||
}
|
||||
|
||||
Log-Message "Rollback completed successfully"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR during rollback: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Main {
|
||||
Log-Message "========================================="
|
||||
Log-Message "GSP Windows Agent Rollback"
|
||||
Log-Message "========================================="
|
||||
Log-Message "Install Path: $InstallPath"
|
||||
Log-Message "Backup Directory: $Script:BackupDir"
|
||||
Log-Message ""
|
||||
|
||||
if (-not (Test-Administrator)) {
|
||||
Log-Message "ERROR: This script must be run as Administrator" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not (Test-Path $Script:LogsDir)) {
|
||||
New-Item -ItemType Directory -Path $Script:LogsDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# List available backups
|
||||
$backupList = List-Backups
|
||||
|
||||
if ($backupList.Count -eq 0) {
|
||||
Write-Host ""
|
||||
Write-Host "No backups available for rollback" -ForegroundColor Yellow
|
||||
Read-Host "Press Enter to close this window"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Select a backup
|
||||
$selectedBackup = Select-Backup $backupList
|
||||
|
||||
if (-not $selectedBackup) {
|
||||
Write-Host "Rollback cancelled"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Confirm restore
|
||||
Write-Host ""
|
||||
Write-Host "Selected: $selectedBackup" -ForegroundColor Yellow
|
||||
$confirm = Read-Host "Restore this backup? (Y/N)"
|
||||
|
||||
if ($confirm -ne "Y" -and $confirm -ne "y") {
|
||||
Write-Host "Rollback cancelled"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Perform rollback
|
||||
if (Restore-Backup $selectedBackup) {
|
||||
Log-Message ""
|
||||
Log-Message "========================================="
|
||||
Log-Message "Rollback Complete!"
|
||||
Log-Message "========================================="
|
||||
Write-Host ""
|
||||
Write-Host "Rollback successful. Agent has been restored." -ForegroundColor Green
|
||||
Write-Host "Log file: $Script:RollbackLogFile"
|
||||
} else {
|
||||
Log-Message ""
|
||||
Log-Message "========================================="
|
||||
Log-Message "Rollback Failed!"
|
||||
Log-Message "========================================="
|
||||
Write-Host ""
|
||||
Write-Host "Rollback failed. Check the log for details." -ForegroundColor Red
|
||||
Write-Host "Log file: $Script:RollbackLogFile"
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Read-Host "Press Enter to close this window"
|
||||
}
|
||||
|
||||
Main
|
||||
341
Installer/Update-GSP-WindowsAgent.ps1
Normal file
341
Installer/Update-GSP-WindowsAgent.ps1
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
# GSP Windows Agent Updater - PowerShell Script
|
||||
# This script updates an existing Git-managed agent installation
|
||||
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
param(
|
||||
[string]$InstallPath = "C:\GSP",
|
||||
[string]$GitBranch = "master"
|
||||
)
|
||||
|
||||
$Script:AgentDir = Join-Path $InstallPath "Agent"
|
||||
$Script:GitDir = Join-Path $InstallPath "tools\PortableGit"
|
||||
$Script:BackupDir = Join-Path $InstallPath "backups\agent"
|
||||
$Script:LogsDir = Join-Path $InstallPath "logs"
|
||||
$Script:UpdateLogFile = Join-Path $Script:LogsDir "update.log"
|
||||
|
||||
function Log-Message {
|
||||
param([string]$Message, [switch]$IsError = $false)
|
||||
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$logLine = "[$timestamp] $Message"
|
||||
|
||||
if ($IsError) {
|
||||
Write-Host $logLine -ForegroundColor Red
|
||||
} else {
|
||||
Write-Host $logLine
|
||||
}
|
||||
|
||||
Add-Content -Path $Script:UpdateLogFile -Value $logLine -Force
|
||||
}
|
||||
|
||||
function Test-Administrator {
|
||||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
||||
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
function Stop-Agent {
|
||||
Log-Message "Stopping agent..."
|
||||
|
||||
try {
|
||||
# Try to stop the scheduled task
|
||||
Stop-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue
|
||||
Log-Message "Scheduled task stopped"
|
||||
|
||||
# Give it a moment to shut down gracefully
|
||||
Start-Sleep -Seconds 2
|
||||
|
||||
# Kill any remaining bash/perl processes from the agent
|
||||
Get-Process bash,perl -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
try {
|
||||
Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue
|
||||
Log-Message "Killed remaining process: $($_.Name) (PID: $($_.Id))"
|
||||
} catch {
|
||||
# Process may already be gone
|
||||
}
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "WARNING stopping agent: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Backup-Agent {
|
||||
Log-Message "Backing up current agent..."
|
||||
|
||||
try {
|
||||
$backupName = "agent-backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
|
||||
$backupPath = Join-Path $Script:BackupDir $backupName
|
||||
|
||||
Log-Message "Backup destination: $backupPath"
|
||||
|
||||
Copy-Item -Path $Script:AgentDir -Destination $backupPath -Recurse -Force
|
||||
|
||||
Log-Message "Backup completed successfully"
|
||||
return $backupPath
|
||||
} catch {
|
||||
Log-Message "ERROR creating backup: $_" -IsError $true
|
||||
return $null
|
||||
}
|
||||
}
|
||||
|
||||
function Preserve-LocalFolders {
|
||||
Log-Message "Preserving local configuration and runtime folders..."
|
||||
|
||||
$preserved = @{}
|
||||
$preserveFolders = @("Cfg", "steamcmd", "screenlogs", "startups", "tmp", "shared")
|
||||
|
||||
try {
|
||||
foreach ($folder in $preserveFolders) {
|
||||
$folderPath = Join-Path $Script:AgentDir $folder
|
||||
if (Test-Path $folderPath) {
|
||||
$tempPath = Join-Path $env:TEMP "gsp_preserve_$folder"
|
||||
if (Test-Path $tempPath) {
|
||||
Remove-Item $tempPath -Recurse -Force
|
||||
}
|
||||
Copy-Item -Path $folderPath -Destination $tempPath -Recurse -Force
|
||||
$preserved[$folder] = $tempPath
|
||||
Log-Message " Preserved: $folder"
|
||||
}
|
||||
}
|
||||
|
||||
return $preserved
|
||||
} catch {
|
||||
Log-Message "ERROR preserving folders: $_" -IsError $true
|
||||
return @{}
|
||||
}
|
||||
}
|
||||
|
||||
function Update-Repository {
|
||||
Log-Message "Updating repository from Git..."
|
||||
|
||||
try {
|
||||
$gitExe = Join-Path $Script:GitDir "cmd\git.exe"
|
||||
|
||||
if (-not (Test-Path $gitExe)) {
|
||||
Log-Message "ERROR: git.exe not found at: $gitExe" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
if (-not (Test-Path (Join-Path $Script:AgentDir ".git"))) {
|
||||
Log-Message "ERROR: Agent directory is not a Git repository (.git folder not found)" -IsError $true
|
||||
Log-Message "The agent must be installed with the Git-based installer to use this update script"
|
||||
return $false
|
||||
}
|
||||
|
||||
Log-Message "Running git fetch..."
|
||||
$fetchProcess = Start-Process -FilePath $gitExe `
|
||||
-ArgumentList "fetch", "origin" `
|
||||
-Wait -PassThru -NoNewWindow -WorkingDirectory $Script:AgentDir
|
||||
|
||||
if ($fetchProcess.ExitCode -ne 0) {
|
||||
Log-Message "ERROR: git fetch failed with code: $($fetchProcess.ExitCode)" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
Log-Message "Running git reset to $GitBranch..."
|
||||
$resetProcess = Start-Process -FilePath $gitExe `
|
||||
-ArgumentList "reset", "--hard", "origin/$GitBranch" `
|
||||
-Wait -PassThru -NoNewWindow -WorkingDirectory $Script:AgentDir
|
||||
|
||||
if ($resetProcess.ExitCode -ne 0) {
|
||||
Log-Message "ERROR: git reset failed with code: $($resetProcess.ExitCode)" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
Log-Message "Repository updated successfully"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR updating repository: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Restore-LocalFolders {
|
||||
param([hashtable]$PreservedFolders)
|
||||
|
||||
Log-Message "Restoring preserved local folders..."
|
||||
|
||||
try {
|
||||
foreach ($folder in $PreservedFolders.Keys) {
|
||||
$tempPath = $PreservedFolders[$folder]
|
||||
$targetPath = Join-Path $Script:AgentDir $folder
|
||||
|
||||
if (Test-Path $targetPath) {
|
||||
Remove-Item -Path $targetPath -Recurse -Force
|
||||
}
|
||||
|
||||
Copy-Item -Path $tempPath -Destination $targetPath -Recurse -Force
|
||||
Remove-Item -Path $tempPath -Recurse -Force
|
||||
|
||||
Log-Message " Restored: $folder"
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR restoring folders: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Validate-Agent {
|
||||
Log-Message "Validating agent syntax..."
|
||||
|
||||
try {
|
||||
$agentScript = Join-Path $Script:AgentDir "OGP64\OGP\ogp_agent.pl"
|
||||
|
||||
if (-not (Test-Path $agentScript)) {
|
||||
Log-Message "WARNING: ogp_agent.pl not found, skipping syntax check"
|
||||
return $true
|
||||
}
|
||||
|
||||
# Try to run perl syntax check
|
||||
$perlCheck = Start-Process -FilePath "perl.exe" `
|
||||
-ArgumentList "-c", $agentScript `
|
||||
-Wait -PassThru -NoNewWindow -ErrorAction SilentlyContinue
|
||||
|
||||
if ($perlCheck.ExitCode -ne 0) {
|
||||
Log-Message "WARNING: Perl syntax check failed, but update may still be valid" -IsError $true
|
||||
} else {
|
||||
Log-Message "Perl syntax validation passed"
|
||||
}
|
||||
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "WARNING: Could not validate agent syntax: $_" -IsError $true
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
function Start-Agent {
|
||||
Log-Message "Starting agent..."
|
||||
|
||||
try {
|
||||
Start-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue
|
||||
Log-Message "Scheduled task started"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "WARNING: Could not start scheduled task immediately" -IsError $true
|
||||
Log-Message "Agent will start at next system boot"
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
function Rollback-Update {
|
||||
param([string]$BackupPath)
|
||||
|
||||
Log-Message "ROLLING BACK UPDATE..."
|
||||
|
||||
if (-not (Test-Path $BackupPath)) {
|
||||
Log-Message "ERROR: Backup not found, cannot rollback" -IsError $true
|
||||
return $false
|
||||
}
|
||||
|
||||
try {
|
||||
Log-Message "Restoring from backup: $BackupPath"
|
||||
|
||||
# Stop agent first
|
||||
Stop-Agent | Out-Null
|
||||
|
||||
# Remove updated directory
|
||||
if (Test-Path $Script:AgentDir) {
|
||||
Remove-Item -Path $Script:AgentDir -Recurse -Force
|
||||
}
|
||||
|
||||
# Restore backup
|
||||
Copy-Item -Path $BackupPath -Destination $Script:AgentDir -Recurse -Force
|
||||
|
||||
# Restart agent
|
||||
Start-Agent | Out-Null
|
||||
|
||||
Log-Message "Rollback completed successfully"
|
||||
return $true
|
||||
} catch {
|
||||
Log-Message "ERROR during rollback: $_" -IsError $true
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Main {
|
||||
Log-Message "========================================="
|
||||
Log-Message "GSP Windows Agent Update"
|
||||
Log-Message "========================================="
|
||||
Log-Message "Install Path: $InstallPath"
|
||||
Log-Message "Git Branch: $GitBranch"
|
||||
Log-Message ""
|
||||
|
||||
# Check admin
|
||||
if (-not (Test-Administrator)) {
|
||||
Log-Message "ERROR: This script must be run as Administrator" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Verify directories exist
|
||||
if (-not (Test-Path $Script:AgentDir)) {
|
||||
Log-Message "ERROR: Agent not found at: $Script:AgentDir" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not (Test-Path $Script:GitDir)) {
|
||||
Log-Message "ERROR: Portable Git not found at: $Script:GitDir" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Create logs directory if needed
|
||||
if (-not (Test-Path $Script:LogsDir)) {
|
||||
New-Item -ItemType Directory -Path $Script:LogsDir -Force | Out-Null
|
||||
}
|
||||
|
||||
# Stop agent
|
||||
Stop-Agent
|
||||
|
||||
# Create backup
|
||||
$backupPath = Backup-Agent
|
||||
if (-not $backupPath) {
|
||||
Log-Message "FATAL: Could not create backup" -IsError $true
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Preserve local folders
|
||||
$preserved = Preserve-LocalFolders
|
||||
|
||||
# Update from Git
|
||||
if (-not (Update-Repository)) {
|
||||
Log-Message "FATAL: Update failed, rolling back..." -IsError $true
|
||||
Rollback-Update $backupPath | Out-Null
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Restore preserved folders
|
||||
if ($preserved.Count -gt 0) {
|
||||
if (-not (Restore-LocalFolders $preserved)) {
|
||||
Log-Message "WARNING: Failed to restore all folders" -IsError $true
|
||||
Rollback-Update $backupPath | Out-Null
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Validate agent
|
||||
Validate-Agent
|
||||
|
||||
# Start agent
|
||||
Start-Agent
|
||||
|
||||
Log-Message ""
|
||||
Log-Message "========================================="
|
||||
Log-Message "Update Complete!"
|
||||
Log-Message "========================================="
|
||||
Log-Message "Agent has been updated successfully"
|
||||
Log-Message "Backup location: $backupPath"
|
||||
Log-Message "Log file: $Script:UpdateLogFile"
|
||||
Log-Message ""
|
||||
Log-Message "The agent will restart at the next opportunity"
|
||||
Log-Message ""
|
||||
|
||||
Read-Host "Press Enter to close this window"
|
||||
}
|
||||
|
||||
Main
|
||||
37
Installer/install.bat
Normal file
37
Installer/install.bat
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
@echo off
|
||||
REM GSP Windows Agent Installer
|
||||
REM This script checks for Administrator privileges and launches the PowerShell installer
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Check for Administrator privileges
|
||||
net session >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo ERROR: This installer must be run as Administrator.
|
||||
echo.
|
||||
echo Please:
|
||||
echo 1. Right-click this batch file
|
||||
echo 2. Select "Run as Administrator"
|
||||
echo 3. Click "Yes" when prompted
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Get the directory where this batch file is located
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
REM Verify the PowerShell script exists
|
||||
if not exist "%SCRIPT_DIR%Install-GSP-WindowsAgent.ps1" (
|
||||
echo ERROR: Install-GSP-WindowsAgent.ps1 not found in %SCRIPT_DIR%
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Launch the PowerShell installer
|
||||
REM Use -NoProfile to skip profile scripts, -ExecutionPolicy Bypass to allow script execution
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%SCRIPT_DIR%Install-GSP-WindowsAgent.ps1'" %*
|
||||
|
||||
REM Exit with PowerShell's exit code
|
||||
exit /b %ERRORLEVEL%
|
||||
36
Installer/rollback.bat
Normal file
36
Installer/rollback.bat
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
@echo off
|
||||
REM GSP Windows Agent Rollback Script
|
||||
REM This script restores a previous agent version from backup
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Check for Administrator privileges
|
||||
net session >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo ERROR: This rollback script must be run as Administrator.
|
||||
echo.
|
||||
echo Please:
|
||||
echo 1. Right-click this batch file
|
||||
echo 2. Select "Run as Administrator"
|
||||
echo 3. Click "Yes" when prompted
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Get the directory where this batch file is located
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
REM Verify the PowerShell script exists
|
||||
if not exist "%SCRIPT_DIR%Rollback-GSP-WindowsAgent.ps1" (
|
||||
echo ERROR: Rollback-GSP-WindowsAgent.ps1 not found in %SCRIPT_DIR%
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Launch the PowerShell rollback script
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%SCRIPT_DIR%Rollback-GSP-WindowsAgent.ps1'" %*
|
||||
|
||||
REM Exit with PowerShell's exit code
|
||||
exit /b %ERRORLEVEL%
|
||||
61
Installer/uninstall-task.bat
Normal file
61
Installer/uninstall-task.bat
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
@echo off
|
||||
REM GSP Windows Agent - Uninstall Task Scheduler Entry
|
||||
REM This script removes the scheduled task only (does NOT delete C:\GSP\home or any game servers)
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Check for Administrator privileges
|
||||
net session >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo ERROR: This uninstaller must be run as Administrator.
|
||||
echo.
|
||||
echo Please:
|
||||
echo 1. Right-click this batch file
|
||||
echo 2. Select "Run as Administrator"
|
||||
echo 3. Click "Yes" when prompted
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo GSP Windows Agent - Remove Scheduled Task
|
||||
echo.
|
||||
echo WARNING: This will only remove the Task Scheduler entry.
|
||||
echo It will NOT delete C:\GSP\home or any game servers.
|
||||
echo It will NOT delete the agent installation.
|
||||
echo.
|
||||
|
||||
set /p CONFIRM="Are you sure? (Y/N): "
|
||||
|
||||
if /i "%CONFIRM%"=="Y" (
|
||||
echo.
|
||||
echo Stopping scheduled task...
|
||||
taskkill /FI "TASKNAME eq GSP Windows Agent" /F 2>nul
|
||||
|
||||
echo Removing scheduled task...
|
||||
schtasks /delete /tn "GSP Windows Agent" /f
|
||||
|
||||
if %errorlevel% equ 0 (
|
||||
echo.
|
||||
echo SUCCESS: Scheduled task removed.
|
||||
echo.
|
||||
echo Agent installation remains at C:\GSP
|
||||
echo Game servers remain at C:\GSP\home
|
||||
echo Backups remain at C:\GSP\backups
|
||||
echo.
|
||||
echo To manually start the agent, run:
|
||||
echo C:\GSP\Agent\OGP64\agent_start.bat
|
||||
echo.
|
||||
) else (
|
||||
echo.
|
||||
echo ERROR: Failed to remove scheduled task.
|
||||
echo.
|
||||
)
|
||||
) else (
|
||||
echo Uninstall cancelled.
|
||||
)
|
||||
|
||||
echo.
|
||||
pause
|
||||
36
Installer/update.bat
Normal file
36
Installer/update.bat
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
@echo off
|
||||
REM GSP Windows Agent Update Script
|
||||
REM This script updates an existing Git-managed agent installation
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Check for Administrator privileges
|
||||
net session >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo.
|
||||
echo ERROR: This updater must be run as Administrator.
|
||||
echo.
|
||||
echo Please:
|
||||
echo 1. Right-click this batch file
|
||||
echo 2. Select "Run as Administrator"
|
||||
echo 3. Click "Yes" when prompted
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Get the directory where this batch file is located
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
|
||||
REM Verify the PowerShell script exists
|
||||
if not exist "%SCRIPT_DIR%Update-GSP-WindowsAgent.ps1" (
|
||||
echo ERROR: Update-GSP-WindowsAgent.ps1 not found in %SCRIPT_DIR%
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Launch the PowerShell updater
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%SCRIPT_DIR%Update-GSP-WindowsAgent.ps1'" %*
|
||||
|
||||
REM Exit with PowerShell's exit code
|
||||
exit /b %ERRORLEVEL%
|
||||
333
bin/ogp_agent
Normal file
333
bin/ogp_agent
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
#
|
||||
# A wrapper script for the OGP agent perl script.
|
||||
# Performs auto-restarting of the agent on crash. You can
|
||||
# extend this to log crashes and more.
|
||||
#
|
||||
# The ogp_agent script should be at the top level of the agent tree
|
||||
# Make sure we are in that directory since the script assumes this is the case
|
||||
|
||||
#####################
|
||||
# Important VARS #
|
||||
#####################
|
||||
|
||||
AGENTDIR="/OGP"
|
||||
BASH_PREFS_CONF="$AGENTDIR/Cfg/bash_prefs.cfg"
|
||||
REPONAME=OGP-Agent-Windows
|
||||
GitHubUsername="OpenGamePanel"
|
||||
|
||||
#####################
|
||||
# FUNCTIONS #
|
||||
#####################
|
||||
|
||||
setupOGPAndReadBashPrefs(){
|
||||
|
||||
# Find CURL
|
||||
if [ -z "$CURL" -o -z "$UNZIP" ]; then
|
||||
checkDepends
|
||||
fi
|
||||
|
||||
chmod -Rf 770 $AGENTDIR
|
||||
find $AGENTDIR -type f -print | xargs chmod ug=rw
|
||||
if [ -d "$AGENTDIR/steamcmd" ]; then
|
||||
find $AGENTDIR/steamcmd -iname \*.dll -exec chmod +x {} \;
|
||||
find $AGENTDIR/steamcmd -iname \*.exe -exec chmod +x {} \;
|
||||
fi
|
||||
if [ -d "$AGENTDIR/screenlogs" ]; then
|
||||
chmod -Rf ug=rwx $AGENTDIR/screenlogs
|
||||
fi
|
||||
chmod +x $AGENTDIR/ogp_agent.pl &> /dev/null
|
||||
chmod +x $AGENTDIR/agent_conf.sh &> /dev/null
|
||||
chmod +x /usr/bin/ogp_agent &> /dev/null
|
||||
|
||||
# Should we perform an automatic update?
|
||||
if [ -e $BASH_PREFS_CONF ]
|
||||
then
|
||||
source "$BASH_PREFS_CONF"
|
||||
if [ "X$agent_auto_update" == "X1" ]
|
||||
then
|
||||
AUTO_UPDATE="yes"
|
||||
fi
|
||||
|
||||
if [ "X$run_pureftpd" == "X0" ]
|
||||
then
|
||||
RUN_PUREFTPD="no"
|
||||
else
|
||||
RUN_PUREFTPD="yes"
|
||||
fi
|
||||
|
||||
if [ "X$ftp_ip" != "X" ]
|
||||
then
|
||||
FTP_IP="$ftp_ip"
|
||||
else
|
||||
FTP_IP="0.0.0.0"
|
||||
fi
|
||||
|
||||
if [ "X$ftp_port" != "X" ]
|
||||
then
|
||||
FTP_PORT="$ftp_port"
|
||||
else
|
||||
FTP_PORT="21"
|
||||
fi
|
||||
|
||||
if [ "X$ftp_pasv_range" != "X" ]
|
||||
then
|
||||
FTP_PASV_STRING="-p $ftp_pasv_range"
|
||||
else
|
||||
FTP_PASV_STRING=""
|
||||
fi
|
||||
|
||||
# Use custom github update address
|
||||
if [ ! -z "$github_update_username" ]; then
|
||||
if [ -f "$CURL" -a -x "$CURL" ] && [ -f "$UNZIP" -a -x "$UNZIP" ]; then
|
||||
REVISIONTest=`curl -Lks https://github.com/${github_update_username}/${REPONAME}/commits/master.atom | grep -Eo "([a-f0-9]{40})" | head -n 1`
|
||||
if [ ! -z "$REVISIONTest" ]; then
|
||||
GitHubUsername=${github_update_username}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
AUTO_UPDATE="yes"
|
||||
RUN_PUREFTPD="yes"
|
||||
FTP_IP="0.0.0.0"
|
||||
FTP_PORT="21"
|
||||
FTP_PASV_STING=""
|
||||
fi
|
||||
|
||||
if test `id -u` -eq 0; then
|
||||
echo
|
||||
echo
|
||||
echo "************** WARNING ***************"
|
||||
echo "Running the OGP agent as root "
|
||||
echo "is highly discouraged. It is generally"
|
||||
echo "unnecessary to use root privileges to "
|
||||
echo "execute the agent. "
|
||||
echo "**************************************"
|
||||
echo
|
||||
echo
|
||||
timeout=10
|
||||
while test $timeout -gt 0; do
|
||||
echo -n "The agent will continue to launch in $timeout seconds\r"
|
||||
timeout=`expr $timeout - 1`
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
ogpGitCleanup(){
|
||||
echo "Cleaning up..."
|
||||
rm -Rf ${REPONAME}-* &> /dev/null
|
||||
if [ -e "ogp_agent_latest.zip" ]; then
|
||||
rm -f "ogp_agent_latest.zip"
|
||||
fi
|
||||
}
|
||||
|
||||
init() {
|
||||
RESTART="yes"
|
||||
AGENT="$AGENTDIR/ogp_agent.pl"
|
||||
TIMEOUT=10 # time to wait after a crash (in seconds)
|
||||
PID_FILE=""
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
"-pidfile")
|
||||
PID_FILE="$2"
|
||||
PID_FILE_SET=1
|
||||
echo $$ > $PID_FILE
|
||||
shift ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test ! -f "$AGENT"; then
|
||||
echo "ERROR: '$AGENT' not found, exiting"
|
||||
quit 1
|
||||
elif test ! -x "$AGENT"; then
|
||||
# Could try chmod but dont know what we will be
|
||||
# chmoding so just fail.
|
||||
echo "ERROR: '$AGENT' not executable, exiting"
|
||||
quit 1
|
||||
fi
|
||||
}
|
||||
|
||||
syntax () {
|
||||
# Prints script syntax
|
||||
|
||||
echo "Syntax:"
|
||||
echo "$0"
|
||||
}
|
||||
|
||||
checkDepends() {
|
||||
CURL=`which curl 2>/dev/null`
|
||||
if test "$?" -gt 0; then
|
||||
echo "WARNING: Failed to locate curl binary."
|
||||
else
|
||||
echo "INFO: Located curl: $CURL"
|
||||
fi
|
||||
UNZIP=`which unzip 2>/dev/null`
|
||||
if test "$?" -gt 0; then
|
||||
echo "WARNING: Failed to locate unzip binary."
|
||||
else
|
||||
echo "INFO: Located unzip: $UNZIP"
|
||||
fi
|
||||
}
|
||||
|
||||
update() {
|
||||
# Run the git update
|
||||
if test -n "$AUTO_UPDATE"; then
|
||||
if [ -f "$CURL" -a -x "$CURL" ] && [ -f "$UNZIP" -a -x "$UNZIP" ]; then
|
||||
cd $AGENTDIR
|
||||
if [ ! -d tmp ]; then
|
||||
mkdir tmp
|
||||
fi
|
||||
cd tmp
|
||||
REVISION=`curl -Lks https://github.com/${GitHubUsername}/${REPONAME}/commits/master.atom | grep -Eo "([a-f0-9]{40})" | head -n 1`
|
||||
curl -Os https://raw.githubusercontent.com/${GitHubUsername}/${REPONAME}/${REVISION}/bin/ogp_agent
|
||||
currentOGPAgentRunContent=$(cat "./ogp_agent")
|
||||
# Check to make sure ogp_agent downloaded successfully from GitHub before we attempt to replace it.
|
||||
# This should fix random 404 people have been experiencing
|
||||
if [ -s "./ogp_agent" ] && [ "$(echo "$currentOGPAgentRunContent" | head -n 1)" != "404: Not Found" ] && [ ! -z "$(echo "$currentOGPAgentRunContent" | grep "ogp_agent.pl")" ]; then
|
||||
diff ./ogp_agent /bin/ogp_agent &>/dev/null
|
||||
if test $? -ne 0; then
|
||||
cp -f ./ogp_agent /bin/ogp_agent &> /dev/null
|
||||
if test $? -eq 0; then
|
||||
cd /bin
|
||||
chmod ugo+x ogp_agent 2>/dev/null
|
||||
echo "`date`: The agent updater has been changed, relaunching..."
|
||||
rm -Rf tmp
|
||||
/bin/ogp_agent
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
CURRENT=$(cat $AGENTDIR/Cfg/Config.pm | grep version | grep -Eo '[0-9a-f]{40}')
|
||||
if [ "$CURRENT" == "$REVISION" ]; then
|
||||
echo "The agent is up to date."
|
||||
else
|
||||
URL=https://github.com/${GitHubUsername}/${REPONAME}/archive/${REVISION}.zip
|
||||
HEAD=$(curl -L -Os --head -w "%{http_code}" "$URL")
|
||||
if [ "$HEAD" == "200" ]; then
|
||||
echo "Updating agent using curl."
|
||||
curl -L -s "$URL" -o "ogp_agent_latest.zip"
|
||||
if test $? -ne 0; then
|
||||
echo "`date`: curl failed to download the update package."
|
||||
else
|
||||
unzip -oq "ogp_agent_latest.zip"
|
||||
if test $? -ne 0; then
|
||||
echo "`date`: Unable to unzip the update package."
|
||||
ogpGitCleanup
|
||||
else
|
||||
cd ${REPONAME}-${REVISION}
|
||||
cp -avf OGP/* $AGENTDIR/. &> /dev/null
|
||||
CP_APP_RET=$?
|
||||
cp -avf bin/* /usr/bin/. &> /dev/null
|
||||
CP_BIN_RET=$?
|
||||
if [ $CP_APP_RET -ne 0 -o $CP_BIN_RET -ne 0 ]; then
|
||||
echo "`date`: The agent files cannot be overwritten."
|
||||
cd ..
|
||||
ogpGitCleanup
|
||||
echo "Agent update failed."
|
||||
else
|
||||
if test ! -e "$AGENTDIR/Cfg/Preferences.pm"; then
|
||||
cp -f Cfg/Preferences.pm $AGENTDIR/Cfg/Preferences.pm &> /dev/null
|
||||
fi
|
||||
echo "Fixing permissions..."
|
||||
chmod +x $AGENTDIR/ogp_agent.pl &> /dev/null
|
||||
chmod +x $AGENTDIR/agent_conf.sh &> /dev/null
|
||||
chmod +x /usr/bin/ogp_agent &> /dev/null
|
||||
cd ..
|
||||
ogpGitCleanup
|
||||
sed -i "s/version.*/version => '${REVISION}',/" $AGENTDIR/Cfg/Config.pm
|
||||
echo "Agent updated successfully."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "There is a update available (${REVISION}) but the download source is not ready.";
|
||||
echo "Try again later."
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
echo "Update failed."
|
||||
fi
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
run() {
|
||||
# Runs the update and agent
|
||||
update
|
||||
if test -n "$RESTART" ; then
|
||||
echo "Agent will auto-restart if there is a crash."
|
||||
#loop forever
|
||||
while true
|
||||
do
|
||||
# Run
|
||||
cd $AGENTDIR
|
||||
./ogp_agent.pl
|
||||
echo "`date`: Agent restart in $TIMEOUT seconds"
|
||||
# don't thrash the hard disk if the agent dies, wait a little
|
||||
sleep $TIMEOUT
|
||||
done # while true
|
||||
else
|
||||
cd $AGENTDIR
|
||||
./ogp_agent.pl
|
||||
fi
|
||||
}
|
||||
|
||||
quit() {
|
||||
# Exits with the give error code, 1
|
||||
# if none specified.
|
||||
# exit code 2 also prints syntax
|
||||
exitcode="$1"
|
||||
|
||||
# default to failure
|
||||
if test -z "$exitcode"; then
|
||||
exitcode=1
|
||||
fi
|
||||
|
||||
case "$exitcode" in
|
||||
0)
|
||||
echo "`date`: OGP Agent Quit" ;;
|
||||
2)
|
||||
syntax ;;
|
||||
*)
|
||||
echo "`date`: OGP Agent Failed" ;;
|
||||
esac
|
||||
|
||||
# Remove pid file
|
||||
if test -n "$PID_FILE" && test -f "$PID_FILE" ; then
|
||||
# The specified pid file
|
||||
rm -f $PID_FILE
|
||||
fi
|
||||
|
||||
# reset SIGINT and then kill ourselves properly
|
||||
trap - 2
|
||||
kill -2 $$
|
||||
}
|
||||
|
||||
#####################
|
||||
# MAIN APP CODE #
|
||||
#####################
|
||||
|
||||
PATH=/usr/local/bin:/usr/bin:${PATH}
|
||||
|
||||
# Start PureFTPD if OGP has been configured to manage FTP users
|
||||
if [ ! -z "$RUN_PUREFTPD" ] && [ "$RUN_PUREFTPD" == "yes" ]; then
|
||||
/usr/sbin/pure-ftpd.exe -S ${FTP_IP},${FTP_PORT} ${FTP_PASV_STRING} -lpuredb:/etc/pureftpd.pdb -g /var/run/pure-ftpd.pid &
|
||||
fi
|
||||
|
||||
# Setup OGP and Read Preferences
|
||||
setupOGPAndReadBashPrefs
|
||||
|
||||
# Initialise
|
||||
init $*
|
||||
|
||||
# Run
|
||||
run
|
||||
|
||||
# Quit normally
|
||||
quit 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue