systemd + screen で Minecraft サーバを管理する
最近は暇な時間に tskserver という Minecraft サーバの環境をほじくり回しています. その一環で Minecraft サーバを systemd で管理するようにしました.
systemd で管理することのメリットとしては,systemd は頭がよいので,なんか良い感じに依存関係を考慮しながら起動順序を調整などをしてくれることがあげられます.
Minecraft のサーバは少し曲者で,Nginx や他のデーモンのようにシグナルを受け取ってくれるわけではないので,systemd の Unit file を書くときはサーバを安全に終了する (stop
コマンドを走らせる) 方法を考えつつやる必要があります.
この記事では,GNU screen を使って systemd から Minecraft サーバにコマンドを投げられるようにして安全な終了を実現します.
環境
OS は Ubuntu Server 16.04.4 LTS,Minecraft サーバの実装は Spigot です.たぶん公式サーバでも起動時の引数に nogui をつければいけるはず.
サーバのディレクトリはひとまず /home/k/tskserver
に置いていてユーザ k
で動かしています.
この記事でできること
- Minecraft サーバを systemd で管理する
- Minecraft サーバを 30 秒のカウントダウンとともに安全に終了できる
- システム起動時に自動的に Minecraft サーバを起動できる
- システム終了時でもネットワーク接続を維持しつつカウントダウンを待ち,Minecraft サーバを安全に終了できる
Minecraft サーバにコマンドを投げる
ここで GNU screen を使います.
screen は detached なセッションに対して screen -S <session_name> -X stuff 'hogehoge'
とコマンドを打つと session_name なセッションに対して hogehoge を標準入力 (?) として投げられるので便利です.
今回はこれを終了時に使います.具体的には終了時に save-all
と stop
コマンドを投げるようにします.
systemd の Unit file を書く
おもむろに /etc/systemd/system/minecraft.service
を作成し,以下を書きます.
[Unit] Description=Minecraft Server After=network-online.target [Service] User=k Group=k TimeoutStopSec=120 WorkingDirectory=/home/k/tskserver ExecStart=/usr/bin/screen -Dm -S tskserver /usr/bin/java -Xms512M -Xmx5G -jar /home/k/tskserver/spigot.jar ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 30s\015" ExecStop=/bin/sleep 10 ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 20s\015" ExecStop=/bin/sleep 10 ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 10s\015" ExecStop=/bin/sleep 5 ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 5s\015" ExecStop=/bin/sleep 5 ExecStop=/usr/bin/screen -S tskserver -X stuff "save-all\015" ExecStop=/usr/bin/screen -S tskserver -X stuff "stop\015" Restart=always [Install] WantedBy=multi-user.target
[Unit]
After=network-online.target
ネットワークがオンラインになってからこの Unit を起動するようにします. 同様にシステム終了時はこの Unit が終了してからネットワークが落ちるように順序を考慮してくれるようになります.
tskserver は fluentd を使ってログを収集しているのでこれに加えて After=fluentd.service
をつけていて,Minecraft サーバが終了するまで fluentd も落ちないようになっています.
[Service]
TimeoutStopSec=
終了時のタイムアウト時間を秒単位で指定します.
systemd は終了するぞってなったときに対象プロセスが終了するのを待ちますが,一定時間で SIGTERM が投げられて強制終了されてしまいます.
デフォルトは 90 秒なので,これよりも長くカウントダウンを設定したかったり,プラグインを入れすぎて stop
に時間がかかりすぎたりする場合は設定しておきましょう.
ExecStop=
終了時に実行するコマンドです.複数指定すると上から順に実行します.
screen -S tskserver -X stuff "say hello\015"
は,セッション名 tskserver のセッションに対して "say hello" と改行コード (0x0A
, \015
)を入力として送ります.改行コードなしだったり 8 進数以外だとコマンドが実行されないので注意.
Restart=always
サーバが勝手に終了した場合は常に自動で再起動するようにします.
次
バックアップなどをいい感じにしたい.あと冗長化構成組んでみたいけど需要あるんだろうか...?
tskserver はこれからも末永く運営していくつもりで,誰でも入れるサーバなので暇なひとは遊びに来てくれ~.[話を聞きに行く↗]
Let's Encrypt の証明書をワイルドカードなやつにして自動更新できるようにした
2018 年 3 月,ついに Let's Encrypt がワイルドカードな証明書の発行に対応したので,所有するサーバの証明書をワイルドカードなものにリプレイスしてみました. 今まではサブジェクト代替名でサブドメインを列挙するスタイルをとっていて地味に面倒だったのと,証明書を読むと internal 向けのドメインがバレちゃうというのがあり,ワイルドカードな証明書に置き換えることでこれらを解決することができました.
この記事のゴール
この記事では以下について述べます.今回作業する環境は ArchLinux ですが,certbot と certbot の cloudflare プラグインのパッケージさえあれば他の OS も動くと思います.
ksswre.net
と*.ksswre.net
の証明書を manual モードで取得する- 上で取得した証明書を自動更新できるようにする (自動更新のため CloudFlare の Free プランを併用)
試行錯誤をしながら作業を行ったので 1 時間弱くらいかかりましたが,最終的にはワイルドカードな証明書が certbot renew
で自動更新できるようになりました.
前提
certbot を使います.ArchLinux なので pacman -S certbot
すると certbot が降ってきた気がします.なければいれましょう.
ワイルドカードな証明書を取得する
おもむろに以下のコマンドをうちます.ワイルドカード証明書を取得するには dns-01 認証が必要なので,manual モードにして認証形式を手動で設定します.
また,2018 年 4 月現在でワイルドカード証明書を発行するには ACME v2 が必要なので --server
オプションを付けて認証サーバを変更します.メールアドレスや IP アドレスを記録するが良いかなどとインタラクティブな操作で確認されるので Y か N を打って答えます.
# certbot certonly --manual -d '*.ksswre.net' -d ksswre.net -m 'mail@example.com' --agree-tos --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory
しばらくすると以下のような画面がでます.これは dns-01 認証のためのもので,ドメインを本当に所有しているかどうか DNS の TXT にワンタイムトークンを追加することで認証します.
------------------------------------------------------------------------------- Please deploy a DNS TXT record under the name _acme-challenge.ksswre.net with the following value: XXXXXXXXXXXXXXXXXXXXXXXXXXXX Before continuing, verify the record is deployed. ------------------------------------------------------------------------------- Press Enter to Continue
ドメイン管理画面を開き (以下は StarDomain の例),ワンタイムトークンを DNS の TXT レコードに追記します.
追記したら Enter を押します.うまいこといくと以下のような表示があるはずです.
Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/ksswre.net-0002/privkey.pem Your cert will expire on 2018-07-05. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
これより,サーバ証明書などが取得できたので nginx.conf
を編集し,証明書を新しいものに切り替えます.nginx.conf
の抜粋.
ssl_certificate /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ksswre.net-0002/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/ksswre.net-0002/chain.pem;
Nginx を再起動すると,うまいこといってるのがわかります.Postfix や Dovecot の設定なども同様にお忘れなくやりましょう.
このままでは自動更新できない
証明書が更新できるか確認しましょう.--force-renewal
オプションを付けて強制更新モードにして一旦走らせてみると,エラーでコケることがわかります.
# certbot renew --force-renewal Saving debug log to /var/log/letsencrypt/letsencrypt.log ------------------------------------------------------------------------------- Processing /etc/letsencrypt/renewal/ksswre.net-0002.conf ------------------------------------------------------------------------------- Could not choose appropriate plugin: The manual plugin is not working; there may be problems with your existing configuration. The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',) Attempting to renew cert (ksswre.net-0002) from /etc/letsencrypt/renewal/ksswre.net-0002.conf produced an unexpected error: The manual plugin is not working; there may be problems with your existing configuration. The error was: PluginError('An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively.',). Skipping. All renewal attempts failed. The following certs could not be renewed: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem (failure)
manual モードの場合はインタラクティブな操作が必要で certbot renew
で更新するには --manual-auth-hook
オプションで認証用ホックを自前で用意する必要があるそうです.ホックを自前で書くのは面倒なので調べてみたら,certbot の CloudFlare プラグインを使う方法があるそうです.以下のサイトが有用でしたので参考にさせていただきました.
a244.hateblo.jp
CloudFlare プラグインを併用して自動更新する
CloudFlare プラグインを使うためには,既存のネームサーバを CloudFlare に変更する必要がありますが,CloudFlare に変更すると DNS TXT レコードの書き換えと dns-01 認証をプラグインが全て自動で行ってくれます.便利です.CloudFlare は個人サイトの規模であれば Free プランで十分なので,無料で運用できます.
このプラグインを使うには,ArchLinux では新しいパッケージをインストールする必要があるのでインストールしておきます.
# pacman -S certbot-cloudflare
上のサイトを参考にしながら CloudFlare でアカウントをとり,ネームサーバを CloudFlare に変更し,管理パネルの Get your API key から Global API Key を取得し,certbot に設定しておきます.CloudFlare の CDN (Proxy) は今回は必要ないのでオフにしておき,ネームサーバだけ有効にしておきます.
設定ができたら,certbot で上のセクションで取得した証明書をリニューアルします.以下のコマンドを走らせます.
# certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -d ksswre.net -d '*.ksswre.net' --server https://acme-v02.api.letsencrypt.org/directory
プラグインとして CloudFlare 用のものが選択されていることがわかります.
Plugins selected: Authenticator dns-cloudflare, Installer None Cert not yet due for renewal
しばらくすると,既に同じドメインで取得した証明書をリプレイスして良いか聞いてくるので,そうしてもらいます. そのあと少し放置すると,CloudFlare のネームサーバを通して dns-01 認証を行われ,正常に証明書が更新されます. この間,上のセクションで使用した manual モードのようにインタラクティブな操作は発生せず,全て自動で進みます.便利.
You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry. (ref: /etc/letsencrypt/renewal/ksswre.net-0002.conf) What would you like to do? ------------------------------------------------------------------------------- 1: Keep the existing certificate for now 2: Renew & replace the cert (limit ~5 per 7 days) ------------------------------------------------------------------------------- Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2 Renewing an existing certificate Performing the following challenges: dns-01 challenge for ksswre.net dns-01 challenge for ksswre.net Waiting 10 seconds for DNS changes to propagate Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/ksswre.net-0002/privkey.pem Your cert will expire on 2018-07-05. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
これで CloudFlare プラグインを使ってワイルドカードな証明書が自動更新できるようになりました.
# certbot renew --force-renewal Saving debug log to /var/log/letsencrypt/letsencrypt.log ------------------------------------------------------------------------------- Processing /etc/letsencrypt/renewal/ksswre.net-0002.conf ------------------------------------------------------------------------------- Plugins selected: Authenticator dns-cloudflare, Installer None Renewing an existing certificate Performing the following challenges: dns-01 challenge for ksswre.net dns-01 challenge for ksswre.net Waiting 10 seconds for DNS changes to propagate Waiting for verification... Cleaning up challenges ------------------------------------------------------------------------------- new certificate deployed without reload, fullchain is /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Congratulations, all renewals succeeded. The following certs have been renewed: /etc/letsencrypt/live/ksswre.net-0002/fullchain.pem (success) -------------------------------------------------------------------------------
この後は,certbot renew
を定期的に投げれば良いので,crontab や systemd-timer を使って定期的にコマンドが走るようにします.これで自動更新は完成です.
キャプチャボード Blackmagic Design Intensity Shuttle を買った
先日 HDMI キャプチャボード Intensity Shuttle For USB 3.0 を購入しました.
このキャプチャボードは 2012 年に発売されたもので少々古いですが,HDMI,RCA 端子 や S 端子とそれらのパススルーに対応しているのが特徴です. またキャプチャ用ソフトウェアが Windows だけでなく Mac にも対応していて,Mac 対応で HDMI キャプチャできる数少ない商品のうちの一つと思います. 対応コーデックなどの詳しい仕様はこのページを参照してください.
ジャーン pic.twitter.com/d33TBpBLRG
— k5342 (@k5342) 2018年2月1日
できたこと
- HDMI 出力の PC 画面のキャプチャ (1080p30, 1080i, 720p, etc.)
- Nintendo Switch の画面キャプチャとパススルー (720p)
- ゲームキューブの画面・音声キャプチャと HDMI 出力
- キャプチャした映像を配信ソフトウェア OBS で配信・録画する
できないこと
- 1080p60 でキャプチャ (Nintendo Switch で 1080p キャプチャできないのはこのせい)
- VGA 出力の PC 画面のキャプチャ
- アップスキャンコンバータ (VGA -> HDMI) を使って変換すればいけるかも?
- 電源供給だけでパススルーする
- キャプチャボードを複数ソフトウェアから利用する
- 付属のキャプチャソフトで録画しながら OBS で配信できない
未確認
使い方の流れ
キャプチャを行う PC の準備
公式サイトからドライバとキャプチャ用ソフトウェアをダウンロードします. 少々分かりにくいですが,ソフトウェアアップデート欄にある Desktop Video をダウンロードすれば良いです. ダウンロードしたらセットアップを起動し,ガイドに従ってインストールを行います.
インストールが終わったら,Intensity Shuttle を PC に接続し,キャプチャしたい映像ソースを接続します. 映像ソースによっては出力設定を変更する必要があるので,それについては以下に個別でまとめるので参照してください. 接続後は Desktop Video Setup というアプリケーションを起動し,Intensity Shuttle のどのポートから信号が入力されるかを選択します.
その後 Blackmagic Media Express というアプリケーションを開き,正常にキャプチャできているか確認します. 正常に設定ができていて,キャプチャボードが映像ソースを認識できれば,このアプリケーションを開いた段階でやっとパススルーが使えるようになります.
他のパソコン画面のキャプチャ
Windows の場合
Windows は HDMI 出力を Intensity Shuttle の HDMI IN 端子に接続するだけで OK で,勝手に解像度を認識してくれるようです.
Mac の場合
Mac はシステム環境設定で出力設定を変更する必要があります.
- HDMI 出力を Intensity Shuttle の HDMI IN 端子に接続します
- システム環境設定→ディスプレイの設定を開きます
- 解像度の設定で BMD HDMI を選択します
- ラジオボタンを ディスプレイに最適 から 変更 に変更し,出力解像度を 1080i か 720p に変更します
Nintendo Switch のキャプチャ
Nintendo Switch の画面をキャプチャする場合は,出力解像度の設定を変更したうえで接続します. 設定 → テレビ出力 → テレビの解像度 と移動し,値を 自動 から 720p に変更します.
ゲームキューブのキャプチャ
なんかつなぐだけでできた. 以前どこかの記事で「ゲームキューブは独自の信号拡張を行っていてこのキャプチャボードだとキャプチャできない」ってみた気がしたので代替として IO-DATA の GV-USB2 を使っていましたが,あっさりできたわ.しかし PS2 や N64 に対応しているかは未確認です.
Demo
スプラトゥーン 2 のプレイ風景を OBS で録画してみました.
不満点
キャプチャボードが時折クラッシュ?というか,キャプチャされる映像が真っ黒になることがあります. 他にも,付属のソフトウェアでキャプチャボードが認識されなくなることがあります.
また,その状態で USB ケーブルを抜き差しすると「前回のドライバのインスタンスがメモリに残っている」旨のエラー (code 38) が発生し,上記の症状が改善されないことがあります. これを解決する方法はキャプチャを行う PC を再起動するしかないとされていて,ちょっと不便です. これらは Windows 上でキャプチャした場合に発生したのですが,もしかすると Mac だと違うかもしれません.
ストアからインストールした Ubuntu で LANG=ja_JP.UTF-8 を使う
最近 ThinkPad を購入し,Windows で遊んでいます.
Fall Creators Update (Build 16215) 以降は Windows Store から Ubuntu がインストールできるようになったそうです.超便利ですよね.
それで,以下のガイドに従ってストアからインストールして dotfiles を流し込んだところ,日本語が化けました. 右が WSL のターミナル,左が MSYS2 のターミナルで Windows ファイルシステムの同一ディレクトリを表示していて,日本語文字が ??? に化けていることがわかります.
2018-01-28 23:34 追記
dotfiles 中の .zshrc が LANG=ja_JP.UTF-8
と指定していたようで,システム上には ja_JP.UTF-8
なロケールが有効化されてないため,これが文字化けの原因となっていました.
LANG=ja_JP.UTF-8
を使えるようにしてデフォルト設定にする
- 適当なエディタで
/etc/locale.gen
を開く ja_JP.UTF-8
がコメントアウトされているので#
を削除して上書き保存sudo locale-gen
を実行- 適当なエディタで
/etc/locale.conf
を開き (無ければ作成) 以下を書いて保存し,再起動
LANG=ja_JP.UTF-8
これで僕の環境では日本語が表示できるようになりました.
しかし完全に文字化けが治ってるわけではないようで,どうやらⅠとⅡが・に化けているようでした.なぜだろう. ひとまず日本語は表示できるようになりましたが,この原因はまた調べます.
Blogger からはてなブログに移行した
Blogger からはてなブログに移行しました.旧 URL は http://blog.ksswre.net です.
遠い昔に登録していた記憶はあったのですが,どうやら 6 年以上放置していたようです.こっちは Markdown で書けて便利ですね. いろいろ使い倒してみたいと思います.
Blogger からの記事の移行は,google-blog-converters-appengine というツールで Blogger の XML 形式から MovableType 形式に変換する必要があるようなので,そのうちやります.
Google Code Archive - Long-term storage for Google Code Project Hosting.