Add external-runner option to the launcher to allow for replacing the native evennia runner with an external process manager (like Linux' start-stop-daemon). Note that without a replacement, this option will make evennia un-reloadable.
This commit is contained in:
parent
ad13594a46
commit
293c3b077d
2 changed files with 29 additions and 7 deletions
|
|
@ -1084,7 +1084,7 @@ def run_menu():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def server_operation(mode, service, interactive, profiler, logserver=False):
|
def server_operation(mode, service, interactive, profiler, logserver=False, doexit=False):
|
||||||
"""
|
"""
|
||||||
Handle argument options given on the command line.
|
Handle argument options given on the command line.
|
||||||
|
|
||||||
|
|
@ -1095,6 +1095,10 @@ def server_operation(mode, service, interactive, profiler, logserver=False):
|
||||||
profiler (bool): Run the service under the profiler.
|
profiler (bool): Run the service under the profiler.
|
||||||
logserver (bool, optional): Log Server data to logfile
|
logserver (bool, optional): Log Server data to logfile
|
||||||
specified by settings.SERVER_LOG_FILE.
|
specified by settings.SERVER_LOG_FILE.
|
||||||
|
doexit (bool, optional): If True, immediately exit the runner after
|
||||||
|
starting the relevant processes. If the runner exits, Evennia
|
||||||
|
cannot be reloaded. This is meant to be used with an external
|
||||||
|
process manager like Linux' start-stop-daemon.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -1136,6 +1140,8 @@ def server_operation(mode, service, interactive, profiler, logserver=False):
|
||||||
cmdstr.append('--logserver')
|
cmdstr.append('--logserver')
|
||||||
django.core.management.call_command(
|
django.core.management.call_command(
|
||||||
'collectstatic', verbosity=1, interactive=False)
|
'collectstatic', verbosity=1, interactive=False)
|
||||||
|
if doexit:
|
||||||
|
cmdstr.append('--doexit')
|
||||||
cmdstr.extend([
|
cmdstr.extend([
|
||||||
GAMEDIR, TWISTED_BINARY, SERVER_LOGFILE,
|
GAMEDIR, TWISTED_BINARY, SERVER_LOGFILE,
|
||||||
PORTAL_LOGFILE, HTTP_LOGFILE])
|
PORTAL_LOGFILE, HTTP_LOGFILE])
|
||||||
|
|
@ -1242,6 +1248,10 @@ def main():
|
||||||
'--initsettings', action='store_true', dest="initsettings",
|
'--initsettings', action='store_true', dest="initsettings",
|
||||||
default=False,
|
default=False,
|
||||||
help="Create a new, empty settings file as gamedir/server/conf/settings.py.")
|
help="Create a new, empty settings file as gamedir/server/conf/settings.py.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--external-runner', action='store_true', dest="doexit",
|
||||||
|
default=False,
|
||||||
|
help="Handle server restart with an external process manager.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"operation", nargs='?', default="noop",
|
"operation", nargs='?', default="noop",
|
||||||
help="Operation to perform: 'start', 'stop', 'reload' or 'menu'.")
|
help="Operation to perform: 'start', 'stop', 'reload' or 'menu'.")
|
||||||
|
|
@ -1315,7 +1325,7 @@ def main():
|
||||||
elif option in ('start', 'reload', 'stop'):
|
elif option in ('start', 'reload', 'stop'):
|
||||||
# operate the server directly
|
# operate the server directly
|
||||||
init_game_directory(CURRENT_DIR, check_db=True)
|
init_game_directory(CURRENT_DIR, check_db=True)
|
||||||
server_operation(option, service, args.interactive, args.profiler, args.logserver)
|
server_operation(option, service, args.interactive, args.profiler, args.logserver, doexit=args.doexit)
|
||||||
elif option != "noop":
|
elif option != "noop":
|
||||||
# pass-through to django manager
|
# pass-through to django manager
|
||||||
check_db = False
|
check_db = False
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ PROCESS_IOERROR = \
|
||||||
|
|
||||||
PROCESS_RESTART = "{component} restarting ..."
|
PROCESS_RESTART = "{component} restarting ..."
|
||||||
|
|
||||||
|
PROCESS_DOEXIT = "Deferring to external runner."
|
||||||
|
|
||||||
# Functions
|
# Functions
|
||||||
|
|
||||||
|
|
@ -134,7 +135,7 @@ def cycle_logfile(logfile):
|
||||||
# Start program management
|
# Start program management
|
||||||
|
|
||||||
|
|
||||||
def start_services(server_argv, portal_argv):
|
def start_services(server_argv, portal_argv, doexit=False):
|
||||||
"""
|
"""
|
||||||
This calls a threaded loop that launces the Portal and Server
|
This calls a threaded loop that launces the Portal and Server
|
||||||
and then restarts them when they finish.
|
and then restarts them when they finish.
|
||||||
|
|
@ -162,7 +163,7 @@ def start_services(server_argv, portal_argv):
|
||||||
|
|
||||||
if portal_argv:
|
if portal_argv:
|
||||||
try:
|
try:
|
||||||
if get_restart_mode(PORTAL_RESTART) == "True":
|
if not doexit and get_restart_mode(PORTAL_RESTART) == "True":
|
||||||
# start portal as interactive, reloadable thread
|
# start portal as interactive, reloadable thread
|
||||||
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
|
PORTAL = thread.start_new_thread(portal_waiter, (processes, ))
|
||||||
else:
|
else:
|
||||||
|
|
@ -175,12 +176,19 @@ def start_services(server_argv, portal_argv):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if server_argv:
|
if server_argv:
|
||||||
|
if doexit:
|
||||||
|
SERVER = Popen(server_argv, env=getenv())
|
||||||
|
else:
|
||||||
# start server as a reloadable thread
|
# start server as a reloadable thread
|
||||||
SERVER = thread.start_new_thread(server_waiter, (processes, ))
|
SERVER = thread.start_new_thread(server_waiter, (processes, ))
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(PROCESS_IOERROR.format(component="Server", traceback=e))
|
print(PROCESS_IOERROR.format(component="Server", traceback=e))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if doexit:
|
||||||
|
# Exit immediately
|
||||||
|
return
|
||||||
|
|
||||||
# Reload loop
|
# Reload loop
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
|
|
@ -234,6 +242,8 @@ def main():
|
||||||
default=False, help='Profile Portal')
|
default=False, help='Profile Portal')
|
||||||
parser.add_argument('--nologcycle', action='store_false', dest='nologcycle',
|
parser.add_argument('--nologcycle', action='store_false', dest='nologcycle',
|
||||||
default=True, help='Do not cycle log files')
|
default=True, help='Do not cycle log files')
|
||||||
|
parser.add_argument('--doexit', action='store_true', dest='doexit',
|
||||||
|
default=False, help='Immediately exit after processes have started.')
|
||||||
parser.add_argument('gamedir', help="path to game dir")
|
parser.add_argument('gamedir', help="path to game dir")
|
||||||
parser.add_argument('twistdbinary', help="path to twistd binary")
|
parser.add_argument('twistdbinary', help="path to twistd binary")
|
||||||
parser.add_argument('slogfile', help="path to server log file")
|
parser.add_argument('slogfile', help="path to server log file")
|
||||||
|
|
@ -327,6 +337,8 @@ def main():
|
||||||
if args.pportal:
|
if args.pportal:
|
||||||
portal_argv.extend(pportal_argv)
|
portal_argv.extend(pportal_argv)
|
||||||
print("\nRunning Evennia Portal under cProfile.")
|
print("\nRunning Evennia Portal under cProfile.")
|
||||||
|
if args.doexit:
|
||||||
|
print(PROCESS_DOEXIT)
|
||||||
|
|
||||||
# Windows fixes (Windows don't support pidfiles natively)
|
# Windows fixes (Windows don't support pidfiles natively)
|
||||||
if os.name == 'nt':
|
if os.name == 'nt':
|
||||||
|
|
@ -336,7 +348,7 @@ def main():
|
||||||
del portal_argv[-2]
|
del portal_argv[-2]
|
||||||
|
|
||||||
# Start processes
|
# Start processes
|
||||||
start_services(server_argv, portal_argv)
|
start_services(server_argv, portal_argv, doexit=args.doexit)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue