通过 IFTTT 来控制和节省 Azure 上的 Minecraft 多人服务器
首先
我們使用 Azure 的虛擬機器,來啟動並運營 Minecraft (Spigot) 多人伺服器。
由于参与成员都在公司上班,因此在工作日的白天我们会停止服务器运行,仅在”工作日的晚上以及整个周末”时间段内自动启动服务器。
这次,我们使用 Azure Automation 来与 IFTTT 的 DateTime 触发器进行连接,以便启动和运行服务器,并且进一步建立了一个与虚拟机的开启和关闭相关的 Minecraft 服务器。
最终目标是将服务器启动通知发送到Discord,以便成员可以确认。
在本文中,我们将按照以下步骤进行解释(忽略基础知识部分)。
-
- 仮想マシンの構築
VM の起動と終了に連動した Minecraft サーバを構築します
Azure Automation で Webhook を作成する
VM の起動と終了を行い、Discord に Webhook で通知する Runbook を構築します
IFTTT で Webhook のトリガーを作成する
构建虚拟机
这次创建的虚拟机具有以下配置。
-
- SKU: Standard D2s v3 (2 vcpu 数、8 GiB メモリ)
-
- Region: 東日本
- Image: Ubuntu Server 18.04 LTS
D2s v3每月¥9,166,但由于平日仅工作约6小时,因此大致每月工作300小时,仅使用了月费的约1/2(仅从价格上看,确实有点贵)。
Spigot 服务器的建设
本次使用Docker进行搭建。
只需克隆nimmis/docker-spigot并修改docker-compose.yml的值即可完成。
$ sudo mkdir -p /minecraft
$ sudo chown -R mcserver:mcserver /minecraft
$ git clone --depth=1 https://github.com/nimmis/docker-spigot /minecraft
version: "2"
services:
spigot-main:
container_name: "spigot-main"
build: "."
ports:
- 80:8123
- 25565:25565
environment:
- MC_MAXMEM=8g
- MC_MINMEM=1g
- SPIGOT_AUTORESTART=yes
- SPIGOT_VER=1.14.4
- SPIGOT_UID=1000
volumes:
- "./server:/minecraft"
restart: "always"
如果执行 docker-compose up,将会进行 spigot.jar 的构建,之后服务器将自动启动。
末尾腳本完成時
当虚拟机试图停止时,需要在执行/save-all命令后结束Minecraft服务器的世界数据。但是,我们正在使用的镜像在容器停止时会自动处理此事项。
所以我会编写一个在结束时运行的脚本,以便在关闭时停止容器。
创建终止时的脚本
$ sudo vim /etc/init.d/stop-mcserver.sh
$ sudo chmod a+x /etc/init.d/stop-mcserver.sh
$ sudo ln -s /etc/init.d/stop-mcserver.sh /etc/rc6.d/K99stop-mcserver
#!/bin/bash
cd /minecraft
/usr/local/bin/docker-compose stop
另外,由于重启设置为“always”,所以在下次启动时容器将自动运行,使得Minecraft服务器能够恢复,从而完成了自动启动和关闭的机制!
没做。
我对此原因仍然不清楚,但在 Azure 虚拟机重启后,容器不知何故无法自动启动。
不过,当进行SSH并执行docker ps等命令时,容器在一段微妙的延迟后启动,因此可以推测Docker守护进程可能没有正确启动。
启动脚本
因此,我们通过在启动时执行一个无害的命令来强制启动Docker守护进程,从而实现了Docker API的调用。
现在,虚拟机重新启动后,容器将自动启动。
启动时脚本
$ crontab -e
crontab文件的内容。
# m h dom mon dow command
@reboot /usr/bin/docker --version > dev/null 2>&1
使用Azure Automation来启动和关闭虚拟机
在Azure Automation的Runbook中实施这些内容。
-
- サーバを起動させる
-
- サーバを停止させる
-
- 起動・停止したら Discord の Webhook で通知する
- Automation 開始トリガーを Incoming Webhook にする
启动或停止服务器
只需要导入Runbook库中排名靠前的两个脚本就可以了。
然而,导入的Runbook尚未根据Azure的规格更改进行更新,即使可以正确启动和停止,但自动化作业仍以错误结束。
原因是因为 Notify VM Started/Stopped 节点的执行条件表达式过时,通过将其与当前的 ActivityOutput 属性匹配来解决这个问题(还有 Notify Failed To Start/Stop 节点附近的错误内容获取方法也已经修复)。
使用 Discord 的 Webhook 进行通知
※ Webhook 已经被创建
我正在将每个输出消息从IDictionary转换为JSON,并通过Webhook将其内容通知到Discord。
格式化消息
使用Write-Output节点,根据Discord的Webhook规范创建内容。
@{
content = $_
}
转换为Json
从格式化的消息中接收活动的输出
通知至webhook
使用Invoke-WebRequest节点,通过POST方式发送ConvertTo-Json活动的输出。
如果不指定Content-Type为application/json; charset=utf-8,会导致日语乱码。
另外,如果不将UseBasicParsing标志设置为True,则作业可能无法正确完成(应该)。
创建一个开始触发器的 Incoming-Webhook。
$ curl -X POST -H "Content-Type: application/json" https://WEBHOOK
请记下每个 Webhook URL。
创建 IFTTT 的触发器
从IFTTT的DateTime触发器中选择”每周的每一天”。
顺便说一句
Azure Automation具有自己的定时执行功能,但由于使用不方便且在智能手机上难以编辑,因此通过IFTTT进行日程编辑会更加简单方便。
虽然可能完全是多余的,但就算是要添加假日判断等功能,我认为还是比在操作手册中建立的方式要好,应该单独托管Discord的机器人并实现自己的调度。