18ef303935
No interactive console exists since lazymc/systemd run the server in the background, and mcrcon isn't packaged for Debian 13. Plain Python3 RCON client instead, reads the password straight from server.properties. setup-server.sh now copies it into mcserver/.
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Minimal Minecraft RCON client. Usage: rcon.py "<command>" ["<command2>" ...]"""
|
|
import socket
|
|
import struct
|
|
import sys
|
|
|
|
HOST = "127.0.0.1"
|
|
PORT = 25575
|
|
PASSWORD_FILE = "server.properties"
|
|
|
|
|
|
def read_password():
|
|
with open(PASSWORD_FILE) as f:
|
|
for line in f:
|
|
if line.startswith("rcon.password="):
|
|
return line.strip().split("=", 1)[1]
|
|
raise SystemExit("rcon.password not found in server.properties")
|
|
|
|
|
|
def send_packet(sock, req_id, pkt_type, payload):
|
|
data = struct.pack("<ii", req_id, pkt_type) + payload.encode() + b"\x00\x00"
|
|
sock.sendall(struct.pack("<i", len(data)) + data)
|
|
|
|
|
|
def read_packet(sock):
|
|
length = struct.unpack("<i", sock.recv(4))[0]
|
|
data = b""
|
|
while len(data) < length:
|
|
data += sock.recv(length - len(data))
|
|
req_id, pkt_type = struct.unpack("<ii", data[:8])
|
|
payload = data[8:-2].decode(errors="replace")
|
|
return req_id, pkt_type, payload
|
|
|
|
|
|
def main():
|
|
password = read_password()
|
|
sock = socket.create_connection((HOST, PORT), timeout=10)
|
|
send_packet(sock, 1, 3, password) # SERVERDATA_AUTH
|
|
req_id, _, _ = read_packet(sock)
|
|
if req_id == -1:
|
|
raise SystemExit("RCON auth failed")
|
|
|
|
for i, cmd in enumerate(sys.argv[1:], start=2):
|
|
send_packet(sock, i, 2, cmd) # SERVERDATA_EXECCOMMAND
|
|
_, _, response = read_packet(sock)
|
|
print(f"> {cmd}\n{response}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|