El script de lanzamiento perfecto del servidor de Minecraft



El autor es muy aficionado al juego, y él mismo es el administrador de un pequeño servidor "exclusivamente para amigos". Como es habitual entre los aficionados, todo se modula en el servidor, y esto conlleva la inestabilidad del trabajo y como resultado de la caída. Como el autor conoce a Powershell mejor que la ubicación de las tiendas en su calle, decidió crear "El mejor guión de lanzamiento de Minecraft 2020 ". El mismo script sirvió de base para la plantilla en el mercado de Ruvds . Pero todas las fuentes ya están en el artículo. Ahora, en orden, cómo sucedió todo.

Necesitamos equipos


Registro alternativo


Una vez que puse un par de modificaciones más, descubrí que el servidor parece fallar sin declarar la guerra. El servidor no escribió errores en latest.log o debug, y la consola, que debía escribir y detener este error, se cerró.

No quiere escribir, no es necesario. Tenemos Powershell con el cmdlet Tee-Object , que toma un objeto y lo muestra en un archivo y en la consola al mismo tiempo.

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

De esta manera, Powershell recogerá StandardOutput y lo escribirá en un archivo. No intente usar Start-Process , ya que devolverá System.ComponentModel.Component, no StandardOutput, y -RedirectStandardOutput hará que sea imposible ingresar a la consola, lo que queremos evitar.

Argumentos de lanzamiento


Al poner el mismo par de modificaciones, el autor notó que el servidor también carece de RAM. Y esto necesita cambiar los argumentos de inicio. 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 "Right So", deberá crear otro script. Este script ejecutará Minecraft. Comencemos con los argumentos.

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

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

Con la ayuda de sort-object, siempre tomaremos el objeto con el dígito más grande, sin importar cuánto los coloque allí. La máxima pereza.

Ahora necesita asignar memoria al servidor. Para hacer esto, tome la cantidad de memoria del sistema y escriba su cantidad en cadena.

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

Corrija el reinicio automático


El autor vio archivos .bat de otras personas, pero no tuvieron en cuenta la razón por la que se detuvo el servidor. ¿Es inconveniente que solo necesites cambiar el archivo mod o eliminar algo?
Ahora hagamos el reinicio correcto. Anteriormente, el autor encontró extraños scripts que reiniciaron el servidor a pesar de que el servidor se cerró. Usaremos el código de salida. Java usa 0 como una finalización exitosa, por lo tanto, bailaremos.

Primero, cree una función que reinicie el servidor si no se completa.

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 de su propia consola se apague normalmente usando el comando / stop.

Si todos decidiéramos automatizar, sería bueno recopilar la fecha de lanzamiento, la finalización y el motivo de la finalización.

Para hacer esto, escribimos el resultado del proceso de inicio en una variable. En el script, se ve así:

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

Y luego escribimos los resultados en un archivo. Esto es lo que nos devuelve en la variable:

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

Todo esto usando Add-Content se puede agregar al archivo. Después de peinarnos un poco, obtenemos tal script y 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 ejecutemos el script con el lanzamiento del controlador.

Inicio adecuado


El autor quiere que un módulo inicie Minecraft de varias versiones desde cualquier ruta, y también pueda colocar registros en una carpeta específica.

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

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

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

No es seguro. El inicio de sesión y la contraseña se indican aquí en texto sin formato, por lo que debe iniciar un usuario individual que tenga acceso a nivel de usuario, o en un grupo aún más estrecho, para iniciar el servidor. No se recomienda utilizar un administrador estándar para esto.

Con entrada automática ordenada. Ahora necesita registrar una nueva tarea en 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:\minecraft\stdout.txt" -MinecraftPath "C:\minecraft\"'
Register-ScheduledTask -TaskName "StartSSMS" -Trigger $Trigger -User $User -Action $PS -RunLevel Highest

Poniendo el módulo juntos


Ahora vamos a convertir todo en módulos que puedan usarse más tarde. Todo el código de los scripts listos para usar está aquí, importar y usar.

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

Start-minecraft


Primero, crearemos un módulo que solo haga eso, ejecutaremos un script que escuchará y grabará la salida estándar.

En el bloque de parámetros, pregunta desde qué carpeta lanzar 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 de esta manera:

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

Ahora pasemos al Handler.ps1 listo para usar.

Para que nuestro script pueda aceptar parámetros cuando se lo llame, también debemos especificar un bloque de parámetros. Tenga en cuenta que inicia Oracle Java, si usa 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 files\Oracle\Java\javapath_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

Registrarse-minecraft


El script prácticamente repite 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 el parámetro Nombre de usuario y Contraseña. Si no se especificó 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:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
 
    if ($null -eq $i) {
        New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -Value $Username
        New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultPassword -Value $Password 
        New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -Value 1
        Write-Verbose "Set-Autologon will enable user auto logon."
 
    }
    else {
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -Value $Username
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultPassword -Value $Password
        Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -Value 1
    }
 
    
    Write-Verbose "Autologon was set successfully."
 
}

Ejecutar este script se ve así:

Set-Autologon -Password "PlaintextPassword"

Cómo utilizar


Ahora consideraremos cómo el autor mismo usa todo esto. Cómo implementar el servidor público de Minecraft en Windows. Comencemos desde el principio.

1. Crear un usuario

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

2. Registre la tarea de ejecutar el script.

Puede registrarse usando el módulo de la siguiente manera:

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

O use las herramientas estándar:

$Trigger = New-ScheduledTaskTrigger -AtLogOn
$User = "ServerAdmin"
$PS = New-ScheduledTaskAction -Execute 'PowerShell.exe" -Argument "Start-Minecraft -Type Forge -LogFile "C:\minecraft\stdout.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 en el sistema 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 sea al menos mínimamente útil para usted, y el artículo es interesante.


All Articles