著者はこのゲームが大好きで、自身も「純粋に友達専用」の小さなサーバーの管理者です。 アマチュアの間ではよくあることですが、サーバー上のすべてが改造されており、これにより不安定性が生じ、その結果、クラッシュが発生します。 Powershell の作成者は、通りにある店舗の場所をよく知っているため、「」を作成することにしました。Minecraft 2020 を起動するためのベスト スクリプト」 同じスクリプトがテンプレートの基礎として機能しました。
必要なコマンド
代替ロギング
ある日、さらにいくつかの MOD をインストールした後、明らかに宣戦布告せずにサーバーがクラッシュしていることに気づきました。 サーバーは、latest.log やデバッグにエラーを書き込まず、理論上はこのエラーを書き込んで停止するはずだったコンソールが閉じられました。
書きたくないなら、書く必要はない。 コマンドレットを備えたPowershellがあります T オブジェクト、オブジェクトを取得し、それをファイルとコンソールに同時に出力します。
.handler.ps1 | Tee-Object .StandardOutput.txt -Append
このようにして、Powershell は StandardOutput を取得してファイルに書き込みます。 使おうとしないでください 開始プロセスStandardOutput ではなく System.ComponentModel.Component が返され、-RedirectStandardOutput によってコンソールに入ることができなくなるため、これは避けたいことです。
起動引数
同じ MOD のペアをインストールした後、作成者はサーバーにも十分な RAM がないことに気づきました。 そして、これには起動引数を変更する必要があります。 誰もが使用する start.bat で毎回変更する代わりに、このスクリプトを使用するだけです。
Tee-Object は、実行可能ファイルが "Just Like This" と呼ばれる場合にのみ StandardOutput を読み取るため、別のスクリプトを作成する必要があります。 このスクリプトは Minecraft 自体によって起動されます。 議論から始めましょう。
将来的に究極の怠惰にふけるためには、スクリプトは実行中に起動引数を収集する必要があります。 これを行うには、まず最新バージョンを検索します。 偽造する.
$forge = ((Get-ChildItem | Where-Object Name -Like "forge*").Name | Sort-Object -Descending) | Select-Object -last 1
sort-object を使用すると、そこに配置したオブジェクトの数に関係なく、常に最大の番号を持つオブジェクトが取得されます。 究極の怠惰。
次に、サーバーにメモリを割り当てる必要があります。 これを行うには、システム メモリの量を取得し、その量を文字列に書き込みます。
$ram = ((Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb)
$xmx = "-Xms" + $ram + "G"
正しい自動再起動
著者は他の人からの .bat ファイルを見ましたが、サーバーが停止した理由は考慮されていませんでした。 これは不便です。MOD ファイルを変更するか、何かを削除する必要がある場合はどうすればよいでしょうか?
では、適切に再起動してみましょう。 著者は以前、サーバーがシャットダウンした理由に関係なく、サーバーを再起動する奇妙なスクリプトに遭遇しました。 終了コードを使用します。 Java は 0 を成功として使用するので、ここから踊ります。
まず、サーバーに障害が発生した場合にサーバーを再起動する関数を作成しましょう。
function Get-MinecraftExitCode {
do {
if ($global:Process.ExitCode -ne 0) {
Write-Log
Restart-Minecraft
}
else {
Write-Log
}
} until ($global:Process.ExitCode -eq 0)
}
スクリプトは、サーバーが /stop コマンドを使用して独自のコンソールから正常にシャットダウンするまで、ループ内に残ります。
すべてを自動化することにした場合は、開始日、完了日、完了の理由も収集するとよいでしょう。
これを行うには、Start-Process の結果を変数に書き込みます。 スクリプトでは次のようになります。
$global:Process = Start-Process -FilePath "C:Program Files (x86)common filesOracleJavajavapath_target_*java.exe" -ArgumentList "$xmx -server -jar $forge nogui" -Wait -NoNewWindow -PassThru
そして結果をファイルに書き込みます。 これは変数で返されるものです。
$global:Process.StartTime
$global:Process.ExitCode
$global:Process.ExitTime
これらすべては、Add-Content を使用してファイルに追加できます。 少し調べてみると、このスクリプトが得られます。これを 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
次に、ハンドラーを起動するスクリプトを作成しましょう。
正しい起動
作成者は、XNUMX つのモジュール内の任意のパスから異なるバージョンの Minecraft を実行し、特定のフォルダーにログを保存できるようにしたいと考えています。
問題は、システムにログインしているユーザーがプロセスを開始する必要があることです。 これはデスクトップまたは WinRm 経由で実行できます。 システム ユーザーまたは管理者としてサーバーを実行しているが、ログインしていない場合、Server.jar は eula.txt を読み取って起動することさえできません。
レジストリに XNUMX つのエントリを追加することで、自動ログインを有効にできます。
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
安全ではありません。 ここではログインとパスワードが平文で示されているため、サーバーを起動するには、ユーザー レベル、またはさらに狭いグループでアクセス権を持つ別のユーザーを作成する必要があります。 これに標準の管理者を使用することは厳密には推奨されません。
自動ログインを整理しました。 次に、サーバーに新しいタスクを登録する必要があります。 Powershell からコマンドを実行するので、次のようになります。
$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
モジュールの組み立て
それでは、後で使用できるモジュールにすべてを入れてみましょう。 既製のスクリプトのコードはすべてここにあり、インポートして使用できます。
モジュールに煩わされたくない場合は、上記のすべてを個別に使用できます。
スタート-Minecraft
まず、標準出力をリッスンして記録するスクリプトを実行するだけのモジュールを作成しましょう。
パラメーター ブロックでは、どのフォルダーから Minecraft を起動するか、ログをどこに置くかを尋ねます。
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
そして、次のように Minecraft を起動する必要があります。
Start-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft"
次に、すぐに使用できる Handler.ps1 に移りましょう。
スクリプトが呼び出されたときにパラメーターを受け入れるためには、パラメーター ブロックも指定する必要があります。 Oracle Java が実行されるため、別のディストリビューションを使用している場合は、実行可能ファイルへのパスを変更する必要があることに注意してください。
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
登録-Minecraft
このスクリプトは、新しいタスクを登録するだけであることを除いて、Start-Minecraft と実質的に同じです。 同じ引数を受け入れます。 ユーザー名が指定されていない場合、現在のユーザー名が使用されます。
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
登録-自動ログオン
パラメーター ブロックでは、スクリプトはユーザー名とパスワードのパラメーターを受け入れます。 ユーザー名が指定されていない場合は、現在のユーザーの名前が使用されます。
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."
}
このスクリプトを実行すると次のようになります。
Set-Autologon -Password "PlaintextPassword"
使用方法
それでは、著者自身がこれらすべてをどのように使用するかを見てみましょう。 Windows にパブリック Minecraft サーバーを適切にデプロイする方法。 最初から始めましょう。
1. ユーザーを作成する
$pass = Get-Credential
New-LocalUser -Name "MinecraftServer" -Password $pass.Password -AccountNeverExpires -PasswordNeverExpires -UserMayNotChangePassword
2. スクリプトを実行するタスクを登録します
次のようなモジュールを使用して登録できます。
Register-Minecraft -Type Forge -LogFile "C:minecraftstdout.txt" -MinecraftPath "C:minecraft" -User "MInecraftServer" -TaskName "MinecraftStarter"
または、標準ツールを使用します。
$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. 自動ログインを有効にしてマシンを再起動します。
Set-Autologon -Username "MinecraftServer" -Password "Qw3"
Завершение
著者は自分自身のためにも含めてスクリプトを作成したため、スクリプトを改善するためのあなたの提案に喜んで耳を傾けます。 著者は、このコードすべてが少なくとも皆さんにとって最低限の役に立つこと、そしてこの記事が興味深いものであったことを願っています。
出所: habr.com