Scriptul perfect pentru a lansa un server Minecraft

Scriptul perfect pentru a lansa un server Minecraft

Autorul iubește foarte mult acest joc și este el însuși administrator al unui server mic „strict pentru prieteni”. Așa cum se obișnuiește printre pasionați, serverul este modat complet, iar asta duce la instabilitate în funcționare și, drept consecință, la prăbușiri. Deoarece Powershell este bine cunoscut de autor, a decis să realizeze „Cel Mai Bun Script Pentru Rularea Minecraft 2020”. Acest script a servit drept bază pentru un șablon în marketplace-ul Ruvds. Dar toate sursele sunt deja disponibile în articol. Acum, pe rând, cum a fost realizat totul.

Comenzile necesare

Jurnalizare alternativă

Odată ce am instalat câteva module în plus, am observat că serverul, din câte se pare, se prăbușește fără avertisment. Serverul nu a scris erori în latest.log sau în debug, iar consola, care în teorie ar fi trebuit să scrie această eroare și să se oprească, a fost închisă.

Dacă nu vrea să scrie – nu este necesar. Avem Powershell cu cmdlet-ul Tee-Object, care ia un obiect și îl scrie simultan în fișier și în consolă.

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

Astfel, Powershell va prelua StandardOutput și îl va scrie în fișier. Nu încercați să folosiți Start-Process, deoarece va returna System.ComponentModel.Component, nu StandardOutput, iar -RedirectStandardOutput va face imposibilă introducerea în consolă, ceea ce dorim să evităm.

Argumentele de lansare

După ce am instalat acele module, autorul a observat că serverul îi lipsește, de asemenea, memorie RAM. Asta necesită modificarea argumentelor de lansare. În loc să le schimbați de fiecare dată în start.bat, care este folosit de toți, folosiți pur și simplu acest script.

Având în vedere că Tee-Object citește StandardOutput doar când executabilul este apelat „Exact așa”, va fi necesar să facem un alt script. Acest script va rula Minecraft-ul. Să începem cu argumentele.

Pentru a ne putea deda pe viitor la lene ultimativă, scriptul trebuie să adune argumentele de lansare în timp real. Pentru aceasta, să începem cu căutarea celei mai recente versiuni forge.

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

Folosind sort-object, vom lua întotdeauna obiectul cu cel mai mare număr, oricâte ați pune acolo. Lenea ultimativă.

Acum trebuie să atribuim serverului memorie. Pentru aceasta, luăm cantitatea de memorie fizică și o adunăm în șir.

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

Repornire automată corectă

Autorul a văzut fișiere .bat de la alții, dar acestea nu țineau cont de motivele pentru care serverul a fost oprit. Este incomod că trebuie să schimbi doar fișierul modului sau să ștergi ceva?
Acum să facem un restart corect. Autorul s-a lovit anterior de scripturi ciudate care restartau serverul indiferent de motivele pentru care serverul s-a oprit. Noi vom folosi exitcode. Java folosește 0 ca încheiere de succes, așa că de aici ne vom ghida.

În primul rând, să creăm o funcție care va restart serverul în cazul în care acesta se oprește din funcționare.

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

Scriptul va rămâne într-un ciclu până când serverul se va închide normal din consola sa, folosind comanda /stop.

Dacă am decis să automatizăm totul, ar fi bine să colectăm și data de pornire, finalizare și motivul finalizării.

Pentru aceasta, vom salva rezultatul Start-Process într-o variabilă. În script, arată astfel:

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

Apoi, vom scrie rezultatele într-un fișier. Iată ce ne returnează variabila:

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

Toate acestea pot fi adăugate într-un fișier folosind Add-Content. După ce le ordonăm puțin, obținem un script pe care îl numim handler.ps1.

Add-Content -Value "Ora de început:" -Path $Logfile 
$global:Process.StartTime
 
Add-Content -Value "Cod de încheiere:" -Path $Logfile 
$global:Process.ExitCode | Add-Content $Logfile
    
Add-Content -Value "Ora de încheiere:" -Path $Logfile 
$global:Process.ExitTime | Add-Content $Logfile

Acum să ne ocupăm de scriptul de pornire al handler-ului.

