Перфектен скрипт за стартиране на Minecraft сървър

Перфектен скрипт за стартиране на Minecraft сървър

Авторът наистина обича играта и е администратор на малък сървър „чисто за приятели“. Както обикновено при любителите, всичко на сървъра е модифицирано, което води до нестабилност на работата и следователно до сривове. Тъй като Powershell му е по-добре познат от разположението на магазините по улицата му, той реши да направи „Най-добрият скрипт за стартиране на Minecraft 2020“. Този скрипт послужи като основа за шаблона в маркетплейса Ruvds. Всички изходни кодове вече са налични в статията. Сега по ред, как всичко беше произведено.

Необходими команди

Алтернативно логване

Веднъж, след като инсталирах още няколко мода, забелязах, че сървърът, по всичко личи, се срива без обявление. Сървърът не записваше грешки в latest.log или debug, а конзолата, която по идея трябваше да напише тази грешка и да се спре, беше затворена.

Ако не иска да пише – няма нужда. Имаме Powershell с командлета Tee-Object, който взима обект и го извежда в файл и в конзолата едновременно.

.handler.ps1 | Tee-Object .StandardOutput.txt -Append

По този начин Powershell ще взема StandardOutput и ще го запише в файл. Не се опитвайте да използвате Start-Process, защото той ще върне System.ComponentModel.Component, а не StandardOutput, а -RedirectStandardOutput ще направи невъзможно въвеждането в конзолата, което искаме да избегнем.

Аргументи за стартиране

След като инсталирах същите тези мода, авторът забеляза, че на сървъра също липсва оперативна памет. И това налага промяна на аргументите за стартиране. Вместо всеки път да ги променяте в start.bat, който всички използват, просто използвайте този скрипт.

Тъй като Tee-Object чете StandardOutput само когато изпълненият файл се извиква „Така директно“, ще трябва да направим още един скрипт. Този скрипт ще стартира самия Minecraft. Нека започнем с аргументите.

За да предаваме наистина ултимативна мързеливост в бъдеще, скриптът трябва да събира аргументите за стартиране в движение. За това нека започнем с търсене на последната версия forge.

$forge = ((Get-ChildItem | Where-Object Name -Like "forge*").Name | Sort-Object -Descending) | Select-Object -last 1

С помощта на sort-object винаги ще взимаме обектa с най-голямото число, без значение колко от тях ще сложите. Ультимативен мързел.

Сега трябва да зададем памет на сървъра. За това вземаме количеството системна памет и записваме сумата в низ.

