Skip to content

Instantly share code, notes, and snippets.

@ipiepiepie
Forked from Prof-Bloodstone/README.md
Last active June 27, 2023 01:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ipiepiepie/4ce306b0e96e8bc5bd04adfb3426c376 to your computer and use it in GitHub Desktop.
Save ipiepiepie/4ce306b0e96e8bc5bd04adfb3426c376 to your computer and use it in GitHub Desktop.
Spigot restart script issues and solution (for Windows)

⚠️ This guide is for self-managed servers. If you rented a server and got a website through which you manage your server - you are on so called shared-hosting and this guide won't work for you.

What is spigot restart script

Spigot added a feature allowing for server to automatically restart on crashes, as well as when authorized user executes /restart command.

How it works

When server starts to shut down, it spawns a new process which runs your restart script, as specified in spigot.yml under settings.restart-script, which defaults to ./start.sh. The idea is that the original server will stop completely, and the new instance will take its place.

Why is it an issue

Because the new server is created before old one fully stopped, this means:

  1. You need enough spare resources, to temporarily run 2 servers at the same time, as the old instance haven't freed up CPU/RAM while the new one starts and prepares itself.
  2. You might hit Unable to bind to port errors, because old server is still occupying the port.
  3. You might hit Is another instance running error, mentioning that world/session.lock is in use

Because the new server is being detached, that means that if you use tmux or screen to start your server, it no longer will give you access to server console after restart.

How can this be fixed

The solution is simple - don't let the restart script start any server, but instead have it communicate with your start script that when old instance is shut down, it should start a new one instead.

How can I do it?

The easiest way is to simply create 2 scripts - start.bat which will be the start script, and restart.bat which will be used by Spigot to notify that a restart is needed.

First, configure spigot.yml to use your restart script instead:

settings:
  restart-script: restart.bat

Finally, copy the attached to this gist start.bat and restart.bat scripts and place them in your server folder from where you start it, which usually is the same directory where server jar, settings and worlds are in. Make sure to understand what they do and change memory setting and other flags to your liking.

Now you can start your server by running start.bat. That's it!

But what about Linux?

You can find Bash version of this script here

I have questions / issues

If you have questions, its best to ask them here so others can see. Alternatively, reach me over on Discord pie#1308.

Known issues

'.' is not recognized as an internal or external command

It can appear on restart if you forgot to remove ./ in start of your restart-script in spigot.yml

Solutions:

  1. Change ./restart.bat to restart.bat in spigot.yml
@echo off
:: We need to use script, since it's hardcoded in spigot
:: Doesn't matter much, since it doesn't do much anyway
:: This script only creates a file which tells `start.bat` that it should restart, instead of exiting.
:: Make sure to change this, if you modified `restart_flag` in `start.bat`!
type nul > .restart_flag
exit 0
@echo off
:: SETTINGS
:: Path to file used to communicate from restart script
set "restart_flag=.restart_flag"
:: How long (in seconds) to wait before restarting
set "restart_delay=5"
:: Whether to restart on crash or not
:: The `settings.restart-on-crash` setting in spigot.yml doesn't always work
:: but also sometimes server might not return proper exit code,
:: so it's best to keep both options enabled
:: Accepted values: y/yes/true/n/no/false
set "restart_on_crash=yes"
:: The name of your server jar
set "server_jar=craftbukkit.jar"
:: What will be passed to `-Xms` and `-Xmx`
set "heap_size=1G"
:: JVM startup flags
:: NOTE: -Xms and -Xmx are set separately
:: These are mostly "Aikar flags"
:: taken from: https://mcflags.emc.gs/
:: TODO try to add one per line for better readability
set "jvm_flags=-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true"
:: Minecraft args you might want to start your server with
:: Usually there isn't much to configure here:
set "mc_args=--nogui"
:: END OF SETTINGS
:: Parse yes
if %restart_on_crash% == yes (set "should_restart_on_crash=1")
if %restart_on_crash% == y (set "should_restart_on_crash=1")
if %restart_on_crash% == true (set "should_restart_on_crash=1")
:: Parse no
if %restart_on_crash% == no (set "should_restart_on_crash=0")
if %restart_on_crash% == n (set "should_restart_on_crash=0")
if %restart_on_crash% == false (set "should_restart_on_crash=0")
:: If we can't initialise %restart_on_crash%, then user input is incorrect
if not defined should_restart_on_crash (
echo ERROR: Invalid value for ^"restart_on_crash^" variable: %restart_on_crash%
exit /b 1
)
:: The arguments that will be passed to java:
set jvm_args=-Xms%heap_size% -Xmx%heap_size% %jvm_flags% -jar %server_jar% %mc_args%
:: Remove restart flag, if it exists,
:: so that we won't restart the server after first stop,
:: unless restart script was called
del %restart_flag% 2>nul
:: Loop infinitely
:loop
:: Run server
java %jvm_args% || (
:: Oops, server didn't exit gracefully
echo Detected server crash ^(exit code: %ERRORLEVEL%^)
:: Check if we should restart on crash or not
if %should_restart_on_crash% == 1 (
type nul > %restart_flag%
)
)
:: Check if restart file exists or exit
if exist %restart_flag% (
:: The flag exists - try to remove it
del %restart_flag% 2>nul || (
:: If we can't remove it (permissions?), then exit to avoid endless restart loop
echo Error removing restart flag ^(exit code: %ERRORLEVEL%^)
exit /b 1
)
) else (
:: Flag doesn't exist, so break out of the loop
exit /b 0
)
:: Restart server with delay
echo Restarting server in %restart_delay% seconds, press Ctrl+C to abort.
timeout /T %restart_delay% /NOBREAK > nul || exit /b 0 REM Exit if timeout is interrupted (for example Ctrl+C)
goto loop
echo Server stopped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment