seeseekey.net - Invictus Deus Ex Machina

Auf einem meiner Raspberry Pi-Rechner läuft eine in Mono geschriebene Server-Applikation. Damit die Server-Applikation funktionierte benötigte sie natürlich die Mono Runtime. Diese kann unter Raspbian einfach mittels des Kommandos:

apt-get install mono-runtime

installiert werden. Als ich die Serverapplikation nach der Installation von Mono ausführen wollte erhielt ich allerdings folgende Fehlermeldung:

Missing method .ctor in assembly Melinda.dll, type System.Runtime.CompilerServices.ExtensionAttribute
Can't find custom attr constructor image: Melinda.dll mtoken ...

Dieses Problem ließ sich durch die Installation der Bibliothek libmono-system-core4.0-cil beheben:

apt-get install libmono-system-core4.0-cil

Im Anschluss erhielt ich bei einem erneuten Startversuch eine weitere Fehlermeldung:

Grapevine.Exceptions.Server.UnableToStartHostException occurred
An error occured when trying to start the Grapevine.Server.RestServer

In diesem Fall kam die Fehlermeldung vom REST-API Framework Grapevine. Allerdings war der Fehler nicht wirklich in der Bibliothek zu finden. Stück für Stück kamen weitere Fehlermeldungen wie diese:

System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.

zustande. Nach einiger Recherche war klar: auch in diesem Fall fehlten weitere Abhängigkeiten aus dem Mono-Framework. In diesem Fall half die Holzhammermethode; die Installation des kompletten Mono-Frameworks. Dazu wurde das Paket mono-complete mittels:

apt-get install mono-complete

installiert. Dieses nimmt ein paar mehr Megabyte als das Runtime-Paket in Anspruch, allerdings sind damit alle möglichen Abhängigkeiten installiert. Somit kann man sich auf die eigentliche Entwicklung und Ausführung der eigenen Applikationen konzentrieren, anstatt einer kuriosen Fehlermeldung nach der anderen hinter her zu jagen.

In den letzten Tagen gab es zwei Artikel zum Thema Counter-Strike 1.6 Server:

In diesem Artikel, der die Fortsetzung der obigen Artikel darstellt, soll es um die Installation von Bots auf dem Counter-Strike 1.6 Server gehen. Damit kann auch gespielt werden wenn auf Server mal nicht so viel los ist. Zur Installation des POD-bot wird wieder das Metamod benötigt, welches im letzten Artikel im Zusammenhang mit dem AMX Mod installiert wurde. Zur Installation laden wir den POD-bot herunter und verschieben ihn in den addons-Ordner:

wget https://seeseekey.net/wp-content/uploads/2017/04/podbot.zip
unzip podbot.zip
rm podbot.zip
mv podbot /home/counterstrike/game/cstrike/addons/podbot

Anschließend muss der POD-bot Mod aktiviert werden. Dazu editieren wir die Datei /home/counterstrike/game/cstrike/addons/metamod/plugins.ini und fügen dort folgendes hinzu:

; POD-bot
win32 addons/podbot/podbot_mm.dll
linux addons/podbot/podbot_mm_i386.so

Damit ist die Grundinstallation des POD-bot abgeschlossen. In der Datei /home/counterstrike/game/cstrike/addons/podbot/podbot.cfg kann der POD-bot nun im Einzelnen konfiguriert werden. Besonders interessant sind dabei folgende Optionen:

# passwordkey - need set as setinfo to get access to the main podbot menu.
# usage (in the below example You may need to write Your-own passwordkey
# string instead default _pbadminpw - if You changed it):
# setinfo _pbadminpw "your_password"
pb_passwordkey "_pbadminpw"

# Set the password to have access to the podbot menu on DS by 'pb menu'
# console command typed in client's admin PC or called from the binded key.
# Example of bind on Your client PC:
# bind "=" "pb menu"
pb_password "your_password"

# Switches to on/off Botchatting. <0|1>. Default is 1.
pb_chat 1

