Авторът много обича играта и сам е администратор на малък сървър "чисто за приятели". Както обикновено при любителите, на сървъра има много модификации, което води до нестабилна работа и последващи падания. Тъй като авторът познава Powershell по-добре от разположението на магазините на своята улица, той реши да създаде "Най-добрият скрипт за старт на Minecraft 2020". Този скрипт стана основа за шаблон в . Всички изходни кодове вече са налични в статията. Сега стъпка по стъпка, как всичко се е случило.
Необходимите ни команди
Алтернативно логване
След като инсталирах още няколко мода, установих, че сървърът, очевидно, пада без предупреждение. Сървърът не записваше грешки в 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 -UserMayNotChangePassword2. Регистриране на задача за стартиране на скрипта
Можете да регистрирате с помощта на модула, така:
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 Highest3. Активиране на автовхода в системата и перезареждане на машината
Set-Autologon -Username "MinecraftServer" -Password "Qw3"Завършване
Авторът е създал скрипта, включително за себе си, затова с радост ще изслуша вашите предложения за подобрения. Авторът се надява, че целият този код е бил поне малко полезен за вас, а статията интересна.
Източник: habr.com
