Konsolenspiele: Shell-Skripte in Node.js schreiben

Vorhandenes Wissen auf neue Szenarien anwenden zu können, vereinfacht die Entwicklung. Warum also nicht auch Shell-Skripte in JavaScript schreiben? Node.js macht's möglich.

vorlesen Druckansicht
Lesezeit: 4 Min.
Von
  • Golo Roden
Inhaltsverzeichnis

In der Regel wird Node.js für die Entwicklung von Webanwendungen verwendet. Es daher als Webserver zu bezeichnen, wäre jedoch falsch: Node.js beherrscht nämlich weitaus mehr als nur die Verarbeitung des HTTP-Protokolls.

Unter anderem eignet es sich auch hervorragend, um Shell-Skripte zu entwickeln. Dazu sind prinzipiell keine besonderen MaĂźnahmen erforderlich, denn die Entwicklung der eigentlichen Logik erfolgt auf die gleiche Art wie bei einem klassischen Modul.

Der wesentliche Unterschied besteht in der zusätzlichen Möglichkeit, ein Shell-Skript direkt auf der Konsole aufrufen zu können, ohne Node.js von Hand angeben zu müssen. Dazu sind lediglich zwei einfache Schritte erforderlich.

Zum einen muss man die Anwendung derart konfigurieren, dass sie fĂĽr ihre AusfĂĽhrung Node.js als Umgebung erfordert. Dazu fĂĽgt man der Datei app.js als erste Zeile die Anweisung

#!/usr/bin/env node

hinzu. Weist man anschlieĂźend der Datei app.js mit Hilfe des Kommandos

$ chmod a+x app.js

die erforderlichen AusfĂĽhrungsrechte zu, kann man diese direkt von der Konsole aufrufen, ohne Node.js explizit angeben zu mĂĽssen:

$ ./app.js

Zum anderen empfiehlt es sich, die Eigenschaft bin in die Datei package.json aufzunehmen, und ihr den Namen der ausfĂĽhrbaren Datei zuzuweisen:

{
"name": "...",
"version": "...",
"main": "app.js",
"bin": "app.js",
"dependencies": {
// ...
}
}

Diese Eigenschaft bewirkt, dass npm bei einer globalen Installation des Moduls einen ausfĂĽhrbaren Verweis mit dem Namen des Moduls in dem Verzeichnis /usr/local/bin generiert, sodass das Modul anschlieĂźend systemweit unter seinem Namen als ausfĂĽhrbare Anwendung zur VerfĂĽgung steht.

Auf dieser Basis ist es nun ein Leichtes, eigene Shell-Skripte zu entwickeln. Als Beispiel soll ein Werkzeug dienen, das die package.json-Dateien aller direkten Unterverzeichnisse ausliest, sie nach einem als Parameter ĂĽbergebenen Modul durchsucht und schlieĂźlich dessen verwendete Version zurĂĽckgibt.

Die Anwendung beginnt mit der Deklaration einiger Variablen und dem Auslesen des als Parameter ĂĽbergebenen zu suchenden Moduls:

#!/usr/bin/env node

'use strict';

var fs = require('fs'),
path = require('path');

var _ = require('underscore');

var dependency = process.argv[2];

AnschlieĂźend ermittelt die Anwendung alle Unterverzeichnisse des derzeitigen Verzeichnisses, wobei vom aktuellen Arbeitsverzeichnis als Basis ausgegangen wird:

fs.readdir(process.cwd(), function (err, directories) {
_.each(directories, function (directory) {
fs.stat(directory, function (err, stats) {
if (!stats.isDirectory()) {
return;
}

// ...
});
});
});

Danach prüft die Anwendung, ob das jeweilige Verzeichnis eine Datei namens package.json enthält. Falls nicht, wird mit dem nächsten Verzeichnis fortgefahren:

var packageJson =
path.join(process.cwd(), directory, 'package.json');

fs.exists(packageJson, function (exists) {
if (!exists) {
return;
}

// ...
});

Ist die Datei package.json hingegen vorhanden, wird sie mit Hilfe der require-Funktion geladen und anschlieĂźend analysiert. Die Anwendung sucht nach dem angegebenen Modul in den Abschnitten dependencies und devDependencies, und gibt im Erfolgsfall die gefundene Versionsnummer aus:

var configuration = require(packageJson);
if ((configuration.dependencies &&
configuration.dependencies[dependency]) ||
(configuration.devDependencies &&
configuration.devDependencies[dependency])) {
var version =
configuration.dependencies[dependency] ||
configuration.devDependencies[dependency];

console.log(directory + ' (' + version + ')');
}

Zuletzt muss man der Datei package.json dieser Anwendung noch einen passenden Namen und die bin-Eigenschaft hinzufĂĽgen:

{
"name": "dep",
"version": "0.0.1",
"main": "app.js",
"bin": "app.js",
"dependencies": {
// ...
}
}

Danach kann man sie mit Hilfe von npm global installieren. AnschlieĂźend steht sie unter ihrem Namen dep systemweit zur VerfĂĽgung:

$ dep underscore
bar (1.3.2)
foo (1.4.4)

tl;dr: Node.js ermöglicht die einfache Entwicklung von Shell-Skripten auf Basis von JavaScript. Besonders hilfreich ist hierbei die Möglichkeit, Node.js als Ausführungsumgebung direkt in der Datei app.js hinterlegen und das Modul über eine spezielle Eigenschaft der Datei package.json global installieren zu können. ()