Das perfekte Skript zum Starten eines Minecraft-Servers

Das perfekte Skript zum Starten eines Minecraft-Servers

Der Autor liebt das Spiel sehr und ist außerdem Administrator eines kleinen Servers „nur für Freunde“. Wie es unter Liebhabern üblich ist, ist der Server modifiziert, was zu Instabilität führt und somit Abstürze zur Folge hat. Da der Autor Powershell besser kennt als die Lage der Geschäfte in seiner Straße, entschied er sich, "Das beste Skript zum Starten von Minecraft 2020" zu erstellen. Dieses Skript diente auch als Grundlage für eine Vorlage im Ruvds-Marktplatz. Aber alle Quellcodes sind bereits im Artikel vorhanden. Jetzt der Reihe nach, wie das alles umgesetzt wurde.

Die benötigten Befehle

Alternatives Logging

Eine weitere Modifikation auf dem Server führte dazu, dass er, anscheinend, ohne Vorwarnung abstürzt. Der Server schrieb keine Fehler in latest.log oder in debug, und die Konsole, die diesen Fehler melden und anhalten sollte, war geschlossen.

Will er nichts schreiben – dann ist das auch nicht erforderlich. Wir haben Powershell mit dem Cmdlet Tee-Object, das ein Objekt nimmt und es gleichzeitig in eine Datei und in die Konsole ausgibt.

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

Auf diese Weise wird Powershell den StandardOutput sammeln und in die Datei schreiben. Versuchen Sie nicht, Start-Process, zu verwenden, da es System.ComponentModel.Component zurückgibt und nicht den StandardOutput. Außerdem würde -RedirectStandardOutput die Eingabe in die Konsole unmöglich machen, was wir vermeiden wollen.

Startargumente

Nachdem der Autor die besagte Modifikation installiert hatte, stellte er fest, dass dem Server auch Arbeitsspeicher fehlt. Daher müssen die Startargumente geändert werden. Anstatt sie jedes Mal in start.bat zu ändern, die alle verwenden, verwenden Sie einfach dieses Skript.

Da Tee-Object den StandardOutput nur liest, wenn die ausführbare Datei "so direkt" aufgerufen wird, muss ein weiteres Skript erstellt werden. Dieses Skript wird Minecraft selbst starten. Beginnen wir mit den Argumenten.

Um in Zukunft in ultimativer Faulheit zu schwelgen, sollte das Skript die Startargumente dynamisch sammeln. Dazu beginnen wir mit der Suche nach der neuesten Version von forge.

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

Mit sort-object werden wir immer das Objekt mit der höchsten Zahl verwenden, wie viele auch immer Sie dort platziert haben. Ultimative Faulheit.

Jetzt muss dem Server Arbeitsspeicher zugewiesen werden. Dazu nehmen wir die Menge an Systemarbeitsspeicher und speichern dessen Summe in einer Zeichenkette.

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

Richtiger automatischer Neustart

Der Autor hat .bat-Dateien von anderen Personen gesehen, aber sie berücksichtigten nicht den Grund, warum der Server gestoppt wurde. Es ist unpraktisch, wenn man einfach die Mod-Datei wechseln oder etwas löschen muss.
Jetzt machen wir einen richtigen Neustart. Der Autor ist früher auf seltsame Skripte gestoßen, die den Server neu starteten, unabhängig davon, warum der Server beendet wurde. Wir werden jedoch den Exitcode verwenden. Java nutzt 0 als erfolgreiche Beendigung, darauf werden wir aufsetzen.

Zuerst erstellen wir eine Funktion, die den Server bei einem fehlerhaften Abschluss neu startet.

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

Das Skript bleibt in einer Schleife, bis der Server von seiner eigenen Konsole ordnungsgemäß mit dem Befehl /stop beendet wird.

Wenn wir alles automatisieren wollen, wäre es gut, auch den Startzeitpunkt, die Beendigungszeit sowie den Grund für die Beendigung zu erfassen.

Dafür speichern wir das Ergebnis von Start-Process in einer Variablen. Im Skript sieht das so aus:

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

Als nächstes speichern wir die Ergebnisse in einer Datei. Das sind die Werte, die wir in die Variable zurückbekommen:

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

All dies kann mit Add-Content in die Datei hinzugefügt werden. Ein wenig aufbereitet, erhalten wir so ein Skript, das wir handler.ps1 nennen.

Add-Content -Value "Startzeit:" -Path $Logfile 
$global:Process.StartTime
 
Add-Content -Value "Exit-Code:" -Path $Logfile 
$global:Process.ExitCode | Add-Content $Logfile
    
Add-Content -Value "Beendigungszeit:" -Path $Logfile 
$global:Process.ExitTime | Add-Content $Logfile

Jetzt lassen Sie uns das Skript zum Starten des Handlers gestalten.

Richtige Autostart

Der Autor möchte Minecraft verschiedener Versionen aus beliebigen Verzeichnissen mit einem Modul starten und zudem die Möglichkeit haben, Protokolle in einem bestimmten Ordner zu speichern.

Das Problem besteht darin, dass der Prozess von einem Benutzer gestartet werden muss, der im System angemeldet ist. Dies kann über den Desktop oder WinRm erfolgen. Wenn der Server im Namen des Systems oder sogar des Administrators ohne Benutzeranmeldung gestartet wird, kann Server.jar nicht einmal die eula.txt lesen und starten.

Den automatischen Login erreichen wir durch Hinzufügen von drei Einträgen in die Registrierung.

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

Es ist unsicher. Der Benutzername und das Passwort werden hier im Klartext angegeben, weshalb für den Serverstart ein separater Benutzer eingerichtet werden sollte, der Zugriff auf Benutzerebene oder in einer noch engeren Gruppe hat. Die Verwendung des Standardadministrators für diesen Zweck wird kategorisch nicht empfohlen.

Mit dem Autologin haben wir uns befasst. Jetzt müssen wir eine neue Aufgabe für den Server registrieren. Wir werden den Befehl aus Powershell ausführen, daher wird es so aussehen:

$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

Wir erstellen ein Modul

Lass uns jetzt alles in Module packen, die wir später verwenden können. Der gesamte Code der fertigen Skripte ist hier, importiere und benutze ihn.

Alles, was oben beschrieben wurde, kannst du separat verwenden, wenn du dich nicht mit Modulen befassen möchtest.

Start-Minecraft

Zuerst erstellen wir ein Modul, das nur das Skript ausführen wird, das die standardausgabe überwacht und aufzeichnet.

Im Parameterblock wird nach dem Ordner gefragt, aus dem Minecraft gestartet werden soll, und wo das Protokoll gespeichert werden soll.

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

Und so muss Minecraft gestartet werden:

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

Jetzt kommen wir zu dem einsatzbereiten Handler.ps1

Damit unser Skript Parameter bei der Aufruf annehmen kann, muss auch ein Parameterblock angegeben werden. Beachte, dass er Oracle Java startet; wenn du eine andere Distribution verwendest, muss der Pfad zur ausführbaren Datei geändert werden.

param (
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$type,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$MinecraftPath,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$StandardOutput
)
 
Set-Location $MinecraftPath
 
function Restart-Minecraft {
 
    Write-host "=============== Starte den göttlichen Spieleserver ============"
 
    $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 "Startzeit:" $global:Process.StartTime
 
    Write-host "Exit-Code:" $global:Process.ExitCode
    
    Write-host "Endzeit:" $global:Process.ExitTime
 
    Write-host "=============== Gestoppter göttlicher Spieleserver ============="
}
 
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

Das Skript wiederholt praktisch Start-Minecraft, mit der Ausnahme, dass es nur eine neue Aufgabe registriert. Es nimmt die gleichen Argumente. Der Benutzername, wenn nicht angegeben, wird auf den aktuellen gesetzt.

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

Im Parameterblock des Skripts wird der Parameter Benutzername und Passwort akzeptiert. Wenn der Benutzername nicht angegeben ist, wird der aktuelle Benutzername verwendet.

function Set-Autologon {
 
    param (
        [Parameter(
        HelpMessage="Benutzername für den Autologon")]
        $Username = $env:USERNAME,
 
        [Parameter(Mandatory=$true,
        HelpMessage="Benutzerpasswort")]
        [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 wird die Benutzeranmeldung aktivieren."
 
    }
    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 "Autologon wurde erfolgreich eingerichtet."
 
}

So sieht der Start dieses Skripts aus:

Set-Autologon -Password "PlaintextPassword"

Wie man es benutzt

Jetzt schauen wir uns an, wie der Autor all dies selbst nutzt. Wie man richtig einen öffentlichen Minecraft-Server unter Windows einrichtet. Beginnen wir von ganz vorne.

1. Benutzer erstellen

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

2. Aufgabe zum Starten des Skripts registrieren

Sie können dies mit einem Modul so registrieren:

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

Oder Sie verwenden die Standardmittel:

$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. Autologon aktivieren und das System neu starten

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

Abschluss

Der Autor hat das Skript auch für sich selbst erstellt und freut sich daher über Ihre Vorschläge zur Verbesserung des Skripts. Der Autor hofft, dass dieser gesamte Code für Sie zumindest minimal nützlich war und der Artikel interessant ist.

Das perfekte Skript zum Starten eines Minecraft-Servers

Quelle: habr.com

60GB SSD 8Gb DDR4