You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

21 lines
7.9 KiB

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>How to use tmux to send and receive things from your Minecraft server | tait.tech</title> <link rel="stylesheet" href="/assets/css/style.css"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="author" content="Tait Hoyem"> <meta name="keywords" content=""> <meta name="description" content=""> </head> <body> <div id="wrapper"> <header> <nav> <input type="checkbox" id="menu"> <label for="menu">&#9776;</label> <div class="menu-content"> <a href="/" class="nav-link">Home</a> <a href="/blog/" class="nav-link">Blog</a> <a href="https://github.com/TTWNO/" class="nav-link" target="_blank" rel="noopener noreferrer">Github</a> </div> </nav> </header> <main> <article> <header> <h1 class="post-title">How to use tmux to send and receive things from your Minecraft server</h1> <time datetime="20-06-25" class="post-date">Thursday, June 25 2020</time> </header> <hr> <p>So recently I had problem. I run a Minecraft server on a big Linux computer I have running in my room. Now, as a system administrator it is very helpful to be able to run some simple commands without needing to login with my key, password, TFA, etc. It is, frankly, a lot of work. Especially when I really just want to be playing games but I just need to check something quickly.</p> <p>So for simple things like finding out of the network, CPU, memory or disk usage is my bottleneck, I wrote this really nifty script to connect the world of Minecraft and the Linux shell.</p> <p>My completed solution for what I needed can be found at <a href="https://github.com/TTWNO/termcraft/">https://github.com/TTWNO/termcraft</a>.</p> <p>If you want some of the implementation details, stick around.</p> <h2 id="solution">Solution</h2> <p>So to solve this interesting problem, I decided to use <code class="language-plaintext highlighter-rouge">tmux</code>. <code class="language-plaintext highlighter-rouge">tmux</code> is a <strong>t</strong>terminal <strong>mu</strong>ltiple<strong>x</strong>er. This allows you to run a terminal session, then detach fromc it while it still runs in the background.</p> <p>This is very valuable when running command line applications that need to have an active console connection, like a Minecraft server.</p> <p>So first I looked at the <code class="language-plaintext highlighter-rouge">tmux</code> command <code class="language-plaintext highlighter-rouge">send-keys</code>.</p> <h4 id="send-keys"><code class="language-plaintext highlighter-rouge">send-keys</code></h4> <p><code class="language-plaintext highlighter-rouge">send-keys</code> allows you to send text, and key presses to a <code class="language-plaintext highlighter-rouge">tmux</code> session. Now assuming this <code class="language-plaintext highlighter-rouge">tmux</code> session is attached to a Minecraft server, there is no reason you could not run a command like this:</p> <pre class="terminal">
$ tmux send-keys "tell @a This is a Test" Enter
</pre> <p>This will send the text “tell @a This is a Test” to the Minecraft server. Then, it will hit the newline character, this will execute the command.</p> <p>So now we can send information to the server and have it tell the users something.</p> <p>But how do we get information about who is typing what in the Minecraft chat?</p> <h3 id="tmuxs-capture-pane-is-painful"><code class="language-plaintext highlighter-rouge">tmux</code>s <code class="language-plaintext highlighter-rouge">capture-pane</code> is painful</h3> <p>So in the manual page for <code class="language-plaintext highlighter-rouge">tmux</code> I can see a section recorded below for options I can give to the <code class="language-plaintext highlighter-rouge">capture-pane</code> subcommand.</p> <pre class="terminal">
-S and -E specify the starting and ending line numbers,
zero is the first line of the visible pane and negative
numbers are lines in the history. - to -S is the start
of the history and to -E the end of the visible pane. The
default is to capture only the visible contents of the pane.
</pre> <p>What it seems to be saying is I can start at line <code class="language-plaintext highlighter-rouge">-S n</code> and end at line <code class="language-plaintext highlighter-rouge">-E n</code>. Negative numbers start from the bottom, so <em>in theory</em> I can do the following: <code class="language-plaintext highlighter-rouge">tmux capture-pane -S -1</code> should capture only the last line, because Im starting from the last line. Right?</p> <p>No. It just doesnt work. Negative numbers do <em>not</em> work with the <code class="language-plaintext highlighter-rouge">tmux capture-pane</code> subcommand.</p> <p>So I did some simple UNIX piping, like so, to get just the last thing in the chat.</p> <pre class="terminal">
$ tmux capture-pane -p -t steve | tail -n1
[SERVER] [ExtraDebuggingInfoHere]: &lt;TaterTheTot&gt; MY_MESSAGE
</pre> <p>TaterTheTot is my Minecraft username :)</p> <p><code class="language-plaintext highlighter-rouge">-p</code> prints the result to the terminal/stdout.</p> <p><code class="language-plaintext highlighter-rouge">steve</code> is the name of the tmux session Im trying to pull form.</p> <p>So thats done! Beauty!</p> <p>Now that we have that, how can we extract the username and the message from the latest line?</p> <h3 id="grep"><code class="language-plaintext highlighter-rouge">grep</code></h3> <p><code class="language-plaintext highlighter-rouge">grep</code> is a command to find patterns of text. <code class="language-plaintext highlighter-rouge">grep</code> has an option to only show a matching pattern of text. This option is <code class="language-plaintext highlighter-rouge">-o</code>.</p> <p>Lets see how we can use this in conjunction with our latest line of server output to get our results.</p> <pre class="terminal">
$ echo "[DEBUG] [SERVER] blah blah: &lt;TaterTheTot&gt; MY_MESAGE" | grep -o "&lt;.&ast;&gt;"
&lt;TaterTheTot&gt;
</pre> <p>Now, thats my name with the &lt; and &gt; attached. Not bad! We can use the <code class="language-plaintext highlighter-rouge">sed</code> command to clean it up a bit.</p> <p>The syntax is like so: <code class="language-plaintext highlighter-rouge">select/somepattern/replacewith/global</code></p> <p>So the following command is: <code class="language-plaintext highlighter-rouge">s/[&lt;&gt;]//g</code></p> <p>Select any characters that are either &lt; or &gt;. Replace with nothing. Do so globally (as in, dont stop after you replace only one character).</p> <p>Take two!</p> <pre class="terminal">
$ echo "[DEBUG] [SERVER] blah blah: &lt;TaterTheTot&gt; MY_MESAGE" | grep -o "&lt;.&ast;&gt;" | sed 's/[&lt;&gt;]//g'
TaterTheTot
</pre> <p>Beautiful!</p> <p>Now what about that pesky message?</p> <h3 id="more-grep-more-sed">more <code class="language-plaintext highlighter-rouge">grep</code>; more <code class="language-plaintext highlighter-rouge">sed</code></h3> <p>Simple: capture everything after the &gt;. Leaving the users message entirely in tact.</p> <pre class="terminal">
$ echo "[DEBUG] [SERVER] blah blah: &lt;TaterTheTot&gt; MY_MESAGE" | grep -o "&gt;.&ast;$" | sed 's/&gt; //'
MY_MESSAGE
</pre> <p>So now we have a way to get the username of someone typing in the Minecraft server chat. We have a way to find out what they said. And, we have a way to respond.</p> <p>You can imagine how these might go together for your own use case.</p> <h3 id="conclusion">Conclusion</h3> <p>This shows some pretty fun stuff you can do with a few simple Linux commands and a Minecraft server.</p> <p>I hope you learned something and found my explanations not horrific haha!</p> <p>Remember to checkout the git repository to see what I did with it: <a href="https://github.com/TTWNO/termcraft">https://github.com/TTWNO/termcraft</a>.</p> <p>Happy hacking!</p> </article> </main> <hr> <footer> This page is mirrored on <a href="https://beta.tait.tech/2020/06/25/tmux-minecraft/">beta.tait.tech</a>. </footer> </div> </body> </html>