Needs:
- rdiff-backup
- tmux
- zstd
- tar
- awk
- ps
- grep
- cut
And obiously java
| #!/bin/bash | |
| # set default settings | |
| MCPATH=$(realpath $(dirname "$BASH_SOURCE[0]")) | |
| SERVICE=$(basename $MCPATH) | |
| BACKUPPATH="$MCPATH/backup" | |
| JAVA_OPTIONS="@user_jvm_args.txt" | |
| PORT=$(grep server-port $MCPATH/server.properties | cut -d '=' -f 2) | |
| JAVA=$(which java) | |
| JAR="-Dlog4j2.formatMsgNoLookups=true @libraries/net/minecraftforge/forge/1.19.2-43.2.8/unix_args.txt" | |
| INVOCATION="${JAVA} ${JAVA_OPTIONS} ${JAR} nogui" | |
| # load user settings | |
| if [ -f mc-config.sh ]; then | |
| source mc-config.sh | |
| fi | |
| if [ -z "$PORT" ]; then | |
| PORT=25565 | |
| fi | |
| # Settings end | |
| is_running() { | |
| if [ ! -e $MCPATH/java.pid ]; then | |
| return 1 | |
| fi | |
| pid=$(cat $MCPATH/java.pid) | |
| if [ -z $pid ]; then | |
| return 1 | |
| fi | |
| ps -eo "%p" | grep "^\\s*$pid\\s*\$" > /dev/null | |
| return $? | |
| } | |
| mc_start() { | |
| if is_running; then | |
| echo "Tried to start but $SERVICE was already running!" | |
| return | |
| fi | |
| echo -n "$SERVICE starting." | |
| cd $MCPATH | |
| tmux new-session -d -s "mc$PORT" -n "mc$PORT" "$INVOCATION" | |
| for (( i=0; i < 10; i++ )); do | |
| tmuxpid=$(tmux list-sessions -F "#{session_name} #{pid}" | awk -v port="mc$PORT" '$1 == port {print $2}') | |
| javapid=$(ps -eo '%P %p' | grep "^\\s*$tmuxpid " | awk -v tpid="$tmuxpid" '$1 == tpid {print $2}') | |
| if [[ -n "$tmuxpid" && -n "$javapid" ]]; then | |
| break | |
| fi | |
| echo -n . | |
| sleep 1 | |
| done | |
| echo | |
| if [[ -n "$tmuxpid" && -n "$javapid" ]]; then | |
| echo "$SERVICE is now running." | |
| echo "$javapid" > $MCPATH/java.pid | |
| else | |
| echo "Could not start $SERVICE." | |
| fi | |
| } | |
| mc_stop() { | |
| if ! is_running; then | |
| echo "$SERVICE was not running." | |
| return | |
| fi | |
| echo "$SERVICE saving map..." | |
| mc_exec "say SERVER SHUTTING DOWN IN 10 SECONDS. Saving map..." | |
| mc_exec "save-all" | |
| sleep 10 | |
| echo -n "$SERVICE stopping." | |
| mc_exec "stop" | |
| for (( i=0; i < 20; i++ )); do | |
| is_running || break | |
| echo -n . | |
| sleep 1 | |
| done | |
| echo | |
| if is_running; then | |
| echo "$SERVICE could not be shut down cleanly... still running." | |
| mc_kill | |
| else | |
| echo "$SERVICE is shut down." | |
| fi | |
| rm $MCPATH/java.pid | |
| } | |
| mc_saveoff() { | |
| if is_running; then | |
| echo "$SERVICE is running... suspending saves" | |
| mc_exec "say SERVER BACKUP STARTING. Server going readonly..." | |
| mc_exec "save-off" | |
| mc_exec "save-all" | |
| sync | |
| sleep 10 | |
| else | |
| echo "$SERVICE was not running. Not suspending saves." | |
| fi | |
| } | |
| mc_saveon() { | |
| if is_running; then | |
| echo "$SERVICE is running... re-enabling saves" | |
| mc_exec "save-on" | |
| mc_exec "say SERVER BACKUP ENDED. Server going read-write..." | |
| else | |
| echo "$SERVICE was not running. Not resuming saves." | |
| fi | |
| } | |
| mc_kill() { | |
| pid=$(cat $MCPATH/java.pid) | |
| echo "terminating process with pid $pid" | |
| kill $pid | |
| for (( i=0; i < 10; i++ )); do | |
| is_running || break | |
| sleep 1 | |
| done | |
| if is_running; then | |
| echo "$SERVICE could not be terminated, killing..." | |
| kill -SIGKILL $pid | |
| echo "$SERVICE killed" | |
| else | |
| echo "$SERVICE terminated" | |
| fi | |
| } | |
| mc_backup() { | |
| echo "Backing up minecraft world" | |
| [ -d "$BACKUPPATH/world" ] || mkdir -p "$BACKUPPATH/world" | |
| echo "*_old\m**/*_old" | \ | |
| rdiff-backup backup --exclude-globbing-filelist-stdin $MCPATH "$BACKUPPATH/world" | |
| echo "Backup complete" | |
| } | |
| mc_archive() { | |
| if (($(date +%H) == 0)) && (($(date +%M) < 15)); then | |
| echo "Compressing world..." | |
| folder=$BACKUPPATH/world | |
| archive=$BACKUPPATH/$(date +%Y-%m-%d).tar.zstd | |
| tar --zstd -cf "$archive"--exclude="rdiff-backup-data" -C "$folder" . | |
| echo "Deleting old archives" | |
| find $BACKUPPATH -maxdepth 1 -type f -mtime +7 -delete | |
| fi | |
| } | |
| mc_exec() { | |
| if is_running; then | |
| tmux send-keys -t "mc$PORT" "$@" C-m | |
| else | |
| echo "$SERVICE was not running. Not executing command." | |
| fi | |
| } | |
| case "$1" in | |
| start) | |
| mc_start | |
| ;; | |
| stop) | |
| mc_stop | |
| ;; | |
| restart) | |
| mc_stop | |
| mc_start | |
| ;; | |
| backup) | |
| mc_saveoff | |
| mc_backup | |
| mc_saveon | |
| mc_archive | |
| ;; | |
| exec) | |
| shift | |
| mc_exec "$@" | |
| ;; | |
| status) | |
| if is_running; then | |
| echo "$SERVICE is running." | |
| else | |
| echo "$SERVICE is not running." | |
| exit 1 | |
| fi | |
| ;; | |
| *) | |
| echo "Usage: $(readlink -f $0) {start|stop|restart|backup|exec|status}" | |
| exit 1 | |
| ;; | |
| esac | |
| exit 0 |