Got a new server! It's way cooler than the last one.

I even have Terraria running as a systemd unit, cleanly saving the world state when shutting down, automatically starting up on system boot, logging to the system log, and with a fifo for sending it commands.

Terraria dedicated server

Originally, I had the Terraria server start with a FIFO being piped in as input, but quickly found out that you could pretty much only ever enter a single server command. Once the process that you use to enter the command is done, the FIFO spits out an end-of-file signal, causing the server (or process that was piping to the server) to stop accepting any new input.

There were various unreliable ways of making 'tail -f' or 'cat' do kinda sorta what I wanted, but I decided to just knock out some very simple C++ code to do the job for me.

Behold, the EOF filter...

pipewrapper.cpp

 1 #include <iostream>
 2 #include <fstream>
 3 using namespace std;
 4 
 5 int main(int argc, char *argv[])
 6 {
 7     fstream pipefile;
 8     bool quit = false;
 9 
10     if(argc < 2) {
11         cerr << "Usage: " << argv[0] << " <input fifo>" << endl;
12         return 1;
13     }
14 
15     while(!quit) {
16         pipefile.open(argv[1]);
17 
18         if(!pipefile.good()) {
19             cerr << "Could not (re)open input file." << endl;
20             break;
21         }
22 
23         while(pipefile.good()) {
24             std::string line;
25             getline(pipefile, line);
26 
27             if(line == "reallyexit") {
28                 quit = true;
29                 break;
30             } else {
31                 cout << line << endl;
32             }
33         }
34         pipefile.close();
35     }
36 
37 
38 	return 0;
39 }

Yup. That's it. It just keeps its own output going, and re-opens the input file (supplied as the first command line argument) every time it finds it closed. Once it receives a special command, "reallyexit", it shuts itself down (and doesn't pass this message along to the output).

Here are the other scripts involved in keeping this thing running...

server_run.bsh
(This one is expected to run until the server is shutdown.)

 1 #!/bin/bash
 2 
 3 echo "----------------------------------------" >> log.txt
 4 echo " Server starting at $(date)" >> log.txt
 5 echo "----------------------------------------" >> log.txt
 6 
 7 cd terraria_install
 8 ../pipewrapper_bin ../server_stdin | \
 9     ./TerrariaServer \
10         -world ../worlds/PUT_YOUR_WORLDFILE_HERE.wld \
11         -pass PUT_YOUR_PASSWORD_HERE | tee ../log.txt

Note: It is definitely better to use the Terraria server config files instead of sticking your password in the command line. It doesn't matter here because everyone who has access to the server has access to the Terraria server too.

Note: 'server_stdin' is the FIFO. 'terraria_install' is the directory under this one that a copy of the Terraria install right out of a Steam directory lives. 'worlds' is a directory containing all the .wld files. 'pipewrapper_bin' is just the compiled binary for 'pipewrapper.cpp'.

server_shutdown.bsh

 1 #!/bin/bash
 2 
 3 SERVER_STILL_RUNNING_COMMAND="pgrep -u $USER TerrariaServer"
 4 
 5 if $SERVER_STILL_RUNNING_COMMAND > /dev/null; then
 6     echo "Server is up.";
 7 else
 8     echo "Server is not running. Are you running it as a different user?";
 9     exit 0;
10 fi
11 
12 echo "Sending exit command..."
13 echo "exit" > server_stdin
14 
15 echo "Waiting for TerrariaServer process to quit..."
16 while $SERVER_STILL_RUNNING_COMMAND > /dev/null; do
17     sleep 1;
18 done
19 
20 echo "Shutting down pipe..."
21 echo "reallyexit" > server_stdin
22 
23 echo "Server shutdown complete!"

This one issues the 'exit' command to the server. It then waits for it to shut down (blocking the server shutdown process for a bit while the Terraria server saves the world). Finally, it issues that 'reallyexit' command to kill the pipe.

Note: This has a serious flaw in it. You can't run multiple Terraria servers on the same system, or this command will never finish until ALL the servers have been shut down. It's just a quick-and-dirty implementation. A correct version would involve some PID wrangling that I didn't want to mess with at the time!

terraria.service

 1 [Unit]
 2 Description=Terraria server
 3 After=network.target
 4 
 5 [Service]
 6 User=terraria
 7 Type=simple
 8 ExecStart=/home/terraria/Terraria/server_run.bsh
 9 ExecStop=/home/terraria/Terraria/server_shutdown.bsh
10 WorkingDirectory=/home/terraria/Terraria
11 TimeoutStopSec=20
12 KillMode=mixed
13 
14 [Install]
15 WantedBy=multi-user.target

This one lives in '/lib/systemd/system'. This is the systemd unit file. It just runs the Terraria server setup out of the 'terraria' user's home directory, in simple mode.

With this setup, some useful commands are...

journalctl -u terraria
View the output logs of the Terraria server. Doesn't show much. Just the stuff that usually goes to the console when running the server.
systemctl list-units terraria.service
View the status of the Terraria service.
systemctl stop terraria
Shutdown the server.
systemctl start terraria
Start the server.

Depending on if there's any interest in this or not, I might be able to cobble together a more convenient package, with proper PID wrangling and all that stuff. Hope this is useful to anyone else trying it.

I'm also interested in any feedback that might help make this a little more solid. It works great for this specific server in a one-instance thing I have going on here, but it could be a little nicer.

[ permalink / comments ]

I have once again reconstructed my website from... uh... something. This time it's based on Jekyll.

Still no guarantees that I'll actually update the stupid thing, but I'll try.

In other news, today was my last day at Trion Worlds, where I was working on Rift. I've moved on to Neoglyphic Entertainment, where I'm going to work with some old friends on some really cool upcoming projects.

Hey look. There's my attempt at blogging. Whee.

[ permalink / comments ]

Here's the big ugly testing post. When I figure out how to do something cool in Jekyll I'll stick it here as a note for future me.

More after the break.

View full article

[ permalink / comments ]

Next page
Copyright © 2015 Clifford Jolly
All rights reserved