El script perfecto para lanzar un servidor de Minecraft

El script perfecto para lanzar un servidor de Minecraft

El autor ama mucho el juego y es administrador de un pequeño servidor "puramente para amigos". Como suele suceder entre los aficionados, en el servidor está modificado todo, lo cual conlleva a la inestabilidad del funcionamiento y, como consecuencia, a caídas. Debido a que conoce Powershell mejor que la ubicación de las tiendas en su calle, decidió hacer "El Mejor Script Para Lanzar Minecraft 2020Este mismo script sirvió como base para una plantilla en el marketplace de Ruvds. Pero todos los códigos fuente ya están en el artículo. Ahora, paso a paso, cómo se realizó todo.

Los comandos que necesitamos

Registro alternativo

Una vez, al instalar un par más de mods, descubrí que el servidor, al parecer, caía sin aviso. El servidor no escribía errores en latest.log o en debug, y la consola, que por idea debería haber escrito este error y detenerse, estaba cerrada.

Si no quiere escribir, no es necesario. Tenemos Powershell con el cmdlet Tee-Object, que toma un objeto y lo imprime en un archivo y en la consola simultáneamente.

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

De este modo, Powershell recogerá StandardOutput y lo registrará en un archivo. No intentes usar Start-Process, porque devolverá System.ComponentModel.Component, no StandardOutput, y -RedirectStandardOutput hará que la entrada en la consola sea imposible, lo que queremos evitar.

Argumentos de inicio

Al haber instalado ese par de mods, el autor notó que el servidor también carecía de memoria RAM. Y eso necesita cambiar los argumentos de inicio. En lugar de cambiarlos cada vez en start.bat, que todos usan, simplemente utiliza este script.

Debido a que Tee-Object lee StandardOutput solo cuando el archivo ejecutable se llama "así directamente", será necesario hacer otro script. Este script iniciará Minecraft. Comencemos con los argumentos.

Para poder entregarse a la pereza definitiva en el futuro, el script debe recolectar los argumentos de inicio sobre la marcha. Para ello, comenzaremos buscando la última versión de forge.

$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 alto, sin importar cuántos pongas allí. Pereza definitiva.

Ahora necesitamos asignar memoria al servidor. Para ello, tomamos la cantidad de memoria del sistema y registramos su suma en una cadena.

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

Reinicio automático correcto

El autor ha visto archivos .bat de otras personas, pero no consideraban la razón por la cual el servidor se detuvo. Es problemático tener que cambiar simplemente el archivo del mod o eliminar algo.
Ahora hagamos un reinicio correcto. El autor se había encontrado anteriormente con scripts extraños que reiniciaban el servidor independientemente de por qué se había detenido. Nosotros utilizaremos el exitcode. Java utiliza 0 como finalización exitosa, de ahí partiremos.

Primero crearemos una función que reiniciará el servidor en caso de que su finalización no haya sido exitosa.

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 un ciclo hasta que el servidor se detenga correctamente desde su propia consola con el comando /stop.

Si decidimos automatizar todo, también sería bueno registrar la fecha de inicio, finalización y la razón de la finalización.

Para esto, almacenamos el resultado de Start-Process en una variable. En el 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 registramos los resultados en un archivo. Esto es lo que se devuelve en la variable:

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

Todo esto se puede agregar a un archivo usando Add-Content. Después de un pequeño ajuste, obtenemos el siguiente script, que llamaremos handler.ps1.

Add-Content -Value "Hora de inicio:" -Path $Logfile 
$global:Process.StartTime
 
Add-Content -Value "Código de salida:" -Path $Logfile 
$global:Process.ExitCode | Add-Content $Logfile
    
Add-Content -Value "Hora de salida:" -Path $Logfile 
$global:Process.ExitTime | Add-Content $Logfile

Ahora vamos a organizar el script con el lanzamiento del handler.

Carga automática correcta

El autor desea iniciar Minecraft de diferentes versiones desde cualquier ruta mediante un solo módulo, así como tener la capacidad de guardar registros en una carpeta específica.

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

Podemos habilitar el inicio de sesión automático mediante la adición de tres entradas en el 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

Esto no es seguro. El nombre de usuario y la contraseña se especifican aquí en texto claro, por lo que se debe crear un usuario separado para la ejecución del servidor, que tenga acceso a nivel de usuario o en un grupo aún más restringido. No se recomienda categoricamente utilizar al administrador estándar para esto.

Hemos resuelto el inicio de sesión automático. Ahora necesitamos registrar una nueva tarea para el servidor. Vamos a ejecutar el comando desde PowerShell, así 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

Vamos a crear un módulo

Ahora vamos a organizar todo en módulos que se puedan utilizar después. Todo el código de los scripts listos está aquí, impórtalo y úsalo.

Todo lo que se ha descrito anteriormente se puede utilizar por separado, si no quieres complicarte con los módulos.

Start-Minecraft

Primero haremos un módulo que se encargue únicamente de ejecutar un script que escuche y registre la salida estándar.

En el bloque de parámetros, se solicita desde qué carpeta ejecutar Minecraft y dónde guardar 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 Minecraft se debe iniciar así:

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

Ahora pasemos al Handler.ps1 listo para usar

Para que nuestro script pueda aceptar parámetros al ser llamado, también es necesario especificar el bloque de parámetros. Ten en cuenta que inicia Oracle Java, si utilizas otra distribución, deberás cambiar la ruta del archivo ejecutable.

param (
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$type,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$MinecraftPath,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$StandardOutput
)
 
Set-Location $MinecraftPath
 
function Restart-Minecraft {
 
    Write-host "=============== Iniciando el servidor de juegos godlike ============"
 
    $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 "Hora de inicio:" $global:Process.StartTime
 
    Write-host "Código de salida:" $global:Process.ExitCode
    
    Write-host "Hora de salida:" $global:Process.ExitTime
 
    Write-host "=============== Servidor de juegos godlike detenido ============="
}
 
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 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

Registrar-Autologon

En el bloque de parámetros, el script acepta el parámetro Username y Password. Si no se ha especificado Username, se utiliza el nombre del usuario actual.

function Set-Autologon {
 
    param (
        [Parameter(
        HelpMessage="Nombre de usuario para autologon")]
        $Username = $env:USERNAME,
 
        [Parameter(Mandatory=$true,
        HelpMessage="Contraseña del usuario")]
        [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 habilitará el inicio de sesión automático para el usuario."
 
    }
    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 "El autologon se configuró exitosamente."
 
}

La ejecución de este script se ve así:

Set-Autologon -Password "PlaintextPassword"

Cómo usar

Ahora analizaremos cómo el autor utiliza todo esto. Cómo se debe configurar correctamente un servidor público de Minecraft en Windows. Comencemos desde el principio.

1. Creamos un usuario

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

2. Registramos una tarea para ejecutar el script

Puedes registrar usando el módulo, así:

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

O usar 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. Activamos el inicio de sesión automático y reiniciamos la máquina

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

Conclusión

El autor hizo el script también para sí mismo, por lo que estará encantado de escuchar tus sugerencias para mejorarlo. El autor espera que todo este código haya sido al menos mínimamente útil para ti y que el artículo sea interesante.

El script perfecto para lanzar un servidor de Minecraft

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster