O script perfeito de inicialização do servidor Minecraft



O autor gosta muito do jogo, e ele próprio é o administrador de um pequeno servidor "apenas para amigos". Como de costume entre amadores, tudo é modulado no servidor, e isso implica em instabilidade do trabalho e como resultado da queda. Como o autor conhece Powershell melhor do que a localização das lojas em sua rua, ele decidiu criar "O melhor script para lançar o Minecraft 2020 ". O mesmo script serviu de base para o modelo no mercado Ruvds . Mas todas as fontes já estão no artigo. Agora, em ordem, como tudo aconteceu.

Precisamos de equipes


Log alternativo


Depois de colocar mais alguns mods, descobri que o servidor parece travar sem declarar guerra. O servidor não gravou erros no arquivo latest.log ou depuração, e o console, que deveria gravar e interromper esse erro, foi fechado.

Não quer escrever - não há necessidade. Temos o PowerShell com o cmdlet Tee-Object , que pega um objeto e o exibe em um arquivo e no console ao mesmo tempo.

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

Dessa forma, o Powershell pegará o StandardOutput e o gravará em um arquivo. Não tente usar o Start-Process , pois ele retornará System.ComponentModel.Component, não StandardOutput e -RedirectStandardOutput impossibilitará a entrada no console, o que queremos evitar.

Argumentos de lançamento


Colocando o mesmo par de mods, o autor notou que o servidor também não possui RAM. E isso precisa alterar os argumentos de inicialização. Em vez de alterá-los sempre no start.bat, que todos usam, basta usar este script.

Como Tee-Object lê StandardOutput somente quando o executável é chamado “Right So”, você terá que criar outro script. Este script executará o próprio minecraft. Vamos começar com os argumentos.

Para entrar em preguiça final no futuro, o script deve coletar argumentos de início em tempo real. Para fazer isso, comece procurando a versão mais recente do forge .

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

Com a ajuda do objeto de classificação, sempre levaremos o objeto com o maior dígito, não importa o quanto você os coloque lá. A preguiça final.

Agora você precisa atribuir memória ao servidor. Para fazer isso, pegue a quantidade de memória do sistema e escreva sua quantidade em 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 não levou em consideração o motivo pelo qual o servidor foi parado. É inconveniente que, se você só precise alterar o arquivo mod ou excluir algo?
Agora vamos reiniciar corretamente. O autor já se deparou com scripts estranhos que reiniciam o servidor, apesar de o servidor ter sido desligado. Usaremos o código de saída. Java usa 0 como uma conclusão bem-sucedida, portanto, vamos dançar.

Primeiro, crie uma função que reiniciará o servidor se ele não for concluído.

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 loop até que o servidor do seu próprio console seja desligado normalmente usando o comando / stop.

Se todos nós decidirmos automatizar, seria bom coletar a data de lançamento, a conclusão e o motivo da conclusão.

Para fazer isso, escrevemos o resultado do processo inicial em uma variável. No script, fica assim:

$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

E então escrevemos os resultados em um arquivo. Aqui está o que retorna para nós na variável:

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

Tudo isso usando Add-Content pode ser adicionado ao arquivo. Depois de pentear um pouco, obtemos um script e o chamamos de 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 vamos executar o script com o lançamento do manipulador.

Inicialização adequada


O autor deseja que um módulo inicie minecraft de várias versões a partir de qualquer caminho e também seja capaz de colocar logs em uma pasta específica.

O problema é que o processo deve ser iniciado pelo usuário que está no sistema. Isso pode ser feito na área de trabalho ou no WinRm. Se você iniciar o servidor em nome do sistema ou mesmo do administrador, mas não fizer o login, o Server.jar nem poderá ler o eula.txt e iniciar.

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

Não é seguro. O login e a senha são indicados aqui em texto sem formatação, portanto, é necessário iniciar um usuário individual que tenha acesso no nível do usuário ou em um grupo ainda mais restrito para iniciar o servidor. Usar um administrador padrão para isso é altamente desencorajado.

Com entrada automática resolvida. Agora você precisa registrar uma nova tarefa no servidor. Como executaremos o comando do Powershell, ele ficará assim:

$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

Juntando o módulo


Agora vamos transformar tudo em módulos que podem ser usados ​​posteriormente. Todo o código de scripts prontos está aqui, importe e use.

Você pode usar tudo o que foi descrito acima separadamente, se não quiser se preocupar com os módulos.

Iniciar minecraft


Primeiro, criaremos um módulo que apenas fará isso, executaremos um script que ouvirá e gravará a saída padrão.

No bloco de parâmetros, ele pergunta de qual pasta iniciar o minecraft e onde colocar 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 você precisará executar minecraft assim:

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

Agora vamos passar para o Handler.ps1 pronto para usar.

Para que nosso script possa aceitar parâmetros quando chamado, também precisamos especificar um bloco de parâmetros. Observe que ele inicia o Oracle Java; se você usar uma distribuição diferente, será necessário alterar o caminho para o arquivo executável.

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

Registrar-minecraft


O script praticamente repete o Start-Minecraft, exceto que ele registra apenas uma nova tarefa. Aceita os mesmos argumentos. O nome de usuário, se não 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

Register-autologon


No bloco de parâmetros, o script aceita o parâmetro Nome de usuário e Senha. Se o nome de usuário não foi especificado, o nome do usuário atual é usado.

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."
 
}

A execução desse script se parece com o seguinte:

Set-Autologon -Password "PlaintextPassword"

Como usar


Agora vamos considerar como o próprio autor usa tudo isso. Como implantar o servidor público Minecraft no Windows. Vamos começar desde o começo.

1. Crie um usuário

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

2. Registre a tarefa de execução do script.Você

pode se registrar usando o módulo, da seguinte maneira:

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

Ou use as ferramentas padrão:

$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. Ligue o login automático ao sistema e reinicie 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 para melhorar o script. O autor espera que todo esse código seja pelo menos minimamente útil para você, e o artigo é interessante.


All Articles