O autor adora moito o xogo e el mesmo é o administrador dun pequeno servidor "puramente para amigos". Como é habitual entre os afeccionados, todo o servidor está modificado, e isto implica inestabilidade e, como resultado, fallos. Dado que o autor de Powershell coñece mellor que a localización das tendas na súa rúa, decidiu facer "Mellor guión para lanzar Minecraft 2020" O mesmo script serviu de base para o modelo en
Os comandos que necesitamos
Rexistro alternativo
Un día, despois de instalar un par de modificacións máis, descubrín que o servidor, ao parecer, fallaba sen declarar a guerra. O servidor non escribiu erros en latest.log nin en debug, e a consola, que en teoría debería escribir este erro e deterse, pechouse.
Se non quere escribir, non fai falta. Temos Powershell con cmdlet Tee-Obxecto, que toma un obxecto e envíao a un ficheiro e á consola ao mesmo tempo.
.handler.ps1 | Tee-Object .StandardOutput.txt -Append
Deste xeito, Powershell recollerá o StandardOutput e escribirá nun ficheiro. Non intente usar Inicio-Procesoporque devolverá System.ComponentModel.Component e non StandardOutput, e -RedirectStandardOutput fará imposible entrar na consola, que é o que queremos evitar.
Lanzar argumentos
Despois de instalar ese mesmo par de modificacións, o autor notou que o servidor tampouco tiña suficiente memoria RAM. E iso require cambiar os argumentos de lanzamento. En lugar de cambialos cada vez en start.bat, que todos usan, só tes que usar este script.
Dado que Tee-Object só le StandardOutput cando o executable se chama "Just Like This", terás que facer outro script. Este script será lanzado polo propio Minecraft. Comecemos polos argumentos.
Para gozar da preguiza definitiva no futuro, o guión debe recoller argumentos de lanzamento sobre a marcha. Para iso, imos comezar a buscar a última versión forxar.
$forge = ((Get-ChildItem | Where-Object Name -Like "forge*").Name | Sort-Object -Descending) | Select-Object -last 1
Usando sort-object, colleremos sempre o obxecto con maior número, sen importar cantos poña alí. Preguiza definitiva.
Agora cómpre asignar memoria ao servidor. Para iso, tome a cantidade de memoria do sistema e escriba a súa cantidade en cadea.
$ram = ((Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb)
$xmx = "-Xms" + $ram + "G"
Reinicio automático correcto
O autor viu ficheiros .bat doutras persoas, pero non tiveron en conta o motivo polo que se detivo o servidor. Isto é un inconveniente, e se só precisas cambiar o ficheiro mod ou eliminar algo?
Agora imos facer un reinicio axeitado. O autor atopouse con scripts estraños que reiniciaban o servidor independentemente do motivo polo que se apagou. Usaremos o código de saída. Java usa 0 como un éxito, así que bailaremos desde aquí.
Primeiro, imos crear unha función que reinicie o servidor se falla.
function Get-MinecraftExitCode {
do {
if ($global:Process.ExitCode -ne 0) {
Write-Log
Restart-Minecraft
}
else {
Write-Log
}
} until ($global:Process.ExitCode -eq 0)
}
O script permanecerá no bucle ata que o servidor se apague normalmente desde a súa propia consola mediante o comando /stop.
Se decidimos automatizar todo, sería bo recoller a data de inicio, a data de finalización e tamén o motivo da finalización.
Para iso, escribimos o resultado de Start-Process nunha variable. No guión vese así:
$global:Process = Start-Process -FilePath "C:Program Files (x86)common filesOracleJavajavapath_target_*java.exe" -ArgumentList "$xmx -server -jar $forge nogui" -Wait -NoNewWindow -PassThru
E despois escribimos os resultados nun ficheiro. Isto é o que se nos devolve na variable:
$global:Process.StartTime
$global:Process.ExitCode
$global:Process.ExitTime
Todo isto pódese engadir a un ficheiro usando Add-Content. Peiteado un pouco, obtemos este script e chamémoslle 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
Agora imos crear un script que lance o controlador.
Arranque correcto
O autor quere executar diferentes versións de Minecraft desde calquera ruta nun módulo e tamén poder almacenar rexistros nun cartafol específico.
O problema é que o proceso debe ser iniciado por un usuario que estea iniciado sesión no sistema. Isto pódese facer a través do escritorio ou WinRm. Se executa o servidor como usuario do sistema ou mesmo como administrador, pero non inicia sesión, Server.jar nin sequera poderá ler eula.txt e iniciar.
Podemos activar o inicio de sesión automático engadindo tres entradas ao rexistro.
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
Non é seguro. O inicio de sesión e o contrasinal indícanse aquí en texto plano, polo que para iniciar o servidor cómpre crear un usuario separado que teña acceso a nivel de usuario ou nun grupo aínda máis reducido. Non se recomenda estrictamente utilizar un administrador estándar para iso.
Resolvemos o inicio de sesión automático. Agora cómpre rexistrar unha nova tarefa para o servidor. Executaremos o comando desde Powershell, polo que quedará 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
Montaxe do módulo
Agora imos poñer todo en módulos que se poden usar máis tarde. Todo o código para scripts listos está aquí, importa e utiliza.
Podes usar todo o descrito anteriormente por separado se non queres molestarte cos módulos.
Inicio - Minecraft
En primeiro lugar, imos crear un módulo que non fará máis que executar un script que escoitará e gravará a saída estándar.
No bloque de parámetros, pregunta desde que cartafol lanzar Minecraft e onde poñer o rexistro.
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
E terás que lanzar Minecraft así:
Start-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft"
Agora imos pasar ao Handler.ps1 listo para usar
Para que o noso script acepte parámetros cando se chame, tamén necesitamos especificar un bloque de parámetros. Teña en conta que executa Oracle Java, se está a usar unha distribución diferente, terá que cambiar o camiño ao ficheiro executable.
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
Rexistro-Minecraft
O script é practicamente o mesmo que Start-Minecraft, agás que só rexistra unha tarefa nova. Acepta os mesmos argumentos. O nome de usuario, se non se especifica, toma o 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
Rexistro-Autologon
No bloque de parámetros, o script acepta os parámetros Nome de usuario e Contrasinal. Se non se especificou o nome de usuario, utilízase o nome do 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."
}
A execución deste script é así:
Set-Autologon -Password "PlaintextPassword"
Como usar
Vexamos agora como utiliza todo isto o propio autor. Como implementar correctamente un servidor público de Minecraft en Windows. Comecemos dende o principio.
1. Crea un usuario
$pass = Get-Credential
New-LocalUser -Name "MinecraftServer" -Password $pass.Password -AccountNeverExpires -PasswordNeverExpires -UserMayNotChangePassword
2. Rexistra a tarefa para executar o script
Podes rexistrarte usando un módulo como este:
Register-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft" -User "MInecraftServer" -TaskName "MinecraftStarter"
Ou use ferramentas 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 o inicio de sesión automático e reinicie a máquina
Set-Autologon -Username "MinecraftServer" -Password "Qw3"
Realización
O autor fixo o guión, incluso para si mesmo, polo tanto, estará encantado de escoitar as túas suxestións para mellorar o guión. O autor espera que todo este código fose polo menos mínimamente útil para vostede e que o artigo fose interesante.
Fonte: www.habr.com