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
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.
Fuente: habr.com