Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ docker run -it --rm itzg/mc-monitor status-bedrock --host play.fallentech.io

where exit code will be 0 for success or 1 for failure.

### Workarounds for some status errors

Some Forge servers may cause a `string length out of bounds` error during status messages due to how the [FML2 protocol](https://wiki.vg/Minecraft_Forge_Handshake#FML2_protocol_.281.13_-_Current.29) bundles the entire modlist for client compatibility check. If there are issues with `status` failing when it otherwise should work, you can try out the experimental `--use-mc-utils` flag below (enables the [mcutils](https://github.com/xrjr/mcutils) protocol library):
```
docker run -it --rm itzg/mc-monitor status --use-mc-utils --host play.fallentech.io
```

### Monitoring a server with Telegraf

> The following example is provided in [examples/mc-monitor-telegraf](examples/mc-monitor-telegraf)
Expand Down
29 changes: 15 additions & 14 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,34 @@ go 1.17

require (
github.com/Raqbit/mc-pinger v0.2.2
github.com/avast/retry-go v3.0.0+incompatible
github.com/google/subcommands v1.2.0
github.com/itzg/go-flagsfiller v1.5.0
github.com/itzg/line-protocol-sender v0.1.1
github.com/itzg/zapconfigs v0.1.0
github.com/prometheus/client_golang v1.11.0
github.com/sandertv/go-raknet v1.10.0
github.com/stretchr/testify v1.7.0
github.com/xrjr/mcutils v1.3.2
go.uber.org/zap v1.19.1
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/subcommands v1.2.0
github.com/iancoleman/strcase v0.1.3 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/itzg/go-flagsfiller v1.5.0
github.com/itzg/line-protocol-sender v0.1.1
github.com/itzg/zapconfigs v0.1.0
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/pires/go-proxyproto v0.6.0 // indirect
github.com/prometheus/client_golang v1.11.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/sandertv/go-raknet v1.10.0
github.com/stretchr/testify v1.7.0
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.1
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 // indirect
google.golang.org/protobuf v1.26.0 // indirect
)

require (
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/xrjr/mcutils v1.3.2 h1:AApQqiVrzNhXyggMIjW82x0EWzsQf4MTRtM0ebFjJ9E=
github.com/xrjr/mcutils v1.3.2/go.mod h1:43n8cyMIHYjiRM2LFZLVH5Ppz2+RvWppz6OgkLP8Lsk=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
Expand Down
54 changes: 54 additions & 0 deletions java_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import (
mcpinger "github.com/Raqbit/mc-pinger"
"github.com/google/subcommands"
"github.com/itzg/go-flagsfiller"
"github.com/xrjr/mcutils/pkg/ping"
)

type statusCmd struct {
Host string `default:"localhost" usage:"hostname of the Minecraft server" env:"MC_HOST"`
Port int `default:"25565" usage:"port of the Minecraft server" env:"MC_PORT"`

UseServerListPing bool `usage:"indicates the legacy, server list ping should be used for pre-1.12"`
UseMcUtils bool `usage:"(experimental) try using mcutils to query the server"`

RetryInterval time.Duration `usage:"if retry-limit is non-zero, status will be retried at this interval" default:"10s"`
RetryLimit int `usage:"if non-zero, failed status will be retried this many times before exiting"`
Expand Down Expand Up @@ -60,6 +62,10 @@ func (c *statusCmd) Execute(ctx context.Context, fs *flag.FlagSet, args ...inter
return c.ExecuteServerListPing()
}

if c.UseMcUtils {
return c.ExecuteMcUtilPing(logger)
}

var options []mcpinger.McPingerOption
if c.Timeout > 0 {
options = append(options, mcpinger.WithTimeout(c.Timeout))
Expand Down Expand Up @@ -143,3 +149,51 @@ func (c *statusCmd) ExecuteServerListPing() subcommands.ExitStatus {
// regular output is within Do function
return subcommands.ExitSuccess
}

func (c *statusCmd) ExecuteMcUtilPing(logger *zap.Logger) subcommands.ExitStatus {
client := ping.NewClient(c.Host, c.Port)
client.DialTimeout = c.Timeout
client.ReadTimeout = c.Timeout

err := retry.Do(func() error {

err := client.Connect()
if err != nil {
logger.Debug("Client failed to connect", zap.Error(err))
return err
}

defer client.Disconnect()

hs, err := client.Handshake()
if err != nil {
logger.Debug("Client failed to handshake", zap.Error(err))
return err
}

response := hs.Properties.Infos()
logger.Debug("mcutils ping returned", zap.Any("properties", response))

if response.Players.Max == 0 {
return errors.New("server not ready")
}

if c.ShowPlayerCount {
fmt.Printf("%d\n", response.Players.Online)
} else {
fmt.Printf("%s:%d : version=%s online=%d max=%d motd='%s'\n",
c.Host, c.Port,
response.Version.Name, response.Players.Online, response.Players.Max, response.Description)
}

return nil
}, retry.Delay(c.RetryInterval), retry.Attempts(uint(c.RetryLimit+1)))

if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "failed to ping %s:%d : %s", c.Host, c.Port, err)
return subcommands.ExitFailure
}

// regular output is within Do function
return subcommands.ExitSuccess
}