mirror of
https://github.com/evennia/evennia.git
synced 2026-03-26 17:56:32 +01:00
Clean up the launcher for the new functionality.
This commit is contained in:
parent
76f27f9bc2
commit
4126ec8318
1 changed files with 59 additions and 222 deletions
|
|
@ -64,14 +64,12 @@ HTTP_LOGFILE = None
|
|||
|
||||
SERVER_PIDFILE = None
|
||||
PORTAL_PIDFILE = None
|
||||
SERVER_RESTART = None
|
||||
PORTAL_RESTART = None
|
||||
|
||||
SERVER_PY_FILE = None
|
||||
PORTAL_PY_FILE = None
|
||||
|
||||
SPROFILER_LOGFILE = os.path.join(GAMEDIR, SERVERDIR, "logs", "server.prof")
|
||||
PPROFILER_LOGFILE = os.path.join(GAMEDIR, SERVERDIR, "logs", "portal.prof")
|
||||
SPROFILER_LOGFILE = None
|
||||
PPROFILER_LOGFILE = None
|
||||
|
||||
TEST_MODE = False
|
||||
ENFORCED_SETTING = False
|
||||
|
|
@ -136,6 +134,12 @@ ERROR_INPUT = \
|
|||
raised an error: '{traceback}'.
|
||||
"""
|
||||
|
||||
ERROR_NO_ALT_GAMEDIR = \
|
||||
"""
|
||||
The path {gamedir} doesn't seem to exist.
|
||||
|
||||
"""
|
||||
|
||||
ERROR_NO_GAMEDIR = \
|
||||
"""
|
||||
ERROR: No Evennia settings file was found. Evennia looks for the
|
||||
|
|
@ -292,40 +296,26 @@ ABOUT_INFO = \
|
|||
|
||||
HELP_ENTRY = \
|
||||
"""
|
||||
Enter 'evennia -h' for command-line options.
|
||||
This is a convenience launcher for the most common actions. For
|
||||
more advanced ways to operate and manage Evennia, see 'evennia -h'.
|
||||
|
||||
Use option (1) in a production environment. During development (2) is
|
||||
usually enough, portal debugging is usually only useful if you are
|
||||
adding new protocols or are debugging Evennia itself.
|
||||
|
||||
Reload with (5) to update the server with your changes without
|
||||
disconnecting any accounts.
|
||||
|
||||
Note: Reload and stop are sometimes poorly supported in Windows. If you
|
||||
have issues, log into the game to stop or restart the server instead.
|
||||
Evennia's manual is found here: https://github.com/evennia/evennia/wiki
|
||||
"""
|
||||
|
||||
MENU = \
|
||||
"""
|
||||
+----Evennia Launcher-------------------------------------------+
|
||||
| |
|
||||
+--- Starting --------------------------------------------------+
|
||||
+--- Common operations -----------------------------------------+
|
||||
| |
|
||||
| 1) (normal): All output to logfiles |
|
||||
| 2) (server devel): Server logs to terminal (-i option) |
|
||||
| 3) (portal devel): Portal logs to terminal |
|
||||
| 4) (full devel): Both Server and Portal logs to terminal |
|
||||
| 1) Start Portal and Server (also restart downed Server) |
|
||||
| 2) Reload Server (update on code changes) |
|
||||
| 3) Stop Portal and Server (full shutdown) |
|
||||
| |
|
||||
+--- Restarting ------------------------------------------------+
|
||||
+--- Other -----------------------------------------------------+
|
||||
| |
|
||||
| 5) Reload the Server |
|
||||
| 6) Reload the Portal (only works with portal/full debug) |
|
||||
| |
|
||||
+--- Stopping --------------------------------------------------+
|
||||
| |
|
||||
| 7) Stopping both Portal and Server |
|
||||
| 8) Stopping only Server |
|
||||
| 9) Stopping only Portal |
|
||||
| 4) Reset Server (Server shutdown with restart) |
|
||||
| 5) Stop Server only |
|
||||
| |
|
||||
+---------------------------------------------------------------+
|
||||
| h) Help i) About info q) Abort |
|
||||
|
|
@ -885,9 +875,11 @@ def stop_server_only():
|
|||
send_instruction(SSHUTD, {})
|
||||
else:
|
||||
print("Server is not running.")
|
||||
reactor.stop()
|
||||
|
||||
def _portal_not_running(fail):
|
||||
print("Evennia is not running.")
|
||||
reactor.stop()
|
||||
|
||||
send_instruction(PSTATUS, None, _portal_running, _portal_not_running)
|
||||
|
||||
|
|
@ -990,7 +982,8 @@ def check_main_evennia_dependencies():
|
|||
def set_gamedir(path):
|
||||
"""
|
||||
Set GAMEDIR based on path, by figuring out where the setting file
|
||||
is inside the directory tree.
|
||||
is inside the directory tree. This allows for running the launcher
|
||||
from elsewhere than the top of the gamedir folder.
|
||||
|
||||
"""
|
||||
global GAMEDIR
|
||||
|
|
@ -998,7 +991,7 @@ def set_gamedir(path):
|
|||
Ndepth = 10
|
||||
settings_path = os.path.join("server", "conf", "settings.py")
|
||||
for i in range(Ndepth):
|
||||
gpath = os.getcwd()
|
||||
gpath = GAMEDIR
|
||||
if "server" in os.listdir(gpath):
|
||||
if os.path.isfile(settings_path):
|
||||
GAMEDIR = gpath
|
||||
|
|
@ -1208,8 +1201,7 @@ def del_pid(pidfile):
|
|||
os.remove(pidfile)
|
||||
|
||||
|
||||
def kill(pidfile, killsignal=SIG, succmsg="", errmsg="",
|
||||
restart_file=SERVER_RESTART, restart=False):
|
||||
def kill(pidfile, killsignal=SIG, succmsg="", errmsg="", restart=False):
|
||||
"""
|
||||
Send a kill signal to a process based on PID. A customized
|
||||
success/error message will be returned. If clean=True, the system
|
||||
|
|
@ -1220,23 +1212,12 @@ def kill(pidfile, killsignal=SIG, succmsg="", errmsg="",
|
|||
killsignal (int, optional): Signal identifier for signal to send.
|
||||
succmsg (str, optional): Message to log on success.
|
||||
errmsg (str, optional): Message to log on failure.
|
||||
restart_file (str, optional): Restart file location.
|
||||
restart (bool, optional): Are we in restart mode or not.
|
||||
|
||||
"""
|
||||
pid = get_pid(pidfile)
|
||||
if pid:
|
||||
if os.name == 'nt':
|
||||
os.remove(pidfile)
|
||||
# set restart/norestart flag
|
||||
if restart:
|
||||
django.core.management.call_command(
|
||||
'collectstatic', interactive=False, verbosity=0)
|
||||
with open(restart_file, 'w') as f:
|
||||
f.write("reload")
|
||||
else:
|
||||
with open(restart_file, 'w') as f:
|
||||
f.write("shutdown")
|
||||
try:
|
||||
if os.name == 'nt':
|
||||
from win32api import GenerateConsoleCtrlEvent, SetConsoleCtrlHandler
|
||||
|
|
@ -1386,7 +1367,7 @@ def init_game_directory(path, check_db=True):
|
|||
global SERVER_PY_FILE, PORTAL_PY_FILE
|
||||
global SERVER_LOGFILE, PORTAL_LOGFILE, HTTP_LOGFILE
|
||||
global SERVER_PIDFILE, PORTAL_PIDFILE
|
||||
global SERVER_RESTART, PORTAL_RESTART
|
||||
global SPROFILER_LOGFILE, PPROFILER_LOGFILE
|
||||
global EVENNIA_VERSION
|
||||
|
||||
AMP_PORT = settings.AMP_PORT
|
||||
|
|
@ -1399,8 +1380,8 @@ def init_game_directory(path, check_db=True):
|
|||
SERVER_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "server.pid")
|
||||
PORTAL_PIDFILE = os.path.join(GAMEDIR, SERVERDIR, "portal.pid")
|
||||
|
||||
SERVER_RESTART = os.path.join(GAMEDIR, SERVERDIR, "server.restart")
|
||||
PORTAL_RESTART = os.path.join(GAMEDIR, SERVERDIR, "portal.restart")
|
||||
SPROFILER_LOGFILE = os.path.join(GAMEDIR, SERVERDIR, "logs", "server.prof")
|
||||
PPROFILER_LOGFILE = os.path.join(GAMEDIR, SERVERDIR, "logs", "portal.prof")
|
||||
|
||||
SERVER_LOGFILE = settings.SERVER_LOG_FILE
|
||||
PORTAL_LOGFILE = settings.PORTAL_LOG_FILE
|
||||
|
|
@ -1548,160 +1529,21 @@ def run_menu():
|
|||
print("Not a valid option.")
|
||||
continue
|
||||
if inp == 1:
|
||||
# start everything, log to log files
|
||||
server_operation("start", "all", False, False)
|
||||
start_evennia(False, False)
|
||||
elif inp == 2:
|
||||
# start everything, server interactive start
|
||||
server_operation("start", "all", True, False)
|
||||
reload_evennia(False, False)
|
||||
elif inp == 3:
|
||||
# start everything, portal interactive start
|
||||
server_operation("start", "server", False, False)
|
||||
server_operation("start", "portal", True, False)
|
||||
stop_evennia()
|
||||
elif inp == 4:
|
||||
# start both server and portal interactively
|
||||
server_operation("start", "server", True, False)
|
||||
server_operation("start", "portal", True, False)
|
||||
reload_evennia(False, True)
|
||||
elif inp == 5:
|
||||
# reload the server
|
||||
server_operation("reload", "server", None, None)
|
||||
elif inp == 6:
|
||||
# reload the portal
|
||||
server_operation("reload", "portal", None, None)
|
||||
elif inp == 7:
|
||||
# stop server and portal
|
||||
server_operation("stop", "all", None, None)
|
||||
elif inp == 8:
|
||||
# stop server
|
||||
server_operation("stop", "server", None, None)
|
||||
elif inp == 9:
|
||||
# stop portal
|
||||
server_operation("stop", "portal", None, None)
|
||||
stop_server_only()
|
||||
else:
|
||||
print("Not a valid option.")
|
||||
continue
|
||||
return
|
||||
|
||||
|
||||
def server_operation(mode, service, interactive, profiler, logserver=False, doexit=False):
|
||||
"""
|
||||
Handle argument options given on the command line.
|
||||
|
||||
Args:
|
||||
mode (str): Start/stop/restart and so on.
|
||||
service (str): "server", "portal" or "all".
|
||||
interactive (bool). Use interactive mode or daemon.
|
||||
profiler (bool): Run the service under the profiler.
|
||||
logserver (bool, optional): Log Server data to logfile
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
cmdstr = [sys.executable, EVENNIA_RUNNER]
|
||||
errmsg = "The %s does not seem to be running."
|
||||
|
||||
if mode == 'start':
|
||||
|
||||
# launch the error checker. Best to catch the errors already here.
|
||||
error_check_python_modules()
|
||||
|
||||
# starting one or many services
|
||||
if service == 'server':
|
||||
if profiler:
|
||||
cmdstr.append('--pserver')
|
||||
if interactive:
|
||||
cmdstr.append('--iserver')
|
||||
if logserver:
|
||||
cmdstr.append('--logserver')
|
||||
cmdstr.append('--noportal')
|
||||
elif service == 'portal':
|
||||
if profiler:
|
||||
cmdstr.append('--pportal')
|
||||
if interactive:
|
||||
cmdstr.append('--iportal')
|
||||
cmdstr.append('--noserver')
|
||||
django.core.management.call_command(
|
||||
'collectstatic', verbosity=1, interactive=False)
|
||||
else:
|
||||
# all
|
||||
# for convenience we don't start logging of
|
||||
# portal, only of server with this command.
|
||||
if profiler:
|
||||
# this is the common case
|
||||
cmdstr.append('--pserver')
|
||||
if interactive:
|
||||
cmdstr.append('--iserver')
|
||||
if logserver:
|
||||
cmdstr.append('--logserver')
|
||||
django.core.management.call_command(
|
||||
'collectstatic', verbosity=1, interactive=False)
|
||||
if doexit:
|
||||
cmdstr.append('--doexit')
|
||||
cmdstr.extend([
|
||||
GAMEDIR, TWISTED_BINARY, SERVER_LOGFILE,
|
||||
PORTAL_LOGFILE, HTTP_LOGFILE])
|
||||
# start the server
|
||||
process = Popen(cmdstr, env=getenv())
|
||||
|
||||
if interactive:
|
||||
try:
|
||||
process.wait()
|
||||
except KeyboardInterrupt:
|
||||
server_operation("stop", "portal", False, False)
|
||||
return
|
||||
finally:
|
||||
print(NOTE_KEYBOARDINTERRUPT)
|
||||
|
||||
elif mode == 'reload':
|
||||
# restarting services
|
||||
if os.name == 'nt':
|
||||
print(
|
||||
"Restarting from command line is not supported under Windows. "
|
||||
"Use the in-game command (@reload by default) "
|
||||
"or use 'evennia stop && evennia start' for a cold reboot.")
|
||||
return
|
||||
if service == 'server':
|
||||
kill(SERVER_PIDFILE, SIG, "Server reloaded.",
|
||||
errmsg % 'Server', SERVER_RESTART, restart=True)
|
||||
elif service == 'portal':
|
||||
print(
|
||||
"Note: Portal usually doesnt't need to be reloaded unless you "
|
||||
"are debugging in interactive mode. If Portal was running in "
|
||||
"default Daemon mode, it cannot be restarted. In that case "
|
||||
"you have to restart it manually with 'evennia.py "
|
||||
"start portal'")
|
||||
kill(PORTAL_PIDFILE, SIG,
|
||||
"Portal reloaded (or stopped, if it was in daemon mode).",
|
||||
errmsg % 'Portal', PORTAL_RESTART, restart=True)
|
||||
else:
|
||||
# all
|
||||
# default mode, only restart server
|
||||
kill(SERVER_PIDFILE, SIG,
|
||||
"Server reload.",
|
||||
errmsg % 'Server', SERVER_RESTART, restart=True)
|
||||
|
||||
elif mode == 'stop':
|
||||
if os.name == "nt":
|
||||
print(
|
||||
"(Obs: You can use a single Ctrl-C to skip "
|
||||
"Windows' annoying 'Terminate batch job (Y/N)?' prompts.)")
|
||||
# stop processes, avoiding reload
|
||||
if service == 'server':
|
||||
kill(SERVER_PIDFILE, SIG,
|
||||
"Server stopped.", errmsg % 'Server', SERVER_RESTART)
|
||||
elif service == 'portal':
|
||||
kill(PORTAL_PIDFILE, SIG,
|
||||
"Portal stopped.", errmsg % 'Portal', PORTAL_RESTART)
|
||||
else:
|
||||
kill(PORTAL_PIDFILE, SIG,
|
||||
"Portal stopped.", errmsg % 'Portal', PORTAL_RESTART)
|
||||
kill(SERVER_PIDFILE, SIG,
|
||||
"Server stopped.", errmsg % 'Server', SERVER_RESTART)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Run the evennia launcher main program.
|
||||
|
|
@ -1715,14 +1557,6 @@ def main():
|
|||
'-v', '--version', action='store_true',
|
||||
dest='show_version', default=False,
|
||||
help="Show version info.")
|
||||
parser.add_argument(
|
||||
'-i', '--interactive', action='store_true',
|
||||
dest='interactive', default=False,
|
||||
help="Start given processes in interactive mode.")
|
||||
parser.add_argument(
|
||||
'-l', '--log', action='store_true',
|
||||
dest="logserver", default=False,
|
||||
help="Log Server data to log file.")
|
||||
parser.add_argument(
|
||||
'--init', action='store', dest="init", metavar="name",
|
||||
help="Creates a new game directory 'name' at the current location.")
|
||||
|
|
@ -1737,6 +1571,10 @@ def main():
|
|||
'--dummyrunner', nargs=1, action='store', dest='dummyrunner',
|
||||
metavar="N",
|
||||
help="Test a running server by connecting N dummy accounts to it.")
|
||||
parser.add_argument(
|
||||
'--gamedir', nargs=1, action='store', dest='altgamedir',
|
||||
default=None, metavar="path/to/gamedir",
|
||||
help="Supply path to gamedir, if not current location")
|
||||
parser.add_argument(
|
||||
'--settings', nargs=1, action='store', dest='altsettings',
|
||||
default=None, metavar="filename.py",
|
||||
|
|
@ -1746,17 +1584,10 @@ def main():
|
|||
'--initsettings', action='store_true', dest="initsettings",
|
||||
default=False,
|
||||
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(
|
||||
"operation", nargs='?', default="noop",
|
||||
help="Operation to perform: 'start', 'stop', 'reload' or 'menu'.")
|
||||
parser.add_argument(
|
||||
"service", metavar="component", nargs='?', default="all",
|
||||
help=("Which component to operate on: "
|
||||
"'server', 'portal' or 'all' (default if not set)."))
|
||||
metavar="start|stop|reload|reset|sstart|info|status|menu",
|
||||
help="Operation to perform. Unregognized actions are passed on to Django.")
|
||||
parser.epilog = (
|
||||
"Common usage: evennia start|stop|reload. Django-admin database commands:"
|
||||
"evennia migration|flush|shell|dbshell (see the django documentation for more "
|
||||
|
|
@ -1765,7 +1596,7 @@ def main():
|
|||
args, unknown_args = parser.parse_known_args()
|
||||
|
||||
# handle arguments
|
||||
option, service = args.operation, args.service
|
||||
option = args.operation
|
||||
|
||||
# make sure we have everything
|
||||
check_main_evennia_dependencies()
|
||||
|
|
@ -1774,7 +1605,16 @@ def main():
|
|||
# show help pane
|
||||
print(CMDLINE_HELP)
|
||||
sys.exit()
|
||||
elif args.init:
|
||||
|
||||
if args.altgamedir:
|
||||
# use alternative gamedir path
|
||||
global GAMEDIR
|
||||
if not os.path.isdir(args.altgamedir) and not args.init:
|
||||
print(ERROR_NO_ALT_GAMEDIR.format(args.altgamedir))
|
||||
sys.exit()
|
||||
GAMEDIR = args.altgamedir
|
||||
|
||||
if args.init:
|
||||
# initialization of game directory
|
||||
create_game_directory(args.init)
|
||||
print(CREATED_NEW_GAMEDIR.format(
|
||||
|
|
@ -1799,8 +1639,6 @@ def main():
|
|||
|
||||
if args.initsettings:
|
||||
# create new settings file
|
||||
global GAMEDIR
|
||||
GAMEDIR = os.getcwd()
|
||||
try:
|
||||
create_settings_file(init=False)
|
||||
print(RECREATED_SETTINGS)
|
||||
|
|
@ -1820,29 +1658,28 @@ def main():
|
|||
# launch menu for operation
|
||||
init_game_directory(CURRENT_DIR, check_db=True)
|
||||
run_menu()
|
||||
elif option in ('status', 'info', 'sstart', 'sreload', 'sreset', 'sstop', 'ssstop', 'start', 'reload', 'stop'):
|
||||
elif option in ('status', 'info', 'start', 'reload', 'reset', 'stop', 'sstop'):
|
||||
# operate the server directly
|
||||
init_game_directory(CURRENT_DIR, check_db=True)
|
||||
if option == "status":
|
||||
query_status()
|
||||
elif option == "info":
|
||||
query_info()
|
||||
elif option == "sstart":
|
||||
elif option == "start":
|
||||
start_evennia(False, args.profiler)
|
||||
elif option == 'sreload':
|
||||
elif option == 'reload':
|
||||
reload_evennia(args.profiler)
|
||||
elif option == 'sreset':
|
||||
elif option == 'reset':
|
||||
reload_evennia(args.profiler, reset=True)
|
||||
elif option == 'sstop':
|
||||
elif option == 'stop':
|
||||
stop_evennia()
|
||||
elif option == 'ssstop':
|
||||
elif option == 'sstop':
|
||||
stop_server_only()
|
||||
else:
|
||||
server_operation(option, service, args.interactive,
|
||||
args.profiler, args.logserver, doexit=args.doexit)
|
||||
elif option != "noop":
|
||||
# pass-through to django manager
|
||||
check_db = False
|
||||
|
||||
# handle special django commands
|
||||
if option in ('runserver', 'testserver'):
|
||||
print(WARNING_RUNSERVER)
|
||||
if option in ("shell", "check"):
|
||||
|
|
@ -1852,12 +1689,12 @@ def main():
|
|||
if option == "test":
|
||||
global TEST_MODE
|
||||
TEST_MODE = True
|
||||
|
||||
init_game_directory(CURRENT_DIR, check_db=check_db)
|
||||
|
||||
# pass on to the manager
|
||||
args = [option]
|
||||
kwargs = {}
|
||||
if service not in ("all", "server", "portal"):
|
||||
args.append(service)
|
||||
if unknown_args:
|
||||
for arg in unknown_args:
|
||||
if arg.startswith("--"):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue