O autor adora o jogo e ele próprio é administrador de um pequeno servidor “puramente para amigos”. Como é comum entre os amadores, tudo no servidor é modificado, o que acarreta instabilidade e, consequentemente, travamentos. Como o autor do Powershell conhece melhor a localização das lojas em sua rua, ele decidiu fazer "Melhor script para lançar o Minecraft 2020" O mesmo script serviu de base para o modelo em
Os comandos que precisamos
Registro alternativo
Um dia, depois de instalar mais alguns mods, descobri que o servidor, aparentemente, estava travando sem declarar guerra. O servidor não gravou erros no last.log ou no debug, e o console, que em teoria deveria ter escrito esse erro e parado, foi fechado.
Se ele não quer escrever, não precisa. Temos Powershell com cmdlet T-objeto, que pega um objeto e o envia para um arquivo e para o console ao mesmo tempo.
.handler.ps1 | Tee-Object .StandardOutput.txt -Append
Dessa forma, o Powershell irá pegar o StandardOutput e gravá-lo em um arquivo. Não tente usar Iniciar-Processoporque retornará System.ComponentModel.Component e não StandardOutput, e -RedirectStandardOutput impossibilitará a entrada no console, que é o que queremos evitar.
Lançar argumentos
Após instalar o mesmo par de mods, o autor percebeu que o servidor também não tinha RAM suficiente. E isso requer a mudança dos argumentos de lançamento. Em vez de alterá-los sempre no start.bat, que todo mundo usa, basta usar este script.
Como Tee-Object só lê StandardOutput quando o executável é chamado de "Just Like This", você terá que fazer outro script. Este script será lançado pelo próprio Minecraft. Vamos começar com os argumentos.
Para se entregar à preguiça definitiva no futuro, o roteiro deve coletar argumentos de lançamento instantaneamente. Para fazer isso, vamos começar procurando a versão mais recente forjar.
$forge = ((Get-ChildItem | Where-Object Name -Like "forge*").Name | Sort-Object -Descending) | Select-Object -last 1
Usando sort-object, sempre pegaremos o objeto com o maior número, não importa quantos deles você coloque lá. 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 uma string.
$ram = ((Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb)
$xmx = "-Xms" + $ram + "G"
Reinicialização automática correta
O autor viu arquivos .bat de outras pessoas, mas não levou em consideração o motivo pelo qual o servidor foi interrompido. Isso é inconveniente, e se você só precisar alterar o arquivo mod ou excluir algo?
Agora vamos fazer uma reinicialização adequada. O autor já encontrou scripts estranhos que reiniciavam o servidor, independentemente do motivo do desligamento do servidor. Usaremos o código de saída. Java usa 0 como sucesso, então vamos dançar a partir daqui.
Primeiro, vamos criar uma função que irá reiniciar o servidor caso ele falhe.
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 seja encerrado normalmente em seu próprio console usando o comando /stop.
Se decidirmos automatizar tudo, seria bom coletar a data de início, a data de conclusão e também o motivo da conclusão.
Para fazer isso, escrevemos o resultado do Start-Process em uma variável. No script fica assim:
$global:Process = Start-Process -FilePath "C:Program Files (x86)common filesOracleJavajavapath_target_*java.exe" -ArgumentList "$xmx -server -jar $forge nogui" -Wait -NoNewWindow -PassThru
E então escrevemos os resultados em um arquivo. Isto é o que nos é retornado na variável:
$global:Process.StartTime
$global:Process.ExitCode
$global:Process.ExitTime
Tudo isso pode ser adicionado a um arquivo usando Add-Content. Depois de pentear um pouco, obtemos esse script e vamos chamá-lo 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 criar um script que inicia o manipulador.
Inicialização correta
O autor deseja executar diferentes versões do Minecraft a partir de qualquer caminho em um módulo e também poder armazenar logs em uma pasta específica.
O problema é que o processo deve ser iniciado por um usuário logado no sistema. Isso pode ser feito através do desktop ou WinRm. Se você executar o servidor como usuário do sistema ou mesmo como administrador, mas não fizer login, o Server.jar nem conseguirá ler o eula.txt e iniciar.
Podemos ativar o login automático 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
Não é seguro. O login e a senha são indicados aqui em texto simples, portanto, para iniciar o servidor é necessário criar um usuário separado que tenha acesso no nível do usuário, ou em um grupo ainda mais restrito. Não é estritamente recomendado usar um administrador padrão para isso.
Resolvemos o login automático. Agora você precisa registrar uma nova tarefa para o servidor. Executaremos o 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
Montagem do módulo
Agora vamos colocar tudo em módulos que poderão ser usados posteriormente. Todo o código dos scripts prontos está aqui, importe e use.
Você pode usar tudo descrito acima separadamente se não quiser se preocupar com módulos.
Iniciar-Minecraft
Primeiro, vamos criar um módulo que não fará nada além de executar um script que ouvirá e registrará 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á iniciar o Minecraft assim:
Start-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft"
Agora vamos passar para o Handler.ps1 pronto para uso
Para que nosso script aceite parâmetros quando chamado, também precisamos especificar um bloco de parâmetros. Observe que ele executa Oracle Java; se você estiver usando uma distribuição diferente, precisará 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 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
O script é praticamente igual ao 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 nome 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
Registro-Autologon
No bloco de parâmetros, o script aceita os parâmetros Nome de usuário e Senha. Se o nome de usuário não for especificado, o nome do usuário atual será 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: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 execução deste script é semelhante a esta:
Set-Autologon -Password "PlaintextPassword"
Como usar
Agora vejamos como o próprio autor usa tudo isso. Como implantar corretamente um servidor público do Minecraft no Windows. Vamos começar desde o início.
1. Crie um usuário
$pass = Get-Credential
New-LocalUser -Name "MinecraftServer" -Password $pass.Password -AccountNeverExpires -PasswordNeverExpires -UserMayNotChangePassword
2. Registre a tarefa para executar o script
Você pode se registrar usando um módulo como este:
Register-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft" -User "MInecraftServer" -TaskName "MinecraftStarter"
Ou use ferramentas padrão:
$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. Ative o login automático e reinicie a máquina
Set-Autologon -Username "MinecraftServer" -Password "Qw3"
Realização
O autor fez o roteiro, inclusive para si mesmo, portanto, terá prazer em ouvir suas sugestões para melhorar o roteiro. O autor espera que todo esse código tenha sido pelo menos minimamente útil para você e que o artigo seja interessante.
Fonte: habr.com