Autoload corect

Autorul dorește să poată porni Minecraft din diferite versiuni din orice cale, precum și să aibă posibilitatea de a aduna jurnalele într-un anumit folder.

Problema constă în faptul că procesul trebuie să fie pornit de un utilizator care este conectat în sistem. Acest lucru poate fi realizat prin birou sau WinRm. Dacă pornim serverul din contul sistemului sau chiar al administratorului, dar nu suntem conectați, Server.jar nu va putea nici să citească eula.txt și să pornească.

Putem activa autoconectarea în sistem prin adăugarea a trei înregistrări în registru.

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

Aceasta nu este sigur. Numele de utilizator și parola sunt specificate aici în text simplu, prin urmare, pentru rularea serverului trebuie să creați un utilizator separat, care are acces la nivel de utilizator sau într-un grup chiar mai restrâns. Utilizarea administratorului standard pentru asta este categoric nerecomandată.

Am terminat cu autentificarea automată. Acum trebuie să înregistrăm o nouă taskă pentru server. O vom rula din PowerShell, așa că va arăta în felul următor:

$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

Să construim modulul

Acum să organizăm totul în module, care vor putea fi apoi folosite. Tot codul scripturilor gata este aici, importați-l și folosiți-l.

Tot ce este descris mai sus puteți folosi separat, dacă nu doriți să vă ocupați de module.

Start-Minecraft

Mai întâi vom crea un modul, care va face doar ceea ce este necesar pentru a lansa scriptul, care va asculta și va înregistra standardoutput.

În blocul de parametrii, el cere din ce dosar să pornească Minecraftul și unde să stocheze logul.

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

Și pentru a porni Minecraftul, va trebui să procedați astfel:

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

Acum să trecem la Handler.ps1 gata de utilizare

Pentru ca scriptul nostru să poată accepta parametrii la apel, trebuie să specificăm și blocul de parametrii. Rețineți că acesta pornește Oracle Java, dacă folosiți o altă distribuție, va trebui să modificați calea către fișierul executabil.

param (
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$type,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$MinecraftPath,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$StandardOutput
)
 
Set-Location $MinecraftPath
 
function Restart-Minecraft {
 
    Write-host "=============== Pornit un server de joc de excepție ============"
 
    $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 "Timpul de început:" $global:Process.StartTime
 
    Write-host "Codul de ieșire:" $global:Process.ExitCode
    
    Write-host "Timpul de ieșire:" $global:Process.ExitTime
 
    Write-host "=============== Oprit server de joc de excepție ============="
}
 
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

Înregistrare-Minecraft

Scriptul este practic o copie a Start-Minecraft, cu excepția faptului că doar înregistrează o nouă sarcină. Primește aceleași argumente. Numele utilizatorului, dacă nu a fost specificat, preia numele actual.

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

Înregistrare-Autologon

În blocul de parametri, scriptul acceptă parametrii Username și Password. Dacă Username nu a fost specificat, se utilizează numele utilizatorului curent.

function Set-Autologon {

    param (
        [Parameter(
        HelpMessage="Numele utilizatorului pentru autologare automatică")]
        $Username = $env:USERNAME,

        [Parameter(Mandatory=$true,
        HelpMessage="Parola utilizatorului")]
        [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 va activa autologarea utilizatorului."

    }
    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 "Autologarea a fost setată cu succes."

}

Executarea acestui script arată așa:

Set-Autologon -Password "PlaintextPassword"

Cum se folosește

Acum vom analiza cum autorul folosește toate acestea. Cum trebuie să implementăm corect un server public Minecraft pe Windows. Să începem de la început.

1. Creăm utilizatorul

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

2. Înregistrăm sarcina de executare a scriptului

Puteți înregistra folosind modulul astfel:

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

Sau folosiți instrumentele standard:

$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. Activăm autologarea în sistem și repornim mașina

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

Încheiere

Autorul a creat scriptul, în parte pentru sine, așa că va fi bucuros să primească sugestii pentru îmbunătățirea scriptului. Autorul speră că tot acest cod v-a fost cel puțin minim util și că articolul este interesant.

Scriptul perfect pentru a lansa un server Minecraft

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster