Reputation: 25
I run a number of modded Minecraft servers for friends on my PC, I am trying to build a program that makes starting them and sending commands to them much easier.
I launch the servers using a bat file and have been able to get subprocess
to do that no problem, but I am unsure how to go about adding the functionality of issuing commands to the server via the console.
I've thought of using stdin.write()
and in the interactive console it works great. The issue is that when I add it to the code it executes the stop command before the server has even started therefore the server never stops. I have tried doing it in a separate function but that didn't work either.
Here is my code so far:
Class file:
import subprocess
class Server:
def __init__(self, server_start_bat, dir):
self.server_start_bat = server_start_bat
self.dir =dir
def start_server(self):
server = subprocess.Popen(self.server_start_bat, cwd=self.dir, shell=True, stdin=subprocess.PIPE, text=True)
server.communicate()
def stop_server(self):
server = subprocess.Popen(self.server_start_bat, cwd=self.dir, shell=True, stdin=subprocess.PIPE, text=True)
server.stdin.write('stop\n')
def command(self, command):
server = subprocess.Popen(self.server_start_bat, cwd=self.dir, shell=True, stdin=subprocess.PIPE, text=True)
self.command = command
server.stdin.write(f'{self.command}\n')
Simple GUI I ran it through:
from tkinter import *
import Servers
server = Servers.Server('path\\to\\bat\\file\\batfile.bat', 'dir\\to\\run\\command\\in')
main = Tk()
main.title('Server Commander')
server_title = Label(main, text="server, hosted on port ")
server_title.pack()
server_start = Button(main, text='Start', command=server.start_server)
server_start.pack()
server_stop = Button(main, text='Stop', command=server.stop_server)
server_stop.pack()
main.mainloop()
Upvotes: 1
Views: 837
Reputation: 23244
There are two issues, I think:
stop_server
and command
each start a new subprocess, which should only be done in start_server
.
start_server
uses server.communicate()
which blocks until the subprocess is done, preventing the program to send any other commands to the server while it is running.
Instead,
start_server
should create the subprocess, then store it in a variable which can be accessed by stop_server
and command
,server.communicate
should be done in stop_server
.stop_server
is also just a special case of command
.
import subprocess
class Server:
def __init__(self, server_start_bat, dir):
self.server_start_bat = server_start_bat
self.dir = dir
def start_server(self):
self.server = subprocess.Popen(self.server_start_bat, cwd=self.dir, shell=True, stdin=subprocess.PIPE, text=True)
def stop_server(self):
self.command('stop')
self.server.communicate()
def command(self, command):
self.server.stdin.write(f'{command}\n')
Upvotes: 1