# Set the below value to 1 to enable auto kill bots if all human players
# are dead already. <0|1>. Default is 0.
pb_autokill 0

# Set the below value to delay (in seconds) autokill bots if
# autokill function is enabled (above). Default is 45.
pb_autokilldelay 45

# These lines below are adding automatically the bots to the server when
# the new game is created on the listenserver or the dedicated server
# is starting.
# As many such lines like "pb add" is here as many bots will be added
# to the server (unless You will not exceed pb_maxbots setting).
pb add 100
pb add 100

Mit dem Kommando:

setinfo _pbadminpw "your_password"

weist man sich gegenüber dem POD-bot aus und erhält administrative Rechte und kann anschließend das Kommando:

pb menu

in der Counter-Strike-Konsole nutzen um die Bots zu konfigurieren.

Vor ein paar Tagen beschrieb ich wie man einen Counter-Strike 1.6 Server unter Ubuntu aufsetzt. Dem Server in der Vanila-Version fehlen allerdings einige Komfort-Features wie z.B. das Voten von Maps. Möchte man diese Funktionalität nutzen, benötigt man ein entsprechendes Mod. Hier empfiehlt es sich das AMX Mod zu installieren. Dieses benötigt den Metamod, der allerdings direkt im Paket enthalten ist. Im ersten Schritt muss der Mod auf dem Server installiert werden. Dazu wechselt man auf das Home-Verzeichnis des Servernutzers und gibt dort folgende Kommandos ein:

mkdir amxmod
cd amxmod
wget http://www.amxmod.net/amxfiles/amxmod_2010.1/amxmod_2010.1_cs-en.zip
unzip amxmod_2010.1_cs-en.zip 
rm amxmod_2010.1_cs-en.zip
cp * /home/counterstrike/game/cstrike/ -r
cd ..
rm -r amxmod/

Mit den Kommandos wird der Mod heruntergeladen und an die richtige Stelle verschoben. Anschließend muss die Pluginliste für das Metamod aktiviert werden:

mv /home/counterstrike/game/cstrike/addons/metamod/sample_plugins.ini /home/counterstrike/game/cstrike/addons/metamod/plugins.ini

Damit das AMX Mod erkennt wer im Spiel über administrative Rechte verfügt, muss die users.ini-Datei bearbeitet werden. Diese befindet sich im Ordner /home/counterstrike/game/cstrike/addons/amx/config/users.ini. Der einfachste Weg den Administrator zu definieren ist es die Steam-ID des jeweiligen Spielers zu benutzen. Zur Ermittlung der Steam-ID des Spielers öffnet man im Spiel mittels der ^-Taste die Konsole und gibt dort den Befehl status ein. Anschließend kann der Nutzer der users.ini-Datei hinzugefügt werden:

"STEAM_0:1:12345"    ""       "abcefijmnopqrstu" "ce"

Dabei muss nur die Steam-ID im vorderen Teil geändert werden. Danach ist die Grundkonfiguration erledigt und der Server kann gestartet werden. Damit die Mods aktiviert werden, muss ein neuer Parameter beim Start übergeben werden:

-dll addons/metamod/dlls/metamod.so

In der vollständigen Kommandozeile könnte dies dann so aussehen:

./hlds_run -game cstrike +map de_dust2 +maxplayers 20 -dll addons/metamod/dlls/metamod.so

Sobald der Server hochgefahren ist kann in der Konsole des Spieles mittels des Befehls:

meta list

überprüft werden ob das Plugin erfolgreich gestartet wurde.

Der AMX Mod wurde erfolgreich installiert

In der Standard-Installation verfügt der AMX Mod über 76 Befehle, welche für den Betrieb und die Steuerung des Servers genutzt werden können:

