Идеален скрипт за стартиране на 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 винаги ще вземаме обект с най-голямото число, колкото и да сте сложили. Ултимативна леност.

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

$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-а.

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

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

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

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

New-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name DefaultUserName -Value $Username -ErrorAction SilentlyContinue
New-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -Name DefaultPassword -Value $Password  -ErrorAction SilentlyContinue
New-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon" -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

Регистрирай-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

Регистрирай-Autologon

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

function Set-Autologon {
 
    param (
        [Parameter(
        HelpMessage="Потребителско име за автовход")]
        $Username = $env:USERNAME,
 
        [Parameter(Mandatory=$true,
        HelpMessage="Парола на потребителя")]
        [ValidateNotNullOrEmpty()]
        $Password
    )
 
    $i = Get-ItemProperty -Path "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon"
 
    if ($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 ще активира автовхода на потребителя."
 
    }
    else {
        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