$ram = ((Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb)
$xmx = "-Xms" + $ram + "G"

Правилен автоматичен рестарт

Авторът е виждал .bat файлове от други хора, но те не отчитат причината, поради която сървърът е спрян. Неприятно е, че ако просто трябва да смените мод файла или да изтриете нещо?
Сега ще направим правилен рестарт. Авторът по-рано е попадал на странни скриптове, които рестартираха сървъра, независимо от причината, поради която сървърът е спрял. Ние ще използваме exitcode. Java използва 0 за успешен завършек, оттук и ще действаме.

Първо, ще създадем функция, която ще рестартира сървъра в случай на неуспешно приключване.

function Get-MinecraftExitCode {
   
    do {
        
        if ($global:Process.ExitCode -ne 0) {
            Write-Log
            Restart-Minecraft
        }
        else {
            Write-Log
        }
 
    } until ($global:Process.ExitCode -eq 0)
    
}

Скриптът ще остане в цикъл, докато сървърът сам не приключи нормално, с командата /stop.

Ако решим да автоматизираме всичко, би било хубаво да записваме датата на стартиране, приключване, както и причината за приключване.

За това записваме резултата от Start-Process в променлива. В скрипта това изглежда така:

$global:Process = Start-Process -FilePath  "C:Program Files (x86)common filesOracleJavajavapath_target_*java.exe" -ArgumentList "$xmx -server -jar $forge nogui" -Wait -NoNewWindow -PassThru

След това записваме резултатите във файл. Ето какво получаваме в променливата:

$global:Process.StartTime
$global:Process.ExitCode	
$global:Process.ExitTime

Всичко това може да се добави във файл с помощта на Add-Content. Леко почистване и получаваме такъв скрипт, който наричаме handler.ps1.

Add-Content -Value "Start time:" -Path $Logfile 
$global:Process.StartTime
 
Add-Content -Value "Exit code:" -Path $Logfile 
$global:Process.ExitCode | Add-Content $Logfile
    
Add-Content -Value "Exit time:" -Path $Logfile 
$global:Process.ExitTime | Add-Content $Logfile

Сега нека структурираме скрипта за стартиране на handler’a.

Правилно автоматично зареждане

Авторът иска с един модул да стартира Minecraft различни версии от всякакви места, а също така да може да събира логовете в конкретна папка.

Проблемът е, че процесът трябва да бъде стартиран от потребител, който е в системата. Това може да се направи чрез работния плот или WinRm. Ако стартирате сървъра от името на системата или дори администратора, но не сте влезли в системата, Server.jar няма да може да прочете eula.txt и да се стартира.

Можем да активираме автоматичния вход в системата, като добавим три записа в регистъра.

New-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -Value $Username -ErrorAction SilentlyContinue
New-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultPassword -Value $Password  -ErrorAction SilentlyContinue
New-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -Value 1 -ErrorAction SilentlyContinue

Това не е безопасно. Логинът и паролата се посочват тук в чист текст, затова е необходимо да се създаде отделен потребител с потребителски достъп или в още по-тясна група за стартиране на сървера. Използването на стандартния администратор за това е категорично не се препоръчва.

С автологин разбрахме. Сега е необходимо да регистрираме нова задача за сървера. Ще стартираме командата от PowerShell, затова това ще изглежда така:

$Trigger = New-ScheduledTaskTrigger -AtLogOn
$User = "ServerAdmin"
$PS = New-ScheduledTaskAction -Execute 'PowerShell.exe" -Argument "Start-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft"'
Register-ScheduledTask -TaskName "StartSSMS" -Trigger $Trigger -User $User -Action $PS -RunLevel Highest

Сглобяваме модула

Сега нека оформим всичко в модули, които след това може да използвате. Цялото код на готовите скриптове е тук, импортирайте и ползвайте.

Всичко, описано по-горе, можете да използвате отделно, ако не желаете да се занимавате с модули.

Start-Minecraft

Първо ще направим модул, който просто ще стартира скрипт, който ще слуша и записва стандартния изход.

В блока с параметри той пита от коя папка да стартира Minecraft и къде да запише логовете.

Set-Location (Split-Path $MyInvocation.MyCommand.Path)
function Start-Minecraft {
    [CmdletBinding()]
    param (
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]
        $LogFile,
 
        [Parameter(Mandatory)]  
        [ValidateSet('Vanilla', 'Forge')]
        [ValidateNotNullOrEmpty()]
        [string]
        $Type,
 
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $MinecraftPath
 
    )
    powershell.exe -file .handler.ps1 -type $type -MinecraftPath $MinecraftPath | Tee-Object $LogFile -Append
}
Export-ModuleMember -Function Start-Minecraft

А Minecraft ще трябва да се стартира така:

Start-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft"

Сега ще преминем към готовия за употреба Handler.ps1

За да може нашият скрипт да приема параметри при извикването, също трябва да посочите блока с параметри. Обърнете внимание, той стартира Oracle Java, ако използвате друга дистрибуция, ще трябва да промените пътя до изпълнимия файл.

param (
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$type,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$MinecraftPath,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$StandardOutput
)
 
Set-Location $MinecraftPath
 
function Restart-Minecraft {
 
    Write-host "=============== Стартиране на сървър за игра ============"
 
    $forge = ((Get-ChildItem | Where-Object Name -Like "forge*").Name | Sort-Object -Descending) | Select-Object -first 1
 
    $ram = ((Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb)
    $xmx = "-Xms" + $ram + "G"
    $global:Process = Start-Process -FilePath  "C:Program Files (x86)common filesOracleJavajavapath_target_*java.exe" -ArgumentList "$xmx -server -jar $forge nogui" -Wait -NoNewWindow -PassThru
    
}
 
function Write-Log {
    Write-host "Начало на времето:" $global:Process.StartTime
 
    Write-host "Код на изход:" $global:Process.ExitCode
    
    Write-host "Край на времето:" $global:Process.ExitTime
 
    Write-host "=============== Спиране на сървър за игра ============="
}
 
function Get-MinecraftExitCode {
   
    do {
        
        if ($global:Process.ExitCode -ne 0) {
            Restart-Minecraft
            Write-Log
        }
        else {
            Write-Log
        }
 
    } until ($global:Process.ExitCode -eq 0)
    
}
 
Get-MinecraftExitCode

Register-Minecraft

Скриптът практически повтаря Start-Minecraft, с изключение на това, че само регистрира нова задача. Приема същите аргументи. Името на потребителя, ако не е указано, взима текущото.

function Register-Minecraft {
    [CmdletBinding()]
    param (
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]
        $LogFile,
 
        [Parameter(Mandatory)]  
        [ValidateSet('Vanilla', 'Forge')]
        [ValidateNotNullOrEmpty()]
        [string]$Type,
 
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$MinecraftPath,
 
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$User,
 
        [Parameter(Mandatory)]
        [string]$TaskName = $env:USERNAME
    )
 
    $Trigger = New-ScheduledTaskTrigger -AtLogOn
    $arguments = "Start-Minecraft -Type $Type -LogFile $LogFile -MinecraftPath $MinecraftPath"
    $PS = New-ScheduledTaskAction -Execute "PowerShell" -Argument "-noexit -command $arguments"
    Register-ScheduledTask -TaskName $TaskName -Trigger $Trigger -User $User -Action $PS -RunLevel Highest
    
}
 
Export-ModuleMember -Function Register-Minecraft

Register-Autologon

В блока параметри скриптът приема параметри Username и Password. Ако Username не е указан, се използва името на текущия потребител.

функция Set-Autologon {
 
    параметр (
        [Параметр(
        СообщениеСправки="Пользователь для автологина")]
        $Username = $env:USERNAME,
 
        [Параметр(Обязательный=$true,
        СообщениеСправки="Пароль пользователя")]
        [ValidateNotNullOrEmpty()]
        $Password
    )
 
    $i = Get-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon"
 
    если ($null -eq $i) {
        New-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name DefaultUserName -Value $Username
        New-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name DefaultPassword -Value $Password 
        New-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name AutoAdminLogon -Value 1
        Write-Verbose "Set-Autologon включит автологин для пользователя."
 
    }
    иначе {
        Set-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name DefaultUserName -Value $Username
        Set-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name DefaultPassword -Value $Password
        Set-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name AutoAdminLogon -Value 1
    }
 
    
    Write-Verbose "Автологин был успешно установлен."
 
}

Запуск на този скрипт изглежда така:

Set-Autologon -Password "PlaintextPassword"

Как да ползвате

Сега нека видим как самият автор използва всичко това. Как правилно да разгръщате публичен Minecraft сървър на Windows. Нека започнем от самото начало.

1. Създаваме потребител

$pass = Get-Credential
New-LocalUser -Name "MinecraftServer" -Password $pass.Password -AccountNeverExpires -PasswordNeverExpires -UserMayNotChangePassword

2. Регистрираме задача за стартиране на скрипта

Можете да регистрирате с помощта на модула, така:

Register-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft" -User "MInecraftServer" -TaskName "MinecraftStarter"

Или да използвате стандартните средства:

$Trigger = New-ScheduledTaskTrigger -AtLogOn
$User = "ServerAdmin"
$PS = New-ScheduledTaskAction -Execute 'PowerShell.exe" -Argument "Start-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft"'
Register-ScheduledTask -TaskName "StartSSMS" -Trigger $Trigger -User $User -Action $PS -RunLevel Highest

3. Включваме автологин в системата и рестартираме машината

Set-Autologon -Username "MinecraftServer" -Password "Qw3"

Завършване

Авторът е направил скрипта, в това число и за себе си, затова с радост ще изслуша вашите предложения за подобряване на скрипта. Авторът се надява, че целият този код е бил поне минимално полезен за вас, а статията интересна.

Перфектен скрипт за стартиране на Minecraft сървър

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster