Ich wollte mich schon länger mal mit node.js beschäftigen und einen einfachen Webdienst damit bauen. Es gibt im uberspace wiki einen kurzen Artikel zu nodejs und auch alle weiteren benötigten Informationen findet man dort irgendwo. Aber man muss sich doch alles zusammen suchen. Deswegen hiermal alle Punkte zusammengefasst, die man beachten muss, um einen einfachen Prototyp bei den ubernauten zu betreiben.
node.js Version
Mit dem Befehl
$ node -v
v0.10.41
kann man sich die aktuell verwendete nodejs Version anzeigen lassen. Diese ist im Normalfall sehr alt. Um beim Aufruf von node eine aktuelle Version zu verwenden, ändern wir den Pfad. Alle verfügbaren installierten Versionen kann man sich anzeigen lassen:
$ ls -ld /package/host/localhost/nodejs-*
In der ~/.bash_profile fügt man in der letzten Zeile die gewünschte Version ein. z.B. 6
$ export PATH=/package/host/localhost/nodejs-6/bin:$PATH
Umgebungsvariable mit source ~/.bash_profile neuladen. Anschließend sollte die korrekte Version benutzt werden.
$ node -v
v6.9.1
Einfacher node.js webserver
Da wir nicht die einzigen auf dem uberspace host sind und die gängigen Ports 80 und 443 bereits vom Apachen verwendet werden, müssen wir unseren node.js server auf einem anderen Port starten und leiten dann die Anfragen an Port 80 an diesen um. Der Port sollte zwischen 61000 und 65535 liegen. Wir suchen uns einen aus (hier 61003) und überprüfen, ob dieser schon belegt ist:
$ /usr/sbin/ss -ln | fgrep 61003
Bekommen wir keinen Eintrag angezeigt, können wir diesen Port verwenden. Die Weiterleitung richten wir mit einer .htaccess Datei in ~/html/ ein:
RewriteEngine On
RewriteRule ^(.*) http://localhost:61003/$1 [P]
Jetzt können wir loslegen. Wir wechseln in unseren DocumentRoot und installieren das node express.js modul für einen Webserver.
$ cd ~/html
$ npm install express
Als nächstes erstellen wir die Datei index.js mit folgenden Inhalt (den Port entsprechend anpassen):
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 61003));
app.get('/', function (req, res) {
res.send('Hello World!')
})
var server = app.listen(app.get('port'), function () {
console.log('Started on port %s', app.get('port'));
});
Der Webserver kann nun testweise mit
node index.js
gestartet werden und ein Aufruf der eigenen uberspace url im Browser sollte ein „Hello World!“ anzeigen. Schon fertig!
Naja, fast. Wir möchten ja, dass der Dienst zukünftig auch läuft, wenn wir nicht angemeldet sind. Also müssen wir unseren Server nun als Dienst einrichten.
Als Dienst einrichten
Dem uberspace wiki folgend erstellen wir als nächstes einen Dienst. Dafür zuerst den supervisor aktivieren und anschließend den Dienst hinzufügen. Hier heißt dieser einfach nodetest.
$ test -d ~/service || uberspace-setup-svscan
$ uberspace-setup-service nodetest node ~/html/index.js
Dem tool uberspace-setup-service übergibt man als 1. Parameter den Name des neuen Dienstes (nodetest) und als 2. Parameter das Kommando (node ~/html/index.js). Das Ergebnis schauen wir uns gleich an. Solltet ihr das ganze testen wollen oder geht irgendetwas schief, könnt ihr so den Dienst wieder löschen:
$ cd ~/service/nodetest
$ rm ~/service/nodetest
$ svc -dx . log
$ rm -rf ~/etc/run-nodetest
Für jeden Dienst wird in ~/service ein eigener Unterordner erzeugt. Hier liegt die run Datei, welche den eigentlich Aufruf beinhaltet und die Logdateien. Seit ihr dem Artikel genau gefolgt, sollte die letzte Zeile mit dem Aufruf der ~/service/nodetest/run so aussehen:
exec /package/host/localhost/nodejs-6/bin/node /home/user/html/index.js 2>&1
Das node als 2. Parameter wurde durch den gesammten Pfad ersetzt. Möchte man das nicht und will lieber immer die eingestellte Version verwenden, den Pfad entfernen und nur node verwenden.
Gesteuert wird der Dienst mit dem tool svc. Die wichtigsten Parameter:
-u |
up, also Dienst starten |
-d |
down, also Dienst beenden |
-h |
hup, ein HUP-Signal senden (Reload) |
Ein Neustart des Dienstes sähe z.B. so aus:
$ svc -du ~/service/nodetest
Logging
Das entsprechende Log des Dienstes können wir recht einfach lesen. Mit dieser kleinen Funktion in der ~/.bashrc wird es aber noch einfacher:
readlog()
{
if [ -n "$1" ]; then
zcat -f ~/service/$1/log/main/* | tai64nlocal | less;
else
echo "Usage: readlog <daemonname>";
fi;
}
Der Aufruf geschieht dann mit:
$ readlog nodetest