Skip to content
Open
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
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
minecraftd-backup.service
minecraftd-backup.timer
minecraftd-backup@.service
minecraftd-backup@.timer
minecraftd-init@.service
minecraftd.conf
minecraftd.service
minecraftd.sh
minecraftd.sysusers
minecraftd.tmpfiles
minecraftd@.service
47 changes: 37 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
SHELL = /bin/sh
INSTALL = install
INSTALL_PROGRAM = $(INSTALL) -m755
INSTALL_DIR = $(INSTALL) -d -m755
INSTALL_DATA = $(INSTALL) -m644
confdir = /etc/conf.d
prefix = /usr
Expand All @@ -10,27 +11,39 @@ datarootdir = $(prefix)/share
mandir = $(prefix)/share/man
man1dir = $(mandir)/man1

SOURCES = minecraftd.sh.in minecraftd.conf.in minecraftd.service.in minecraftd.sysusers.in minecraftd.tmpfiles.in minecraftd-backup.service.in minecraftd-backup.timer.in
SOURCES = $(wildcard *.in)
OBJECTS = $(SOURCES:.in=)

GAME = minecraft
INAME = minecraftd
SERVER_ROOT = /srv/$(GAME)
CONFIG_PATH = /etc/conf.d/$(GAME)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you swap this line with the one below, you can use SYSCONFDIR in CONFIG_PATH.

SYSCONFDIR = /etc
INSTANCE_CONFIG_DIR = $(SYSCONFDIR)/$(GAME)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about merging CONFIG_PATH into INSTACE_CONFIG_DIR. IMO it would make more sense to have one central directory where to configure everything at once.

Specifically what do you think about /etc/minecraftd and /etc/minecraftd.d (respectively with INAME and config dir)? IMHO this would be a neat solution.

BACKUP_DEST = $(SERVER_ROOT)/backup
LIBRARY_PATH = $(libdir)/$(GAME)
BACKUP_PATHS = world
BACKUP_FLAGS = -z
KEEP_BACKUPS = 10
GAME_USER = $(GAME)
SERVER_MEMORY_INITIAL = 512
SERVER_MEMORY_MAXIMUM = 1024
Comment on lines +29 to +30
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These flags are not meaningful for servers which do not allow for configuring the memory via the command line.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll need to look into this further. You mentioned cuberite which I am not familiar with. -Xms and -Xmx are arguments to the JVM executable so they should work regardless of what server implementation is being used. Can you help me understand what I'm missing?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes all java based implementations should honor this flag or more precisely, it will be enforced by the JVM. However, cuberite is a C++ rewrite and does not care about any of this.

MAIN_EXECUTABLE = minecraft_server.jar
ifeq ($(MAIN_EXECUTABLE),$(MAIN_EXECUTABLE:/%=))
MAIN_EXECUTABLE_ABSOLUTE = $(SERVER_ROOT)/$(MAIN_EXECUTABLE)
else
MAIN_EXECUTABLE_ABSOLUTE = $(MAIN_EXECUTABLE)
endif
TMUX_SOCKET_DIR = /run/$(GAME)/tmux
SESSION_NAME = $(GAME)
SERVER_START_CMD = java -Xms512M -Xmx1024M -jar ./$${MAIN_EXECUTABLE} nogui
SERVER_START_CMD = java -Xms@SERVER_MEMORY_INITIAL@M -Xmx@SERVER_MEMORY_MAXIMUM@M -jar @MAIN_EXECUTABLE@ nogui
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work. You may not use @ within the replacement strings since the replacement is not recursed.

EDIT: I just saw that you actually account for this later but that just feels very wrong on so many levels. Please don't do that!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, while it does work, I'm open to any better solution.

My goal here is to allow users to customize the memory allocated to the server without overriding the entire JVM command line, should the packager need to add/change/remove other JVM arguments. Do you have any recommendations for how this could be accomplished? I'm okay with returning to the use of eval if you think that's better.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal is clear but I don't like adding any java specific options. The only viable solution to me seems to alter all of SERVER_START_CMD.

I am afraid you have to jog my memory a little about your proposal regarding eval. In which way was eval used before?

SERVER_START_SUCCESS = done
IDLE_SERVER = false
IDLE_SESSION_NAME = idle_server_$${SESSION_NAME}
IDLE_SESSION_NAME = idle_server_@SESSION_NAME@
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

I am fine with removing this variable completely and simply derive it from SESSION_NAME within the script.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

GAME_PORT = 25565
CHECK_PLAYER_TIME = 30
IDLE_IF_TIME = 1200
GAME_COMMAND_DUMP = /tmp/$${INAME}_$${SESSION_NAME}_command_dump.txt
GAME_COMMAND_DUMP = $(TMUX_SOCKET_DIR)/@INAME@_@SESSION_NAME@_command_dump.txt
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Again I am fine with removing this variable from the configuration munging and hardcode its dependency on INAME and SESSION_NAME within the script.


.MAIN = all

Expand All @@ -40,12 +53,20 @@ define replace_all
-e 's#@INAME@#$(INAME)#g' \
-e 's#@GAME@#$(GAME)#g' \
-e 's#@SERVER_ROOT@#$(SERVER_ROOT)#g' \
-e 's#@CONFIG_PATH@#$(CONFIG_PATH)#g' \
-e 's#@LIBRARY_PATH@#$(LIBRARY_PATH)#g' \
-e 's#@SYSCONFDIR@#$(SYSCONFDIR)#g' \
-e 's#@INSTANCE_CONFIG_DIR@#$(INSTANCE_CONFIG_DIR)#g' \
-e 's#@BACKUP_DEST@#$(BACKUP_DEST)#g' \
-e 's#@BACKUP_PATHS@#$(BACKUP_PATHS)#g' \
-e 's#@BACKUP_FLAGS@#$(BACKUP_FLAGS)#g' \
-e 's#@KEEP_BACKUPS@#$(KEEP_BACKUPS)#g' \
-e 's#@GAME_USER@#$(GAME_USER)#g' \
-e 's#@MAIN_EXECUTABLE@#$(MAIN_EXECUTABLE)#g' \
-e 's#@MAIN_EXECUTABLE_ABSOLUTE@#$(MAIN_EXECUTABLE_ABSOLUTE)#g' \
-e 's#@SERVER_MEMORY_INITIAL@#$(SERVER_MEMORY_INITIAL)#g' \
-e 's#@SERVER_MEMORY_MAXIMUM@#$(SERVER_MEMORY_MAXIMUM)#g' \
-e 's#@TMUX_SOCKET_DIR@#$(TMUX_SOCKET_DIR)#g' \
-e 's#@SESSION_NAME@#$(SESSION_NAME)#g' \
-e 's#@SERVER_START_CMD@#$(SERVER_START_CMD)#g' \
-e 's#@SERVER_START_SUCCESS@#$(SERVER_START_SUCCESS)#g' \
Expand Down Expand Up @@ -88,12 +109,18 @@ maintainer-clean: clean

install:
$(INSTALL_PROGRAM) -D minecraftd.sh "$(DESTDIR)$(bindir)/$(INAME)"
$(INSTALL_DATA) -D minecraftd.conf "$(DESTDIR)$(confdir)/$(GAME)"
$(INSTALL_DATA) -D minecraftd.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME).service"
$(INSTALL_DATA) -D minecraftd-backup.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup.service"
$(INSTALL_DATA) -D minecraftd-backup.timer "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup.timer"
$(INSTALL_DATA) -D minecraftd.sysusers "$(DESTDIR)$(libdir)/sysusers.d/$(INAME).conf"
$(INSTALL_DATA) -D minecraftd.tmpfiles "$(DESTDIR)$(libdir)/tmpfiles.d/$(INAME).conf"
$(INSTALL_DIR) "$(DESTDIR)$(LIBRARY_PATH)"
$(INSTALL_DATA) -D argparse.sh "$(DESTDIR)$(LIBRARY_PATH)/argparse.sh"
$(INSTALL_DATA) -D minecraftd.conf "$(DESTDIR)$(confdir)/$(GAME)"
$(INSTALL_DATA) -D minecraftd.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME).service"
$(INSTALL_DATA) -D minecraftd-backup.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup.service"
$(INSTALL_DATA) -D minecraftd-backup.timer "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup.timer"
$(INSTALL_DATA) -D minecraftd@.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME)@.service"
$(INSTALL_DATA) -D minecraftd-init@.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-init@.service"
$(INSTALL_DATA) -D minecraftd-backup@.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup@.service"
$(INSTALL_DATA) -D minecraftd-backup@.timer "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup@.timer"
$(INSTALL_DATA) -D minecraftd.sysusers "$(DESTDIR)$(libdir)/sysusers.d/$(INAME).conf"
$(INSTALL_DATA) -D minecraftd.tmpfiles "$(DESTDIR)$(libdir)/tmpfiles.d/$(INAME).conf"

uninstall:
rm -f "$(bindir)/$(INAME)"
Expand Down
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,42 @@ Use the minecraft script under /usr/bin/minecraftd to start, stop or backup the

### How to configure the Server

Adjust the configuration file under /etc/conf.d/minecraft to your liking.
Adjust the configuration file under `/etc/conf.d/minecraft` to your liking.

If you are running multiple servers, the configuration file `/etc/minecraft/<instance name>` will be loaded if it exists, and will supersede any options set in the global configuration.

Any configuration variable can be overridden in the environment.

To see the effective configuration based on the instance name and all applicable configuration files, run `minecraftd print`, `minecraftd -i server2 print`, etc. To print the plain value of a single configuration key, use the `-k` argument: `minecraftd print -k SERVER_ROOT`.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put each sentence on its own line here and in the following to make future git diffs nicer.


### Server does not start

For the server to start you have to accept the EULA in /srv/minecraft/eula.txt !
The EULA file is generated after the first server start.

### Running multiple servers on the same host

The generated file `minecraftd@.service` allows you to run than one instance of the server on a single host. A unique data directory (`/srv/minecraft/servers/<instance name>`) is created for each instance.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing the word "more"


You need to create, at minimum, `eula.txt` and `server.properties` (the latter specifying an alternate `server-port`) before the server will start. This means the workflow for setting up a new server looks something like:

```sh
systemctl start minecraftd@server-name # (creates directories; the service will fail to start, that's ok)
sed -re 's;^eula=.*$;eula=true;' -i /srv/minecraft/servers/server-name/eula.txt
sed -re 's;^(server-port|query\.port)=.*$;\1=25567;g' /srv/minecraft/servers/server-name/server.properties
systemctl start minecraftd@server-name # (it should start this time)
```

To facilitate the use of a unique environment variable file per instance, the file `/etc/minecraft/<instance name>` is read in addition to the global environment file, `/etc/conf.d/minecraft`. Note that `minecraft` is the value of the `@GAME@` macro in this case, so change this to `/etc/spigot/<instance name>`, etc. Values in the instance-specific environment file take precedence over values in the global configuration.

The configuration variables whose defaults change in instantiated mode are:

* `SERVER_ROOT` changes from `/srv/minecraft` to `/srv/minecraft/servers/<instance name>`
* `SESSION_NAME` changes from `minecraft` to `minecraft-<instance name>`
* `BACKUP_DEST` changes from `/srv/minecraft/backup` to `/srv/minecraft/servers/<instance name>/backup`

These can also be overridden in the instance-specific configuration file, `/etc/minecraft/<instance name>`.

## License

Unless otherwise stated, the files in this project may be distributed under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. This work is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See [version 2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) and [version 3](https://www.gnu.org/copyleft/gpl-3.0.html) of the GNU General Public License for more details.
189 changes: 189 additions & 0 deletions argparse.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/bin/bash
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please just inline this script. It is pretty fancy and not specifically related to the minecraft server. However, in its current form it still couples tightly to it. Furthermore, I really like that the server is just a single bash script without any additional library files.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file adds a lot of LOC and I don't feel that it's tightly coupled. Can you share why you said it couples tightly to the launcher script?

With the launcher script adding a lot of LOC in this change, do you think it makes sense to go the opposite direction, and break out the launcher script into individual files? It's not yet at the point where it really needs that, but if it keeps growing that will eventually be a tech debt item and maybe it could be better to just get that out of the way now. Completely up to you though.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DESCRIPTION and COPYRIGHT are just assumed to be set in the calling script, and the signature of the management script is not that common in other CLI tools. Thus, compared to tools like getopt or getopts this feels somewhat more tightly coupled.

I would much rather have one larger script than many small libraries stuck together (at least in bash). The scoping in bash is a mess and I find it easier to grasp larger bash scripts. I don't think we have hit the point yet that the script has become unwieldy.


# shell script library to parse and validate command line arguments, and generate the --help text.

set -u

re_subcmd_vn='^[a-z0-9]+:[A-Za-z0-9_]+$'
COMMAND=

declare -A args args_help subcmds

add_arg() {
local short="$1"
local long="$2"
local varname="$3"
local help="$4"
local required="${5:-false}"
[ -v 6 ] && local default="$6"
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation, plus missing double brackets

if [[ "$varname" =~ $re_subcmd_vn ]]; then
local subc _vn
IFS=":" read subc _vn <<< "$varname"
[[ -n "${subcmds[$subc]}" ]]
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an implicit test that this subcommand is defined? If so please terminate explicitly here instead of relying on set -u.

fi
args[$varname]="$short $long $required"
args_help[$varname]="$help"
# init the global
[[ -v default ]] && declare -g ${varname#*:}="${default}"
}

add_subcommand() {
local subc="$1"
local help="$2"

subcmds[$subc]="$help"
}

usage() {
# help function. generates usage instructions
local short long required help
local n_subcmds=${#subcmds[@]}
local ofd=1
[[ -v 1 ]] && ofd=2
local cols=80
[[ -t $ofd ]] && cols=$(tput cols)
(
if [[ -v 1 ]]; then
echo "ERROR: $1"
echo ""
fi
if [[ -v DESCRIPTION ]]; then
echo -e "$DESCRIPTION"
echo ""
fi
if [[ $n_subcmds < 1 ]]; then
echo "Usage: $0 [options]"
echo ""
echo "Valid options are:"
else
echo "Usage: $0 [global options] COMMAND [command-specific options]"
echo ""
echo "Global options:"
fi
for varname in ${!args[@]}; do
[[ $varname =~ $re_subcmd_vn ]] && continue
IFS=" " read short long required <<< "${args[$varname]}"
help="${args_help[$varname]}"
printf " -%s, --%-16s %s (required: %s)\n" "$short" "$long" "$help" "$required"
done

if [[ $n_subcmds > 0 ]]; then
echo ""
echo "Valid commands:"
for subcmd in ${!subcmds[@]}; do
printf " %-12s %s\n" "$subcmd" "${subcmds[$subcmd]}"
done

for subcmd in ${!subcmds[@]}; do
echo ""
echo "Options for command \"$subcmd\":"
local n=0
for varname in ${!args[@]}; do
[[ "${varname%:*}" == "$subcmd" ]] || continue
((n++))
IFS=" " read short long required <<< "${args[$varname]}"
help="${args_help[$varname]}"
printf " -%s, --%-16s %s (required: %s)\n" "$short" "$long" "$help" "$required"
done
[[ $n == 0 ]] && echo " (None)"
done
echo ""

[[ -v COPYRIGHT ]] && echo -e "$COPYRIGHT"
fi
) | fold -w "$cols" -s >&$ofd
exit 1
}

parse_args() {
local short long required longprefix found
local n_subcmds=${#subcmds[@]}
declare -a bareargs reqargs
while [[ -v 1 ]]; do
case "$1" in
--help|-h)
usage ;;
-*)
# parse as named option
found=false
for varname in ${!args[@]}; do
IFS=" " read short long required <<< "${args[$varname]}"
if [[ $varname =~ $re_subcmd_vn ]]; then
# subcommand option
local vsubc _vn
IFS=":" read vsubc _vn <<< "$varname"
[[ "$vsubc" = "$COMMAND" ]] || continue
varname=$_vn
fi
longprefix="--$long="
case "$1" in
-$short|--$long)
[[ -v 2 ]] || usage "value for argument $1 may not be omitted"
declare -g $varname="$2"
found=true
shift
;;
$longprefix*)
found=true
declare -g $varname=${1:${#longprefix}}
;;
esac
done
[[ "$found" == "true" ]] || usage "Unknown option: $1"
;;
*)
if [[ $n_subcmds > 0 && $COMMAND == "" ]]; then
COMMAND="$1"
[[ -v subcmds[$COMMAND] ]] || usage "Undefined command: $COMMAND"
else
bareargs+=("$1")
fi
;;
esac
shift
done

[[ $n_subcmds > 0 && $COMMAND == "" ]] && usage "No command was given."

# build list of missing required args
for varname in ${!args[@]}; do
IFS=" " read short long required <<< "${args[$varname]}"
[[ "$required" == "true" ]] || continue
if [[ $varname =~ $re_subcmd_vn ]]; then
# subcommand option
local vsubc _vn
IFS=":" read vsubc _vn <<< "$varname"
[[ "$vsubc" = "$COMMAND" ]] || continue
[[ -v $_vn ]] && continue
reqargs+=("$varname")
else
[[ -v $varname ]] && continue
reqargs+=("$varname")
fi
done
# process bareword args
while [[ -v bareargs[0] && -v reqargs[0] ]]; do
declare -g ${reqargs[0]#*:}="${bareargs[0]}"
bareargs=("${bareargs[@]:1}")
reqargs=("${reqargs[@]:1}")
done

# if there's any bareword arguments left, we are out of ideas for what to do with them, so fail.
[[ -v bareargs[0] ]] && usage "Unknown argument: ${bareargs[0]}"

# enforce required args
for varname in ${!args[@]}; do
IFS=" " read short long required <<< "${args[$varname]}"
[[ "$required" == "true" ]] || continue
if [[ $varname =~ $re_subcmd_vn ]]; then
# subcommand arg
local vsubc _vn
IFS=":" read vsubc _vn <<< "$varname"
[[ "$vsubc" == "$COMMAND" ]] || continue
[[ ! -v $_vn ]] && usage "Option is required for command $vsubc but not set: $long"
else
# global arg
[[ ! -v $varname ]] && usage "Required option or positional argument not set: $long"
fi
done
}
16 changes: 16 additions & 0 deletions minecraftd-backup@.service.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[Unit]
Description=@GAME@ Server World Backup
After=local-fs.target

[Service]
Type=oneshot
Environment=SERVER_ROOT=@SERVER_ROOT@/servers/%i
Environment=BACKUP_DEST=@SERVER_ROOT@/servers/%i/backup
Environment=SESSION_NAME=@GAME@-%i
EnvironmentFile=-@INSTANCE_CONFIG_DIR@/%i
ExecStart=/usr/bin/@INAME@ backup
User=@GAME_USER@
Group=@GAME_USER@

[Install]
WantedBy=multi-user.target
10 changes: 10 additions & 0 deletions minecraftd-backup@.timer.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
Description=Daily @GAME@ Server Backup

[Timer]
OnCalendar=daily
AccuracySec=5min
Persistent=true

[Install]
WantedBy=multi-user.target
12 changes: 12 additions & 0 deletions minecraftd-init@.service.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this service file really necessary? It runs exactly once and is not needed afterwards, right?

Copy link
Copy Markdown
Author

@fuhry fuhry Jun 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried everything, but unfortunately, systemd's sandboxing affects all ExecStartPre= commands too.

Instead of this approach, we can update the launcher script to exit with an error after instructing the user to run the init command themselves prior to attempting to start a new server instance. They need to create a eula.txt file anyway, so that's not too terrible. Which do you prefer?

Copy link
Copy Markdown
Owner

@Edenhofer Edenhofer Jun 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I would much rather print an error and require user intervention than have a systemd service lying around that runs exactly once.

Description=Create server directories for @GAME@ %i instance
After=local-fs.target network.target multi-user.target

[Service]
Type=oneshot
RemainAfterExit=no
# create the "servers" directory followed by the instance directory
ExecStart=/usr/bin/@INAME@ -i %i init

[Install]
WantedBy=multi-user.target
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing new line at end of file

2 changes: 1 addition & 1 deletion minecraftd.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ BACKUP_PATHS="@BACKUP_PATHS@" # World paths separated by spaces relative to SERV
BACKUP_FLAGS="@BACKUP_FLAGS@"
KEEP_BACKUPS="@KEEP_BACKUPS@"
GAME_USER="@GAME_USER@"
MAIN_EXECUTABLE="@MAIN_EXECUTABLE@"
MAIN_EXECUTABLE="@MAIN_EXECUTABLE_ABSOLUTE@"
SESSION_NAME="@SESSION_NAME@"

# System parameters for java
Expand Down
Loading