1: amx_help - displays this help
2: amx_langmenu - displays language menu
3: amx_language [|save] - displays/sets/saves language
4: amx_listmaps - lists maps that can be nominated
5: amx_who - displays who is on server
6: say /currentmap - displays current map (say)
7: say /ff - displays friendly fire status (say)
8: say /flop15 - displays worst 15 players (MOTD)
9: say /flop15new - displays worst 15 players (MOTD)
10: say /hp - displays info. about your killer (chat)
11: amx_csayy [color]  - sends center hud message to all players - anonymous
12: amx_flicksay [color]  - sends flickering hud message to all players
13: amx_flicksayy [color]  - sends flickering hud message to all players - anonymous
14: amx_fsay   [color]  - sends hud message to all players
15: amx_fsayy   [color]  - sends hud message to all players - anonymous
16: amx_fxsay [color]  - sends fx hud message to all players
17: amx_fxsayy [color]  - sends fx hud message to all players - anonymous
18: amx_help - displays this help
19: amx_kick  [reason] - kicks
20: amx_kickmenu - displays kick menu
21: amx_langmenu - displays language menu
22: amx_language [|save] - displays/sets/saves language
23: amx_leave  [tag] [tag] [tag] - kicks non specified players
24: amx_listmaps - lists maps that can be nominated
25: amx_map  - changelevel
26: amx_mapmenu - displays changelevel menu
27: amx_name   - changes player's name
28: amx_plugcmdmenu [filename.amx/plugin name] - displays plugins commands menu
29: amx_psay   - sends private message
30: amx_psayy   - sends private message - anonymous
31: amx_say  - sends message to all players
32: amx_sayy  - sends message to all players - anonymous
33: amx_scrollsay [color]  - sends scroll message to all players
34: amx_scrollsayy [color]  - sends scroll message to all players - anonymous
35: amx_slap  [power] - slaps
36: amx_slapmenu - displays slap/slay menu
37: amx_slay  - slays
38: amx_speechmenu - displays speech menu
39: amx_teammenu - displays team menu
40: amx_teleportmenu - displays teleport menu
41: amx_tsay [color]  - sends left side hud message to all players
42: amx_tsayy [color]  - sends left side hud message to all players - anonymous
43: amx_vote    [answer #3] [answer #4] - starts a custom vote
44: amx_voteban  [ip] - starts a voteban
45: amx_voteff - starts a vote to enable/disable Friendly Fire
46: amx_votekick  - starts a votekick
47: amx_votemap  [map] [map] [map] - starts a votemap
48: amx_votemapmenu - displays votemap menu
49: amx_votenextmap [time] - the map will be changed [time] seconds after the end of the vote
50: amx_who - displays who is on server
51: amxmodmenu - displays menus
52: say <@[@|@]|#[#|#]|$[$|$]>[color]  - displays chat/hud message
53: say /currentmap - displays current map (say)
54: say /ff - displays friendly fire status (say)
55: say /flop15 - displays worst 15 players (MOTD)
56: say /flop15new - displays worst 15 players (MOTD)
57: say /hp - displays info. about your killer (chat)
58: say /me - displays current round stats (chat)
59: say /rank - displays your rank (chat)
60: say /rankstats - displays your server stats (MOTD)
61: say /rankstatsnew - displays your server stats (MOTD)
62: say /report - displays weapon status (say_team)
63: say /score - displays last score (chat)
64: say /stats - displays players stats (menu/MOTD)
65: say /statsme - displays your stats (MOTD)
66: say /streak - display info. about your killing streak
67: say /switch - switch client's stats on or off
68: say /thetime - displays the time (say)
69: say /timeleft - displays time left on map (say)
70: say /top15 - displays top 15 players (MOTD)
71: say /top15new - displays top 15 players (MOTD)
72: say currentmap - displays current map
73: say nextmap - displays next map
74: say thetime - displays current time
75: say timeleft - displays timeleft
76: say_team @ - displays message to admins

Counter-Strike 1.6 hat mittlerweile einige Jahre auf dem Buckel, gehört aber immer noch zu den beliebtesten Multiplayer-Spielen. Möchte man unter Ubuntu einen Server aufsetzen, so ist dies in wenigen Schritten erledigt. Im ersten Schritt müssen Abhängigkeiten installiert und ein Nutzer für den Server angelegt werden:

apt-get install lib32gcc1
adduser counterstrike

Nach dem Anlegen des Nutzers wird in dessen Kontext gewechselt und dort die Ordner-Infrastruktur angelegt:

su counterstrike
cd
mkdir steam
mkdir game

Nun steht die Installation des Steam-Kommandozeilen-Clients an:

cd steam
wget http://media.steampowered.com/installer/steamcmd_linux.tar.gz
tar -xvzf steamcmd_linux.tar.gz
rm steamcmd_linux.tar.gz

Danach kann der Steam-Client gestartet werden und der Counter-Strike-Server installiert werden:

./steamcmd.sh
login anonymous
force_install_dir /home/counterstrike/game/
app_update "90 -beta Beta" validate

Beim app_update kann es bei der Installation zu folgender Fehlermeldung kommen:

Error! App '90' state is 0x6 after update job.

Zur Lösung des Problems muss der Befehl:

app_update "90 -beta Beta" validate

so oft ausgeführt werden, bis der Vorgang schlussendlich erfolgreich beendet wird. Anschließend kann der Steam-Client mit dem Kommando exit beendet werden. Bevor man den Server startet, sollte man die server.cfg-Datei den Umständen entsprechend anpassen. Diese befindet sich im Ordner /home/counterstrike/game/cstrike/. Fertig konfiguriert könnte diese so aussehen:

// Use this file to configure your DEDICATED server. 
// This config file is executed on server start.

// server password
sv_password "geheim"
rcon_password "geheim"

// disable autoaim
sv_aim 0

// disable clients' ability to pause the server
pausable 0

// default server name. Change to "Bob's Server", etc.
hostname "Mein erster CS-Server"

// maximum client movement speed 
sv_maxspeed 320

// 20 minute timelimit
mp_timelimit 20

sv_cheats 0

// load ban files
// exec listip.cfg
// exec banned.cfg

Wenn man beim Start des Servers mittels:

./hlds_run -game cstrike +map de_dust2

folgende Ausgabe erhält:

dlopen failed trying to load:
/home/counterstrike/.steam/sdk32/steamclient.so
with error:
/home/counterstrike/.steam/sdk32/steamclient.so: cannot open shared object file: No such file or directory

muss ein symbolischer Link erstellt werden, welcher auf den linux32-Ordner der Steam-Installation zeigt:

cd
mkdir .steam
ln -s /home/counterstrike/steam/linux32 /home/counterstrike/.steam/sdk32

Anschließend kann der Server wieder gestartet werden. Alternativ kann der Server natürlich auch in einer screen-Umgebung gestartet werden, so das dieser im Hintergrund läuft.

Für macOS existiert seit vielen Jahren eine Erweiterung (der macOS Server), mit welchem dem Betriebssystem bestimmte Server-Funktionalitäten hinzugefügt werden können. Wenn der macOS Server später wieder deinstalliert werden soll, so ist dies in zwei einfachen Schritten möglich.

Die Konfigurationsoberfläche des macOS Server

Im ersten Schritt muss die Server-Applikation aus dem Programme-Ordner gelöscht werden. Anschließend muss der Ordner /Library/Server gelöscht werden. Damit ist der macOS Server deinstalliert.

Möchte man unter Linux auf dem Terminal einen Ordner mittels tar und gzip komprimieren, so ist dies mit zwei Befehlen erledigt:

tar cvwf data.tar data

Damit wird der Ordner data in eine Tar-Datei archiviert. Bei den Buchstaben nach dem Befehl handelt es sich um die gewünschten Optionen (create, verbose, interactive, file). Eine Tar-Datei ist nicht komprimiert, da das Tar-Format die Daten der Dateien einfach hintereinander in der Tar-Datei anordnet. Zur Kompression der Tar-Datei wird gzip genutzt:

gzip -9 data.tar

Damit wird die Datei mittels gzip gepackt und trägt anschließend den Namen data.tar.gz. Das -9 teilt gzip mit, das die höchste Kompressionsstufe genutzt werden soll.

In den letzten Tagen habe ich für ein Projekt einen REST-Server geschrieben. Der Server läuft unter .NET bzw. Mono – also war ich auf der Suche nach einer passenden Bibliothek bzw. einem Framework, welches mich bei dem Aufsetzen eines solchen Servers unterstützt. Nach einem Blick auf Nancy und einigen anderen Frameworks bin ich schlussendlich bei Grapevine gelandet.

sukona.github.io

sukona.github.io

Dabei handelt es sich um eine Bibliothek, welche neben einem REST-Client auch einen REST-Server bereitstellt. Das Hauptaugenmerk der Entwicklung wird dabei auf den REST-Server gelegt. Mit Hilfe des Frameworks lässt sich ein REST-Server mittels weniger Zeilen Quellcode aufsetzen:

ServerSettings settings = new ServerSettings();
settings.Host = "localhost";
settings.Port = "1111";

RestServer server = new RestServer(settings);
server.Start();

In diesem Beispiel werden die Einstellungen für den Server angelegt und anschließend dem Server übergeben. Danach wird der Server mit der Methode Start hochgefahren. Damit verfügt man zwar über einen REST-Server, dieser verfügt allerdings über keinerlei Methoden was die praktische Verwendung eher erschwert. Ressourcen für den Server werden mittels des Attributes RestResource markiert:

[RestResource(BasePath = "/time/")]
public class TimeModule
{
    [RestRoute(PathInfo = "date")]
    public IHttpContext GetDate(IHttpContext context)
    {
        context.Response.SendResponse(Grapevine.Util.HttpStatusCode.Accepted, getDate());
        return context;
    }
}

Über das Attribut RestRoute wird eine Methode für Grapevine gekennzeichnet – das Pathinfo definiert dabei den Pfad über welchen diese aufgerufen werden kann. Durch den über das Attribut RestResource festgelegten BasePath lautet die vollständige URL für die Ressource:

http://localhost:1111/time/date

Wird diese Methode per GET aufgerufen, so wird das aktuelle Datum zurückgegeben. Damit ist ein minimaler REST-Server mit einer Ressource implementiert. Grapevine selbst ist unter der Apache Lizenz lizenziert und damit freie Software. Der Quelltext der Bibliothek befindet sich auf GitHub.

Den freien Suchserver Elasticsearch kann man, wie das Wort Suchserver es dezent andeutet, als Server betreiben. Allerdings ist es manchmal nicht gewünscht einen dedizierter Server zu betreiben. In einem solchen Fall kann man den Elasticsearch-Server in eine Java-Applikation einbetten. Der sicherlich häufigste Fall für eine solche Einbettung ist dabei die Nutzung zu Testzwecken (z.B. Unit-Tests zum Test der Suchergebnisse). Im ersten Schritt sollte in das Java-Projekt die entsprechende Abhängigkeit zum Projekt hinzugefügt werden. In diesem Beispiel wird dabei auf einem auf Maven basierenden Projekt ausgegangen – in diesem muss die pom.xml entsprechend erweitert werden:

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>2.3.4</version>
</dependency>

Damit wurde Elasticsearch dem Projekt hinzugefügt. Nun muss der eigentliche Server im Java-Projekt gestartet werden. Dafür werden nur wenige Zeilen Quellcode benötigt:

Settings.Builder elasticsearchSettings = Settings.settingsBuilder()
    .put("http.enabled", "true")
    .put("path.data", "data")
    .put("path.home", "home");

Node node = nodeBuilder()
    .local(true)
    .settings(elasticsearchSettings.build())
    .node();

In diesem Beispiel werden im ersten Schritt die Einstellungen für Elasticsearch definiert. Dabei wird unter anderem der HTTP-Modus aktiviert. Wenn dieser deaktiviert ist, ist die Kommunikation per HTTP nicht mehr möglich. Stattdessen kann dann nur noch die Kommunikation über das Transport-Interface genutzt werden. Dieses Interface wird im Normalfall für die interne Kommunikationen zwischen einzelnen Elasticsearch-Clustern genutzt – allerdings ist eine Nutzung mit dem Elasticsearch-Java-Client ebenfalls möglich. Mit dem aktivierten Modus, ist die Entwicklung einfacher (z.B. für den Einsatz von Analyse-Tools) und die Konfiguration näher an der Praxis. Standardmäßig horcht der Elasticsearch-Server dabei auf dem Port 9200 – in diesem Beispiel wäre er über die URL:

http://localhost:9200

erreichbar. Nachdem die Einstellungen angelegt wurden, werden diese dem NodeBuilder übergeben, welcher schlussendlich den Elasticsearch-Server hochfährt. Nachdem dieser hochgefahren wurde, kann die Nutzung des selben beginnen.

Ein REST-API von Hand entwickelt, benötigt eine Dokumentation, ein entsprechenden Server und eventuell einige Clients als Referenz. Einfacher wird es mit einem Framework wie Swagger. Unter Zuhilfenahme der Beschreibungssprache YAML können mit Hilfe des Frameworks REST-APIs, Dokumentation, Server und Clients generiert werden.

Der Swagger Editor

Der Swagger Editor

Doch Swagger versteht sich nicht nur als Framework, sondern auch als Spezifikation. Begonnen wurde mit der Entwicklung bereits im 2010; die Swagger Specification trägt seit Anfang Januar 2012 offiziell den Namen OpenAPI Specification und beschreibt eine maschinenlesbare Interfacedefinitionen einer REST-API. Ähnliches wurde unter anderem schon mit WSDL und WADL versucht – alles Konzepte bzw. Beschreibungsprachen welche an ihren eigenen Limitationen gescheitert sind und wenn überhaupt nur noch sporadisch genutzt werden.

Betreut und weiterentwickelt wird die Spezifikation nun von der Open API Initiative, zu der namenhafte Firmen wie Google, PayPal, IBM, Atlassian und Microsoft gehören. Die Spezifikation als solche ist freie Software und auf GitHub zu finden. Sie ist unter der Apache Lizenz lizenziert. Aktuell ist die Spezifikation in der Version 2.0 veröffentlicht.

Auf der offiziellen Webseite von Swagger findet sich ein Editor, mit welchem APIs definiert werden können und anschließend exportiert werden können. Der Editor kann dabei Server unter anderem in den Sprachen bzw. für die Framworks Haskel, Jax-RS, Node.js, Python, Rails und PHP erzeugen. Bei den Clients ist die Auswahl noch größer. Diese können in C#, HTML, Dart, Go, Groovy, Java, Javascript, Objective C, Perl, PHP, Ruby, Scala, Swift und vielen weiteren Sprachen erzeugt werden.

Neben dem Editor kann für die Erzeugung von Clients auch der Swagger Codegen genutzt werden. Dabei handelt es sich um eine Java-Anwendung um die Clients lokal auf dem eigenen Rechner zu erzeugen. Der Editor und viele weitere Tools rund um Swagger sind ebenfalls auf GitHub zu finden. – auch diese sind freie Software, welche unter der Apache Lizenz stehen.

Unter Umständen kann es unter Ubuntu, oder anderen Distributionen basierend auf Debian passieren, das ein apt-get Vorgang fehlschlägt. Dies kann sich darin äußern das apt-get nicht mehr genutzt werden kann – stattdessen bekommt man folgende Meldung zu sehen:

E: Could not get lock /var/lib/dpkg/lock - open (11 Resource temporarily unavailable)
E: Unable to lock the administration directory (/var/lib/dpkg/) is another process using it?

Hintergrund ist das dpkg Sperrdateien mit dem Name lock anlegt und sie nach getaner Arbeit wieder entfernt. Bei plötzlichen Unterbrechungen wie z.B. einem Stromausfall kann es passieren das die Dateien nicht mehr entfernt werden. Lösen kann man das Problem indem man die entsprechenden Sperrdateien entfernt:

rm /var/lib/dpkg/lock
rm /var/lib/apt/lists/lock
rm /var/cache/apt/archives/lock

Abschließend sollte dpkg bzw. apt-get wieder ohne Probleme funktionieren.