Improving my update script for Debain

If I run the following command, I end up with git-paper-231

wget --no-cache

When I check it shows (currently) build 245. If I download this on my Windows 10 machine, I get git-paper-231

My initial suspicion is that the lastSuccessfulBuild was not properly updated, but I have seen older topics where it seems one person gets the old version but others get the new one.

Any idea how I can sort this out? It has broken my update script.

Please don’t use Jenkins - it needs to be heavily cached and this is one of the issues it causes. It’ll also be hidden in the future.

You can use Paper downloads API to easily download whatever version you want:

1 Like

Thanks, I will convert over!

Worked like a charm!

In case anyone would like it, here is my update script on Debian 10 with systemd using the API download instead.

This is run via crontab as root with output to a log file, for my setup this looks like:

0 4 7 * * /opt/minecraft/server/ >> /opt/minecraft/server/logs/update_cron.log

Set hostname, port, and password for mcron
in my configuration, mcron is under /opt/minecraft/tools/mcron
The server is at /opt/minecraft/server
These will need adjusted for your configuration
Minecraft is run under user ‘minecraft’


cd /opt/minecraft/server/;
touch /opt/minecraft/server/paperclip.jar.1
touch /opt/minecraft/server/paperclip.jar.2
touch /opt/minecraft/server/paperclip.jar.3
echo “Comparing Checksums”;
oldsum=$(md5sum paperclip.jar | awk ‘{print $1}’);
echo “Download paperclip for comparison”
/usr/bin/wget -N -O paperclip.jar.tmp --no-cache;
newsum=$(md5sum paperclip.jar.tmp | awk ‘{print $1}’);

if [[ “$oldsum” != “$newsum” ]]; then
echo “Update Required”;
echo “Stopping Server”;
/opt/minecraft/tools/mcrcon/mcrcon -H HOSTNAME -P PORT -p MCRONPASS stop;
echo “Rolling paperclip.jar files”;
/usr/bin/mv -f /opt/minecraft/server/paperclip.jar.2 paperclip.jar.3;
/usr/bin/mv -f /opt/minecraft/server/paperclip.jar.1 paperclip.jar.2;
/usr/bin/mv -f /opt/minecraft/server/paperclip.jar paperclip.jar.1;
echo “Installing new paperclip.jar”;
/usr/bin/mv -f /opt/minecraft/server/paperclip.jar.tmp /opt/minecraft/server/paperclip.jar
echo “Set file permissions”;
/usr/bin/chown minecraft:minecraft paperclip.jar;
echo “Update Process Complete”;
echo “Starting Minecraft”
systemctl start minecraft
echo “Exiting”
exit 0;

@Mr.Ike Please note that auto-updating is advised against. Just this week Paper released a build that irreversibly damaged world saves - number 234. You’ll notice that 235 was released shortly afterwards with the change reversed:

This is especially concerning given that your script doesn’t take a backup before starting the server with new jar.

While ideally one would have a second server to easily test every release before applying on production server, it’s not always feasible or required. Just make sure you understand risks.

Please, take backups and make sure they work.

1 Like

Ah, good point. I have a backup script that runs hourly as well as before the updater.

I should note that my server is just for friends and family. I would likely have a testing instance if this was a production-ready server.


0 * * * * su minecraft -c “/opt/minecraft/server/” >> /opt/minecraft/server/logs/backup_cron.log

Edit: Block quoting messed up the command syntax. Used Pastebin instead (should have done that from the start).

This is what I meant when I said:

While I could write quite a lenghty post about all the ways your scripts might be unsafe, the main 2 things are:

  1. You should use bash errexit, nounset and pipefail options, to make your scripts more secure and handle more edge-cases. You can enable them by writing set -euo pipefail after you shebang.
  2. You should execute save-off before save-all. save-off means “Don’t add new chunks to the save queue automatically”. Then you run save-all which means “Add all loaded chunks to save queue now”. After that you should wait a few seconds because Paper has incremental saving spread over multiple ticks, and also for the process to flush all data to disk (can be forced with save-all-flush iirc, but not recommend as it force everything to happen in a single tick).

I’m glad the change to the downloads API worked for you :slight_smile:

Hey, I appreciate the extra tips! I will look into point 1 and implement it, as for point 2 that is simple enough to fix.

+1 :slight_smile:

I have implemented your suggestions as well as researched other ‘best-practices’ to implement.

I added:
set -eu -o pipefail
to my scripts and
|| true;
to the end of any command allowed to fail.

Some other notes for anyone else reading this thread:

  • Using passwords in scripts is considered ill-advised. Since this machine is private, there is less risk of anyone snooping into the script. If they have access to the Debian install, I would have bigger concerns than my mcrcon password.
  • Always quote your variable calls.
  • Do not allow user input unless you can sanitize it properly.
  • Always call binaries by their full path (both good for security and avoids issues with shell path variables)
  • set -f can be useful to disable globbing when not needed as this can be abused.
  • Set an exit status when ending.
  • Remember to set file permissions for scripts to prevent unauthorized read/write/execution
  • Prefer expanded command options over abbreviated (Example: ls --all instead of ls -a) for readability.
  • If possible, use a higher-level language to write your command functions such as python. This will allow more security options in your code.
1 Like