El script de inicio de servidor de Minecraft perfecto

El script de inicio de servidor de Minecraft perfecto

El autor ama mucho el juego, y él mismo es el administrador de un pequeño servidor "puramente para amigos". Como es habitual entre los aficionados, todo en el servidor está modificado, y esto conlleva inestabilidad en el trabajo y, como resultado, una caída. Dado que el autor conoce Powershell mejor que la ubicación de las tiendas en su calle, decidió hacer "Mejor guión para lanzar Minecraft 2020". El mismo guión sirvió como base para la plantilla en Mercado de Ruvds. Pero todas las fuentes ya están en el artículo. Ahora, en orden, cómo se hizo todo.

Los comandos que necesitamos

Registro alternativo

Una vez que instalé un par de mods más, descubrí que el servidor, aparentemente, se estaba bloqueando sin declarar la guerra. El servidor no escribió errores en latest.log o debug, y la consola, que, en teoría, se suponía que escribiría este error y se detendría, se cerró.

Si no quieres escribir, no lo hagas. Tenemos Powershell con un cmdlet Objeto en T, que toma un objeto y lo envía a un archivo y a la consola al mismo tiempo.

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

Entonces, Powershell tomará StandardOutput y lo escribirá en un archivo. No intentes usar Proceso de inicio, porque devolverá un System.ComponentModel.Component, no un StandardOutput, y -RedirectStandardOutput hará que sea imposible escribir en la consola, que es lo que queremos evitar.

Argumentos de lanzamiento

Habiendo instalado el mismo par de mods, el autor notó que el servidor tampoco tenía suficiente RAM. Y es necesario cambiar los argumentos de lanzamiento. En lugar de cambiarlos cada vez en start.bat, que todos usan, solo use este script.

Dado que Tee-Object lee StandardOutput solo cuando el ejecutable se llama "Just like that", se tendrá que hacer una secuencia de comandos más. Este script ejecutará Minecraft en sí mismo. Comencemos con los argumentos.

Para disfrutar de la pereza definitiva en el futuro, el guión debe recopilar argumentos de lanzamiento sobre la marcha. Para hacer esto, comencemos buscando la última versión. forjar.

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

Con sort-object , siempre tomaremos el objeto con el número más grande, sin importar cuántos pongas ahí. Pereza máxima.

Ahora necesitamos asignar memoria al servidor. Para hacer esto, tomamos la cantidad de memoria del sistema y escribimos su cantidad en una cadena.

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

Reinicio automático adecuado

El autor ha visto archivos .bat de otras personas, pero no tomaron en cuenta la razón por la que se detuvo el servidor. Es un inconveniente, ¿qué sucede si solo necesita cambiar el archivo mod o eliminar algo?
Ahora hagamos un reinicio adecuado. El autor se encontró previamente con extraños scripts que reiniciaban el servidor sin importar por qué se cerraba el servidor. Usaremos el código de salida. Java usa 0 como éxito, así que bailemos desde allí.

Primero, creemos una función que reiniciará el servidor si falla.

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

El script permanecerá en el bucle hasta que el servidor salga normalmente de su propia consola usando el comando /stop.

Si decidimos automatizar todo, sería bueno recopilar la fecha de lanzamiento, el final y también el motivo del final.

Para hacer esto, escribimos el resultado de Start-Process en una variable. En un script se ve así:

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

Y luego escribe los resultados en un archivo. Esto es lo que se nos devuelve en una variable:

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

Todo esto se puede agregar al archivo usando Add-Content. Habiendo cepillado un poco, obtenemos un script de este tipo, pero lo llamamos 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

Ahora diseñemos el script con el lanzamiento del controlador.

Carga automática adecuada

El autor quiere ejecutar Minecraft de varias versiones desde cualquier ruta con un módulo y también poder colocar registros en una carpeta específica.

El problema es que el proceso debe ser iniciado por un usuario que esté logueado. Esto se puede hacer a través del escritorio o WinRm. Si ejecuta el servidor como un sistema o incluso como administrador, pero no inicia sesión, Server.jar ni siquiera podrá leer eula.txt y comenzar.

Podemos habilitar el inicio de sesión automático agregando tres entradas al registro.

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

No es seguro. El nombre de usuario y la contraseña se indican aquí mediante el texto sin formato, por lo tanto, para iniciar el servidor, debe crear un usuario separado que tenga acceso a nivel de usuario o en un grupo aún más reducido. Se desaconseja enfáticamente utilizar el administrador estándar para esto.

Descubrimos el inicio de sesión automático. Ahora necesita registrar una nueva tarea para el servidor. Ejecutaremos el comando desde Powershell, por lo que se verá así:

$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

Montaje del módulo

Ahora organicemos todo en módulos que se puedan usar más adelante. Todo el código de los scripts listos para usar está aquí, importe y use.

Puede usar todo lo descrito anteriormente por separado si no quiere molestarse con los módulos.

iniciar minecraft

Primero, hagamos un módulo que no haga nada más que ejecutar un script que escuchará y escribirá en la salida estándar.

En el bloque de parámetros, pregunta desde qué carpeta iniciar Minecraft y dónde colocar el registro.

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

Y necesitarás ejecutar Minecraft así:

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

Ahora pasemos al Handler.ps1 listo para usar

Para que nuestro script acepte parámetros cuando se le llame, también debemos especificar un bloque de parámetros. Tenga en cuenta que ejecuta Oracle Java, si está utilizando una distribución diferente, deberá cambiar la ruta al archivo ejecutable.

param (
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$type,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$MinecraftPath,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$StandardOutput
)
 
Set-Location $MinecraftPath
 
function Restart-Minecraft {
 
    Write-host "=============== Starting godlike game server ============"
 
    $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 "Start time:" $global:Process.StartTime
 
    Write-host "Exit code:" $global:Process.ExitCode
    
    Write-host "Exit time:" $global:Process.ExitTime
 
    Write-host "=============== Stopped godlike game server ============="
}
 
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

registrar minecraft

El script es prácticamente el mismo que Start-Minecraft, excepto que solo registra una nueva tarea. Acepta los mismos argumentos. El nombre de usuario, si no se especifica, toma el 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

Registrarse-Autologon

En el bloque de parámetros, el script acepta los parámetros Nombre de usuario y Contraseña. Si no se especifica el nombre de usuario, se utiliza el nombre del usuario actual.

function Set-Autologon {
 
    param (
        [Parameter(
        HelpMessage="Username for autologon")]
        $Username = $env:USERNAME,
 
        [Parameter(Mandatory=$true,
        HelpMessage="User password")]
        [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 will enable user auto logon."
 
    }
    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 was set successfully."
 
}

Ejecutar este script se ve así:

Set-Autologon -Password "PlaintextPassword"

Cómo usar

Ahora considere cómo el autor mismo usa todo esto. Cómo implementar correctamente un servidor público de Minecraft en Windows. Empecemos desde el principio.

1. Crea un usuario

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

2. Registre la tarea para ejecutar el script

Puedes registrarte con un módulo así:

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

O utilice las herramientas estándar:

$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. Active el inicio de sesión automático y reinicie la máquina

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

Terminación

El autor hizo el guión, incluso para sí mismo, por lo tanto, estará encantado de escuchar sus sugerencias para mejorar el guión. El autor espera que todo este código haya sido mínimamente útil para usted, y el artículo es interesante.

El script de inicio de servidor de Minecraft perfecto

Fuente: habr.com

Añadir un comentario