Compare commits

...

6 Commits

17 changed files with 593 additions and 25 deletions

View File

@ -1,10 +1,13 @@
FROM openjdk:8u212-jre-alpine FROM openjdk:16-slim
EXPOSE 25565 RUN apt update
EXPOSE 25575 RUN apt install -y xxd cron
WORKDIR /mc-server COPY cron-backup /etc/cron.d/minecraft-backup
COPY . /mc-server RUN chmod 0644 /etc/cron.d/minecraft-backup
RUN chmod +x /mc-server/scripts/start.sh RUN crontab /etc/cron.d/minecraft-backup
CMD ["/bin/sh", "-c", "./scripts/start.sh"]
RUN touch /var/log/cron.log
CMD cron

View File

@ -15,5 +15,8 @@ docker-compose up -d
All necessary images should be downloaded automatically and the service should be started in the background. All necessary images should be downloaded automatically and the service should be started in the background.
## Template deployment
When starting a new instance from the template branch, you need to add your own `server.jar` file to the root of the folder for docker to start the server.
## Minecraft update ## Minecraft update
When an update is release by Mojang, the `jar` file must be updated and further configuration might be necessary to keep server optimization and quality of life improvements. When an update is release by Mojang, the `jar` file must be updated and further configuration might be necessary to keep server optimization and quality of life improvements.

View File

@ -1 +0,0 @@
[]

View File

@ -1 +0,0 @@
[]

1
cron-backup Normal file
View File

@ -0,0 +1 @@
0 */6 * * * /mc-server/scripts/backup_task.sh

View File

@ -8,7 +8,8 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
ports: ports:
- 25565:25565 - 25565:25565
- 25575:25575
volumes: volumes:
- ${PWD}/world:/mc-server/world - ${PWD}:/mc-server
working_dir: "/mc-server"
entrypoint: ["sh", "/mc-server/scripts/init.sh"]

Binary file not shown.

View File

@ -1,2 +0,0 @@
#Sat Aug 15 13:52:53 CEST 2020
serverJar=server.jar

View File

@ -1,6 +0,0 @@
# This is the configuration file for Lithium.
#
# You can find information on editing this file and all the available options here:
# https://github.com/jellysquid3/lithium-fabric/wiki/Configuration-File
#
# By default, this file will be empty except for this notice.

564
scripts/backup.sh Executable file
View File

@ -0,0 +1,564 @@
#!/usr/bin/env bash
# Minecraft server automatic backup management script
# https://github.com/nicolaschan/minecraft-backup
# MIT License
#
# For Minecraft servers running in a GNU screen, tmux, or RCON.
# For most convenience, run automatically with cron.
# Default Configuration
SCREEN_NAME="" # Name of the GNU Screen, tmux session, or hostname:port:password for RCON
SERVER_WORLDS=() # Server world directory
BACKUP_DIRECTORY="" # Directory to save backups in
MAX_BACKUPS=128 # -1 indicates unlimited
DELETE_METHOD="thin" # Choices: thin, sequential, none; sequential: delete oldest; thin: keep last 24 hourly, last 30 daily, and monthly (use with 1 hr cron interval)
COMPRESSION_ALGORITHM="gzip" # Leave empty for no compression
COMPRESSION_FILE_EXTENSION=".gz" # Leave empty for no compression; Precede with a . (for example: ".gz")
COMPRESSION_LEVEL=3 # Passed to the compression algorithm
ENABLE_CHAT_MESSAGES=false # Tell players in Minecraft chat about backup status
PREFIX="Backup" # Shows in the chat message
DEBUG=false # Enable debug messages
SUPPRESS_WARNINGS=false # Suppress warnings
RESTIC_HOSTNAME="" # Leave empty to use system hostname
LOCK_FILE="" # Optional lock file to acquire to ensure two backups don't run at once
LOCK_FILE_TIMEOUT="" # Optional lock file wait timeout (in seconds)
WINDOW_MANAGER="screen" # Choices: screen, tmux, RCON
# Other Variables (do not modify)
DATE_FORMAT="%F_%H-%M-%S"
TIMESTAMP=$(date +$DATE_FORMAT)
log-fatal () {
echo -e "\033[0;31mFATAL:\033[0m $*"
}
log-warning () {
echo -e "\033[0;33mWARNING:\033[0m $*"
}
debug-log () {
if "$DEBUG"; then
echo "$1"
fi
}
while getopts 'a:cd:e:f:hH:i:l:m:o:p:qr:s:t:u:vw:x' FLAG; do
case $FLAG in
a) COMPRESSION_ALGORITHM=$OPTARG ;;
c) ENABLE_CHAT_MESSAGES=true ;;
d) DELETE_METHOD=$OPTARG ;;
e) COMPRESSION_FILE_EXTENSION=".$OPTARG" ;;
f) TIMESTAMP=$OPTARG ;;
h) echo "Minecraft Backup"
echo "Repository: https://github.com/nicolaschan/minecraft-backup"
echo "-a Compression algorithm (default: gzip)"
echo "-c Enable chat messages"
echo "-d Delete method: thin (default), sequential, none"
echo "-e Compression file extension, exclude leading \".\" (default: gz)"
echo "-f Output file name (default is the timestamp)"
echo "-h Shows this help text"
echo "-H Set hostname for restic backup (restic only)"
echo "-i Input directory (path to world folder, use -i once for each world)"
echo "-l Compression level (default: 3)"
echo "-m Maximum backups to keep, use -1 for unlimited (default: 128)"
echo "-o Output directory"
echo "-p Prefix that shows in Minecraft chat (default: Backup)"
echo "-q Suppress warnings"
echo "-r Restic repo name (if using restic)"
echo "-s Screen name, tmux session name, or hostname:port:password for RCON"
echo "-t Enable lock file (lock file not used by default)"
echo "-u Lock file timeout seconds (empty = unlimited)"
echo "-v Verbose mode"
echo "-w Window manager: screen (default), tmux, RCON"
exit 0
;;
H) RESTIC_HOSTNAME=$OPTARG ;;
i) SERVER_WORLDS+=("$OPTARG") ;;
l) COMPRESSION_LEVEL=$OPTARG ;;
m) MAX_BACKUPS=$OPTARG ;;
o) BACKUP_DIRECTORY=$OPTARG ;;
p) PREFIX=$OPTARG ;;
q) SUPPRESS_WARNINGS=true ;;
r) RESTIC_REPO=$OPTARG ;;
s) SCREEN_NAME=$OPTARG ;;
t) LOCK_FILE=$OPTARG ;;
u) LOCK_FILE_TIMEOUT=$OPTARG ;;
v) DEBUG=true ;;
w) WINDOW_MANAGER=$OPTARG ;;
*) log-fatal "Invalid option -$FLAG"; exit 1 ;;
esac
done
rcon-command () {
HOST="$(echo "$1" | cut -d: -f1)"
PORT="$(echo "$1" | cut -d: -f2)"
PASSWORD="$(echo "$1" | cut -d: -f3-)"
COMMAND="$2"
reverse-hex-endian () {
# Given a 4-byte hex integer, reverse endianness
while read -r -d '' -N 8 INTEGER; do
echo "$INTEGER" | sed -E 's/(..)(..)(..)(..)/\4\3\2\1/'
done
}
decode-hex-int () {
# decode little-endian hex integer
while read -r -d '' -N 8 INTEGER; do
BIG_ENDIAN_HEX=$(echo "$INTEGER" | reverse-hex-endian)
echo "$((16#$BIG_ENDIAN_HEX))"
done
}
stream-to-hex () {
xxd -ps
}
hex-to-stream () {
xxd -ps -r
}
encode-int () {
# Encode an integer as 4 bytes in little endian and return as hex
INT="$1"
# Source: https://stackoverflow.com/a/9955198
printf "%08x" "$INT" | sed -E 's/(..)(..)(..)(..)/\4\3\2\1/'
}
encode () {
# Encode a packet type and payload for the rcon protocol
TYPE="$1"
PAYLOAD="$2"
REQUEST_ID="$3"
PAYLOAD_LENGTH="${#PAYLOAD}"
TOTAL_LENGTH="$((4 + 4 + PAYLOAD_LENGTH + 1 + 1))"
OUTPUT=""
OUTPUT+=$(encode-int "$TOTAL_LENGTH")
OUTPUT+=$(encode-int "$REQUEST_ID")
OUTPUT+=$(encode-int "$TYPE")
OUTPUT+=$(echo -n "$PAYLOAD" | stream-to-hex)
OUTPUT+="0000"
echo -n "$OUTPUT" | hex-to-stream
}
read-response () {
# read next response packet and return the payload text
HEX_LENGTH=$(head -c4 <&3 | stream-to-hex | reverse-hex-endian)
LENGTH=$((16#$HEX_LENGTH))
RESPONSE_PAYLOAD=$(head -c $LENGTH <&3 | stream-to-hex)
echo -n "$RESPONSE_PAYLOAD"
}
response-request-id () {
echo -n "${1:0:8}" | decode-hex-int
}
response-type () {
echo -n "${1:8:8}" | decode-hex-int
}
response-payload () {
echo -n "${1:16:-4}" | hex-to-stream
}
login () {
PASSWORD="$1"
encode 3 "$PASSWORD" 12 >&3
RESPONSE=$(read-response "$IN_PIPE")
RESPONSE_REQUEST_ID=$(response-request-id "$RESPONSE")
if [[ "$RESPONSE_REQUEST_ID" == "-1" ]] || [[ "$RESPONSE_REQUEST_ID" == "4294967295" ]]; then
log-warning "RCON connection failed: Wrong RCON password" 1>&2
return 1
fi
}
run-command () {
COMMAND="$1"
# encode 2 "$COMMAND" 13 >> "$OUT_PIPE"
encode 2 "$COMMAND" 13 >&3
RESPONSE=$(read-response "$IN_PIPE")
response-payload "$RESPONSE"
}
# Open a TCP socket
# Source: https://www.xmodulo.com/tcp-udp-socket-bash-shell.html
if ! exec 3<>/dev/tcp/"$HOST"/"$PORT"; then
log-warning "RCON connection failed: Could not connect to $HOST:$PORT"
return 1
fi
login "$PASSWORD" || return 1
debug-log "$(run-command "$COMMAND")"
# Close the socket
exec 3<&-
exec 3>&-
}
if ! "$DEBUG"; then
QUIET="-q"
else
QUIET=""
fi
if [[ "$COMPRESSION_FILE_EXTENSION" == "." ]]; then
COMPRESSION_FILE_EXTENSION=""
fi
# Check for missing encouraged arguments
if ! $SUPPRESS_WARNINGS; then
if [[ "$SCREEN_NAME" == "" ]]; then
log-warning "Minecraft screen/tmux/rcon location not specified (use -s)"
fi
fi
# Check for required arguments
MISSING_CONFIGURATION=false
if [[ "${#SERVER_WORLDS[@]}" == "0" ]]; then
log-fatal "Server world not specified (use -i)"
MISSING_CONFIGURATION=true
fi
if [[ "$BACKUP_DIRECTORY" == "" ]] && [[ "$RESTIC_REPO" == "" ]]; then
log-fatal "Backup location not specified (use -o or -r)"
MISSING_CONFIGURATION=true
fi
if [[ "$RESTIC_REPO" != "" ]]; then
if [[ "$BACKUP_DIRECTORY" != "" ]]; then
log-fatal "Both output directory (-o) and restic repo (-r) specified but only one may be used at a time"
MISSING_CONFIGURATION=true
fi
if [[ $MAX_BACKUPS -ge 0 ]] && [[ $MAX_BACKUPS -lt 70 ]] && [[ $DELETE_METHOD == "thin" ]]; then
log-fatal "Thinning delete with restic requires at least 70 snapshots to be kept. If you need to keep fewer than 70, use sequential delete."
MISSING_CONFIGURATION=true
fi
fi
if $MISSING_CONFIGURATION; then
exit 1
fi
if [[ "$BACKUP_DIRECTORY" != "" ]]; then
ARCHIVE_FILE_NAME="$TIMESTAMP.tar$COMPRESSION_FILE_EXTENSION"
ARCHIVE_PATH="$BACKUP_DIRECTORY/$ARCHIVE_FILE_NAME"
fi
if [[ "$RESTIC_REPO" != "" ]]; then
ARCHIVE_PATH="$RESTIC_REPO $TIMESTAMP"
fi
# Minecraft server screen interface functions
message-players () {
local MESSAGE=$1
local HOVER_MESSAGE=$2
message-players-color "$MESSAGE" "$HOVER_MESSAGE" "gray"
}
execute-command () {
local COMMAND=$1
if [[ $SCREEN_NAME != "" ]]; then
case $WINDOW_MANAGER in
"screen") screen -S "$SCREEN_NAME" -p 0 -X stuff "$COMMAND$(printf \\r)"
;;
"tmux") tmux send-keys -t "$SCREEN_NAME" "$COMMAND" ENTER
;;
"RCON"|"rcon") rcon-command "$SCREEN_NAME" "$COMMAND"
;;
esac
fi
}
message-players-error () {
local MESSAGE=$1
local HOVER_MESSAGE=$2
message-players-color "$MESSAGE" "$HOVER_MESSAGE" "red"
}
message-players-success () {
local MESSAGE=$1
local HOVER_MESSAGE=$2
message-players-color "$MESSAGE" "$HOVER_MESSAGE" "green"
}
message-players-color () {
local MESSAGE=$1
local HOVER_MESSAGE=$2
local COLOR=$3
debug-log "$MESSAGE ($HOVER_MESSAGE)"
if $ENABLE_CHAT_MESSAGES; then
execute-command "tellraw @a [\"\",{\"text\":\"[$PREFIX] \",\"color\":\"gray\",\"italic\":true},{\"text\":\"$MESSAGE\",\"color\":\"$COLOR\",\"italic\":true,\"hoverEvent\":{\"action\":\"show_text\",\"value\":{\"text\":\"\",\"extra\":[{\"text\":\"$HOVER_MESSAGE\"}]}}}]"
fi
}
# Parse file timestamp to one readable by "date"
parse-file-timestamp () {
local DATE_STRING
DATE_STRING="$(echo "$1" | awk -F_ '{gsub(/-/,":",$2); print $1" "$2}')"
echo "$DATE_STRING"
}
# Delete a backup
delete-backup () {
local BACKUP=$1
rm "$BACKUP_DIRECTORY"/"$BACKUP"
message-players "Deleted old backup" "$BACKUP"
}
# Sequential delete method
delete-sequentially () {
local BACKUPS=("$BACKUP_DIRECTORY"/*) # List oldest first
while [[ $MAX_BACKUPS -ge 0 && ${#BACKUPS[@]} -gt $MAX_BACKUPS ]]; do
delete-backup "$(basename "${BACKUPS[0]}")"
BACKUPS=("$BACKUP_DIRECTORY"/*)
done
}
# Functions to sort backups into correct categories based on timestamps
is-hourly-backup () {
local TIMESTAMP=$*
local MINUTE
MINUTE=$(date -d "$TIMESTAMP" +%M)
return "$MINUTE"
}
is-daily-backup () {
local TIMESTAMP=$*
local HOUR
HOUR=$(date -d "$TIMESTAMP" +%H)
return "$HOUR"
}
is-weekly-backup () {
local TIMESTAMP=$*
local DAY
DAY=$(date -d "$TIMESTAMP" +%u)
return "$((DAY - 1))"
}
# Helper function to sum an array
array-sum () {
SUM=0
for NUMBER in "$@"; do
(( SUM += NUMBER ))
done
echo "$SUM"
}
# Given two exit codes, print a nonzero one if there is one
exit-code () {
if [[ "$1" != "0" ]]; then
echo "$1"
else
if [[ "$2" == "" ]]; then
echo 0
else
echo "$2"
fi
fi
}
# Thinning delete method
delete-thinning () {
# sub-hourly, hourly, daily, weekly is everything else
local BLOCK_SIZES=(16 24 30)
# First block is unconditional
# The next blocks will only accept files whose names cause these functions to return true (0)
local BLOCK_FUNCTIONS=("is-hourly-backup" "is-daily-backup" "is-weekly-backup")
# Warn if $MAX_BACKUPS does not have enough room for all the blocks
TOTAL_BLOCK_SIZE=$(array-sum "${BLOCK_SIZES[@]}")
if [[ $MAX_BACKUPS != -1 ]] && [[ $TOTAL_BLOCK_SIZE -gt $MAX_BACKUPS ]]; then
if ! $SUPPRESS_WARNINGS; then
log-warning "MAX_BACKUPS ($MAX_BACKUPS) is smaller than TOTAL_BLOCK_SIZE ($TOTAL_BLOCK_SIZE)"
fi
fi
local CURRENT_INDEX=0
local BACKUPS=("$BACKUP_DIRECTORY"/*) # Oldest first
local NUM_BACKUPS="${#BACKUPS[@]}"
for BLOCK_INDEX in "${!BLOCK_SIZES[@]}"; do
local BLOCK_SIZE=${BLOCK_SIZES[BLOCK_INDEX]}
local BLOCK_FUNCTION=${BLOCK_FUNCTIONS[BLOCK_INDEX]}
local OLDEST_BACKUP_IN_BLOCK_INDEX=$((NUM_BACKUPS - 1 - (BLOCK_SIZE + CURRENT_INDEX))) # Not an off-by-one error because a new backup was already saved
if [ "$OLDEST_BACKUP_IN_BLOCK_INDEX" -lt 0 ]; then
break;
fi
local OLDEST_BACKUP_IN_BLOCK
OLDEST_BACKUP_IN_BLOCK="$(basename "${BACKUPS[OLDEST_BACKUP_IN_BLOCK_INDEX]}")"
local OLDEST_BACKUP_TIMESTAMP
OLDEST_BACKUP_TIMESTAMP=$(parse-file-timestamp "${OLDEST_BACKUP_IN_BLOCK:0:19}")
local BLOCK_COMMAND="$BLOCK_FUNCTION $OLDEST_BACKUP_TIMESTAMP"
if $BLOCK_COMMAND; then
# Oldest backup in this block satisfies the condition for placement in the next block
debug-log "$OLDEST_BACKUP_IN_BLOCK promoted to next block"
else
# Oldest backup in this block does not satisfy the condition for placement in next block
delete-backup "$OLDEST_BACKUP_IN_BLOCK"
break
fi
((CURRENT_INDEX += BLOCK_SIZE))
done
delete-sequentially
}
delete-restic-sequential () {
if [ "$MAX_BACKUPS" -ge 0 ]; then
restic forget -r "$RESTIC_REPO" --keep-last "$MAX_BACKUPS" "$QUIET"
fi
}
delete-restic-thinning () {
if [ "$MAX_BACKUPS" -ge 70 ]; then
# MAX_BACKUPS >= 70
restic forget -r "$RESTIC_REPO" --keep-last 16 --keep-hourly 24 --keep-daily 30 --keep-weekly $((MAX_BACKUPS - 70)) "$QUIET"
else
# We have a check that MAX_BACKUPS is not 70 > MAX_BACKUPS >= 0, so we can assume here it is negative
# Negative means don't delete old snapshots
restic forget -r "$RESTIC_REPO" --keep-last 16 --keep-hourly 24 --keep-daily 30 --keep-weekly 9999999 "$QUIET"
fi
}
# Delete old backups
delete-old-backups () {
if [[ "$BACKUP_DIRECTORY" != "" ]]; then
case $DELETE_METHOD in
"sequential") delete-sequentially
;;
"thin") delete-thinning
;;
esac
fi
if [[ "$RESTIC_REPO" != "" ]]; then
case $DELETE_METHOD in
"sequential") delete-restic-sequential
;;
"thin") delete-restic-thinning
;;
esac
fi
}
clean-up () {
# Re-enable world autosaving
execute-command "save-on"
# Save the world
execute-command "save-all"
TIME_DELTA=$((END_TIME - START_TIME))
if [[ "$BACKUP_DIRECTORY" != "" ]]; then
WORLD_SIZE_BYTES=$(du --bytes --total --max-depth=0 "${SERVER_WORLDS[@]}" | tail -n 1 | awk '{print $1}')
ARCHIVE_SIZE_BYTES=$(du -b "$ARCHIVE_PATH" | awk '{print $1}')
ARCHIVE_SIZE=$(du -h "$ARCHIVE_PATH" | awk '{print $1}')
BACKUP_DIRECTORY_SIZE=$(du -h --max-depth=0 "$BACKUP_DIRECTORY" | awk '{print $1}')
# Check that archive size is not null and at least 200 Bytes
if [[ "$ARCHIVE_EXIT_CODE" == "0" && "$WORLD_SIZE_BYTES" -gt 0 && "$ARCHIVE_SIZE" != "" && "$ARCHIVE_SIZE_BYTES" -gt 200 ]]; then
# Notify players of completion
COMPRESSION_PERCENT=$((ARCHIVE_SIZE_BYTES * 100 / WORLD_SIZE_BYTES))
message-players-success "Backup complete!" "$TIME_DELTA s, $ARCHIVE_SIZE/$BACKUP_DIRECTORY_SIZE, $COMPRESSION_PERCENT%"
delete-old-backups
exit 0
else
rm "$ARCHIVE_PATH" # Delete bad archive so we can't fill up with bad archives
message-players-error "Backup was not saved!" "Please notify an administrator"
exit 1
fi
fi
if [[ "$RESTIC_REPO" != "" ]]; then
if [[ "$ARCHIVE_EXIT_CODE" == "0" ]]; then
message-players-success "Backup complete!" "$TIME_DELTA s"
delete-old-backups
exit 0
else
message-players-error "Backup was not saved!" "Please notify an administrator"
exit 1
fi
fi
}
trap "clean-up" 2
do-backup () {
# Notify players of start
message-players "Starting backup..." "$ARCHIVE_PATH"
# Disable world autosaving
execute-command "save-off"
# Backup world
START_TIME=$(date +"%s")
if [[ "$BACKUP_DIRECTORY" != "" ]]; then
# Ensure backup directory exists
mkdir -p "$(dirname "$ARCHIVE_PATH")"
case $COMPRESSION_ALGORITHM in
# No compression
"") tar -cf "$ARCHIVE_PATH" "${SERVER_WORLDS[@]}"
;;
# With compression
*) tar -cf - "${SERVER_WORLDS[@]}" | $COMPRESSION_ALGORITHM -cv -"$COMPRESSION_LEVEL" - > "$ARCHIVE_PATH" 2>> /dev/null
;;
esac
EXIT_CODES=("${PIPESTATUS[@]}")
# tar exit codes: http://www.gnu.org/software/tar/manual/html_section/Synopsis.html
# 0 = successful, 1 = some files differ, 2 = fatal
if [ "${EXIT_CODES[0]}" == "1" ]; then
log-warning "Some files may differ in the backup archive (file changed as read)"
TAR_EXIT_CODE="0"
else
TAR_EXIT_CODE="${EXIT_CODES[0]}"
fi
ARCHIVE_EXIT_CODE="$(exit-code "$TAR_EXIT_CODE" "${EXIT_CODES[1]}")"
if [ "$ARCHIVE_EXIT_CODE" -ne 0 ]; then
log-fatal "Archive command exited with nonzero exit code $ARCHIVE_EXIT_CODE"
fi
fi
if [[ "$RESTIC_REPO" != "" ]]; then
RESTIC_TIMESTAMP="${TIMESTAMP:0:10} ${TIMESTAMP:11:2}:${TIMESTAMP:14:2}:${TIMESTAMP:17:2}"
if [[ "$RESTIC_HOSTNAME" == "" ]]; then
RESTIC_HOSTNAME_OPTION=()
else
RESTIC_HOSTNAME_OPTION=("--host" "$RESTIC_HOSTNAME")
fi
restic backup -r "$RESTIC_REPO" "${SERVER_WORLDS[@]}" --time "$RESTIC_TIMESTAMP" "$QUIET" "${RESTIC_HOSTNAME_OPTION[@]}"
ARCHIVE_EXIT_CODE=$?
if [ "$ARCHIVE_EXIT_CODE" -eq 3 ]; then
log-warning "Incomplete snapshot taken (some files could not be read)"
ARCHIVE_EXIT_CODE="0"
else
if [ "$ARCHIVE_EXIT_CODE" -ne 0 ]; then
# According to the restic docs, exit code is either 0, 1, or 3
# Exit code 1 means fatal
# See: https://restic.readthedocs.io/en/latest/040_backup.html
log-fatal "No restic snapshot created (exit code $ARCHIVE_EXIT_CODE)"
fi
fi
fi
sync
END_TIME=$(date +"%s")
clean-up
}
if [[ "$LOCK_FILE" != "" ]]; then
TIMEOUT_OPTION=()
if [[ "$LOCK_FILE_TIMEOUT" != "" ]]; then
TIMEOUT_OPTION=("-w" "$LOCK_FILE_TIMEOUT")
fi
(if ! flock "${TIMEOUT_OPTION[@]}" --no-fork 200; then
log-fatal "Could not acquire lock on lock file: $LOCK_FILE"
exit 1
fi
do-backup) 200>"$LOCK_FILE"
else
do-backup
fi

1
scripts/backup_task.sh Executable file
View File

@ -0,0 +1 @@
/mc-server/scripts/backup.sh -c -i /mc-server/world -o /mc-server/backups -s localhost:25575:secret -w rcon

2
scripts/init.sh Normal file
View File

@ -0,0 +1,2 @@
sh -c "sleep 60 && /mc-server/scripts/backup_task.sh" &
/mc-server/scripts/start.sh

2
scripts/start.sh Normal file → Executable file
View File

@ -1 +1 @@
java -XX:+UseG1GC -Xmx10G -Xms10G -Dsun.rmi.dgc.server.gcInterval=2147483646 -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -jar /mc-server/fabric-server-launch.jar nogui java -XX:+UseG1GC -Xmx10G -Xms10G -Dsun.rmi.dgc.server.gcInterval=2147483646 -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -jar /mc-server/server.jar nogui

Binary file not shown.

View File

@ -1,5 +1,5 @@
#Minecraft server properties #Minecraft server properties
#Sun Aug 23 18:38:11 CEST 2020 #Sun Jul 18 17:40:53 UTC 2021
enable-jmx-monitoring=false enable-jmx-monitoring=false
rcon.port=25575 rcon.port=25575
level-seed= level-seed=
@ -12,11 +12,12 @@ motd=\u00A7e\u00A7lServeur SNIR\u00A7r \u00A77\u00A7oPowered by Bernard Inc.
query.port=25565 query.port=25565
pvp=true pvp=true
generate-structures=true generate-structures=true
difficulty=easy difficulty=hard
network-compression-threshold=256 network-compression-threshold=256
require-resource-pack=false
max-tick-time=60000 max-tick-time=60000
use-native-transport=true
max-players=20 max-players=20
use-native-transport=true
online-mode=true online-mode=true
enable-status=true enable-status=true
allow-flight=false allow-flight=false
@ -24,6 +25,7 @@ broadcast-rcon-to-ops=true
view-distance=10 view-distance=10
max-build-height=256 max-build-height=256
server-ip= server-ip=
resource-pack-prompt=
allow-nether=true allow-nether=true
server-port=25565 server-port=25565
enable-rcon=true enable-rcon=true
@ -32,9 +34,10 @@ op-permission-level=4
prevent-proxy-connections=false prevent-proxy-connections=false
resource-pack= resource-pack=
entity-broadcast-range-percentage=100 entity-broadcast-range-percentage=100
rcon.password= rcon.password=secret
player-idle-timeout=0 player-idle-timeout=0
force-gamemode=false force-gamemode=false
rate-limit=0
hardcore=false hardcore=false
white-list=true white-list=true
broadcast-console-to-ops=true broadcast-console-to-ops=true
@ -43,6 +46,7 @@ spawn-animals=true
snooper-enabled=true snooper-enabled=true
function-permission-level=2 function-permission-level=2
level-type=default level-type=default
text-filtering-config=
spawn-monsters=true spawn-monsters=true
enforce-whitelist=false enforce-whitelist=false
resource-pack-sha1= resource-pack-sha1=

View File

@ -1 +0,0 @@
[{"name":"ImGuitoune","uuid":"338a2692-aaf1-4e95-8fe6-4ab8496132e1","expiresOn":"2020-09-12 21:55:53 +0200"},{"name":"ArthurCuillere","uuid":"1939a9de-319e-468d-b080-de48cad53ccd","expiresOn":"2020-08-29 15:48:04 +0200"},{"name":"PoneyFoufou","uuid":"d51cd9fc-e3e8-433a-aac3-51915d9360b5","expiresOn":"2020-08-29 15:47:53 +0200"},{"name":"Valouuh","uuid":"4d1b4f47-c6f0-4c72-93c1-9428a9f3250f","expiresOn":"2020-08-29 15:47:58 +0200"},{"name":"tospot46","uuid":"7ec06095-61b7-49fc-8d14-9f1285733e31","expiresOn":"2020-09-11 17:25:11 +0200"},{"name":"Cervicales","uuid":"e6a2efcf-70dc-43c6-94e5-e82b20d6ad98","expiresOn":"2020-09-11 16:10:34 +0200"},{"name":"LeGrosCon","uuid":"e84cbb15-a08b-4437-9e75-485bcf03f78a","expiresOn":"2020-08-29 15:47:47 +0200"},{"name":"Iseii","uuid":"39cee4db-3168-440e-9ddd-3176a6559338","expiresOn":"2020-08-29 15:47:33 +0200"},{"name":"Flo_Poney","uuid":"3c2e07cb-e9d4-468d-93e3-ca2777e952ab","expiresOn":"2020-08-29 15:47:40 +0200"}]