O script ideal para iniciar um servidor Minecraft

O script ideal para iniciar um servidor Minecraft

O autor realmente ama o jogo e é administrador de um pequeno servidor "apenas para amigos". Como é comum entre os entusiastas, o servidor possui várias mods, o que resulta em instabilidade e, consequentemente, quedas. Como o Powershell é mais familiar para ele do que a localização das lojas na sua rua, ele decidiu criar "O Melhor Script Para Iniciar Minecraft 2020". Este mesmo script serviu como base para um modelo no marketplace Ruvds. Mas todos os códigos-fonte já estão no artigo. Agora, vamos passo a passo, como tudo isso foi feito.

Os comandos necessários para nós

Registro alternativo

Certa vez, ao instalar mais alguns mods, percebi que o servidor, aparentemente, estava caindo sem aviso prévio. O servidor não registrou erros no latest.log ou no debug, e o console, que deveria imprimir esse erro e parar, estava fechado.

Se ele não quer reportar – não precisa. Temos o Powershell com o cmdlet Tee-Object, que pega um objeto e o envia para um arquivo e para o console ao mesmo tempo.

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

Assim, o Powershell irá capturar o StandardOutput e gravá-lo em um arquivo. Não tente usar Start-Process, pois ele retornará System.ComponentModel.Component, não o StandardOutput, e -RedirectStandardOutput tornará impossível a entrada no console, o que queremos evitar.

Argumentos de inicialização

Depois de instalar aqueles mods, o autor notou que o servidor também estava sem memória RAM suficiente. Isso significa que é necessário alterar os argumentos de inicialização. Em vez de mudar isso toda vez no start.bat, que todo mundo usa, basta usar este script.

Como o Tee-Object lê o StandardOutput apenas quando o arquivo executável é chamado "Assim", precisaremos criar mais um script. Este script irá iniciar o próprio Minecraft. Vamos começar com os argumentos.

Para no futuro se entregar à total preguiça, o script deve reunir os argumentos de inicialização dinamicamente. Para isso, vamos começar procurando a última versão do forge.

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

Com o sort-object, sempre pegaremos o objeto com o número mais alto, não importa quantos você tenha ali. Total preguiça.

Agora precisamos alocar memória para o servidor. Para isso, pegamos a quantidade de memória do sistema e somamos isso em uma string.

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

Reinício automático correto

O autor viu arquivos .bat de outras pessoas, mas eles não consideravam o motivo pelo qual o servidor havia sido encerrado. É inconveniente, não é? E se precisar apenas trocar o arquivo do mod ou remover algo?
Agora vamos realizar o reinício corretamente. O autor anteriormente encontrou scripts estranhos que reiniciavam o servidor independentemente de como o servidor havia parado. Vamos usar o exitcode. O Java utiliza 0 para uma finalização bem-sucedida, e é a partir disso que trabalharemos.

Primeiro, vamos criar uma função que reiniciará o servidor em caso de falha na sua finalização.

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á em um loop até que o servidor se encerre corretamente a partir de sua própria console, usando o comando /stop.

Se decidirmos automatizar tudo, seria bom também coletar a data de início, término, e a razão para a finalização.

Para isso, gravamos o resultado de Start-Process em uma variável. No script, isso se parece com:

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

Em seguida, gravamos os resultados em um arquivo. Aqui está o que é retornado para a variável:

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

Tudo isso pode ser adicionado a um arquivo usando Add-Content. Após uma pequena organização, temos este script, que chamaremos de handler.ps1.

Add-Content -Value "Hora de início:" -Path $Logfile 
$global:Process.StartTime
 
Add-Content -Value "Código de saída:" -Path $Logfile 
$global:Process.ExitCode | Add-Content $Logfile
    
Add-Content -Value "Hora de saída:" -Path $Logfile 
$global:Process.ExitTime | Add-Content $Logfile

Agora vamos organizar o script com a execução do handler.

Inicialização automática correta

O autor deseja usar um único módulo para executar diferentes versões do Minecraft a partir de quaisquer caminhos, além de ter a capacidade de armazenar logs em uma pasta específica.

O problema é que o processo deve ser iniciado por um usuário que esteja no sistema. Isso pode ser feito através da área de trabalho ou WinRm. Se o servidor for executado sob a conta do sistema ou até mesmo como administrador, mas o usuário não estiver logado, então o Server.jar não conseguirá ler o eula.txt e não iniciará.

Podemos habilitar o login automático no sistema adicionando três entradas ao 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

Isso não é seguro. O login e a senha são informados aqui em texto simples, por isso, para rodar o servidor, você deve criar um usuário separado que tenha acesso no nível de usuário ou em um grupo ainda mais restrito. Usar o administrador padrão para isso é fortemente desaconselhado.

Já entendemos o login automático. Agora precisamos registrar uma nova tarefa para o servidor. Vamos executar um comando do Powershell, então ficará assim:

$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 compilar o módulo

Agora vamos organizar tudo em módulos que poderão ser utilizados depois. Todo o código dos scripts prontos está aqui, importe e utilize.

Tudo o que foi descrito acima pode ser usado separadamente, caso você não queira se preocupar com módulos.

Start-Minecraft

Primeiro, faremos um módulo que apenas executará o script, que ouvirá e registrará a saída padrão.

No bloco de parâmetros, ele solicita de qual pasta iniciar o Minecraft e onde armazenar o log.

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 o Minecraft deve ser iniciado assim:

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

Agora vamos para o Handler.ps1 pronto para uso

Para que nosso script possa aceitar parâmetros quando chamado, também precisamos especificar o bloco de parâmetros. Observe que ele executa o Oracle Java; se você estiver usando outra distribuição, precisará alterar o caminho para o executável.

param (
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$type,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$MinecraftPath,
 
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string]$StandardOutput
)
 
Set-Location $MinecraftPath
 
function Restart-Minecraft {
 
    Write-host "=============== Iniciando o servidor de jogo incrível ============"
 
    $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 início:" $global:Process.StartTime
 
    Write-host "Código de saída:" $global:Process.ExitCode
    
    Write-host "Hora de saída:" $global:Process.ExitTime
 
    Write-host "=============== Servidor de jogo incrível parado ============="
}
 
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

O script é praticamente uma duplicata de Start-Minecraft, exceto que apenas registra uma nova tarefa. Aceita os mesmos argumentos. O nome de usuário, se não for especificado, assume o atual.

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

No bloco de parâmetros, o script aceita os parâmetros Username e Password. Se o Username não for especificado, usa o nome do usuário atual.

function Set-Autologon {
 
    param (
        [Parameter(
        HelpMessage="Nome de usuário para autologon")]
        $Username = $env:USERNAME,
 
        [Parameter(Mandatory=$true,
        HelpMessage="Senha do usuário")]
        [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 ativará o logon automático do usuário."
 
    }
    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 foi configurado com sucesso."
 
}

A execução deste script se parece com isto:

Set-Autologon -Password "SenhaEmTextoClaro"

Como usar

Agora vamos ver como o autor usa tudo isso. Como corretamente configurar um servidor público Minecraft no Windows. Vamos começar do começo.

1. Criar o usuário

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

2. Registrar a tarefa para executar o script

Você pode registrar usando o módulo assim:

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

Ou usar os recursos padrões:

$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. Ativar o logon automático e reiniciar a máquina

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

Conclusão

O autor fez o script, inclusive para si mesmo, portanto, ficará feliz em ouvir suas sugestões de melhorias. O autor espera que todo esse código tenha sido minimamente útil para você e que o artigo seja interessante.

O script ideal para iniciar um servidor Minecraft

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster