Авторът наистина обича играта и е администратор на малък сървър „чисто за приятели“. Както обикновено при любителите, всичко на сървъра е модифицирано, което води до нестабилност на работата и следователно до сривове. Тъй като 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 винаги ще взимаме обект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-MinecraftRegister-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 -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
