Website-Suche

Marcel – Eine modernere Shell für Linux


Marcel ist eine neue Hülle. Sie ähnelt in vielerlei Hinsicht herkömmlichen Shells, macht aber ein paar Dinge anders:

  • Piping: Alle Shells verwenden Pipes, um einen Text von der Ausgabe eines Befehls an die Eingabe eines anderen zu senden. Marcel leitet strukturierte Daten anstelle von Zeichenfolgen weiter.
  • Python: Marcel ist in Python implementiert und macht Python auf verschiedene Weise verfügbar. Wenn Sie in Ihren Befehlen ein wenig Logik benötigen, können Sie diese mit Marcel in Python ausdrücken.
  • Scripting: Marcel verfolgt einen ungewöhnlichen Ansatz beim Scripting. Sie können natürlich auch einfach eine Folge von Marcel-Befehlen in eine Textdatei schreiben und diese ausführen. Marcel stellt aber auch eine API in Form eines Python-Moduls zur Verfügung. Sie können dieses Modul importieren, um Python-Skripte auf weitaus bequemere Weise auszuführen, als dies mit einfachem Python möglich ist.

Marcel ist unter GPLv3 lizenziert.

Marcel Modern Shell unter Linux installieren

Marcel benötigt Python 3.6 oder höher. Es wurde unter Linux entwickelt und getestet und funktioniert hauptsächlich unter macOS. (Wenn Sie bei der Portierung auf Windows helfen oder die macOS-Mängel beheben möchten, nehmen Sie Kontakt mit uns auf.)

So installieren Sie marcel für Ihren eigenen Gebrauch:

python3 -m pip install marcel

Oder wenn Sie für alle Benutzer installieren möchten (z. B. nach /usr/local):

sudo python3 -m pip install --prefix /usr/local marcel

Nachdem Sie marcel installiert haben, überprüfen Sie, ob es funktioniert, indem Sie den Befehl marcel ausführen und dann an der marcel-Eingabeaufforderung die Version ausführen Befehl:

marcel

Anpassung von Marcel Shell

Sie können marcel in der Datei ~/.marcel.py anpassen, die beim Start gelesen wird (und bei Änderung erneut gelesen wird). Wie Sie am Namen der Datei erkennen können, erfolgt die Anpassung von Marcel in Python.

Eine Sache, die Sie wahrscheinlich tun möchten, ist, die Eingabeaufforderung anzupassen. Dazu weisen Sie der Variablen PROMPT eine Liste zu. Wenn Ihre Eingabeaufforderung beispielsweise das aktuelle Verzeichnis in Grün sein soll, gefolgt von > in Blau:

PROMPT = [
    Color(0, 4, 0),
    lambda: PWD,
    Color(0, 2, 5),
    '> '
]

Die resultierende Eingabeaufforderung sieht folgendermaßen aus:

Dies ersetzt die undurchschaubare PS1-Konfiguration, die Sie in Bash vornehmen müssten. Color(0, 4, 0) gibt Grün an (die Argumente sind RGB-Werte im Bereich 0-5). PWD ist die Umgebungsvariable, die Ihr aktuelles Verzeichnis darstellt. Wenn Sie dieser Variablen das Präfix lambda: voranstellen, wird eine Funktion generiert, die jedes Mal ausgewertet wird, wenn die Eingabeaufforderung angezeigt wird.

Der ~/.marcel.py kann auch Python-Module importieren. Wenn Sie beispielsweise die Funktionen des Mathematikmoduls in Ihren Marcel-Befehlen verwenden möchten:

from math import *

Sobald Sie dies getan haben, können Sie auf Symbole aus diesem Modul verweisen, z. B. pi:

Beachten Sie, dass pi in Klammern steht. Im Allgemeinen verwendet marcel Klammern, um Python-Ausdrücke zu begrenzen. (pi) wertet also den Python-Ausdruck aus, der den Wert der Variablen pi abruft. Sie können auf diese Weise auch auf herkömmliche Umgebungsvariablen zugreifen, z. (USER) und (HOME) oder jeder gültige Python-Ausdruck, der auf Symbolen in Marcels Namespace basiert.

Und natürlich können Sie auch eigene Symbole definieren. Wenn Sie diese Funktionsdefinition beispielsweise in ~/.marcel.py einfügen:

def factorial(n):
    f = 1
    for i in range(1, n + 1):
        f *= i
    return f

Dann können Sie die Fakultätsfunktion in der Befehlszeile verwenden, z. B.

Beispiele von Marcel Shell

Hier lernen wir einige Beispiele für Befehle in der Marcel-Shell kennen.

Finden Sie Dateigrößen nach Erweiterung

Durchsuchen Sie das aktuelle Verzeichnis rekursiv, gruppieren Sie die Dateien nach ihrer Erweiterung (z. B. .txt, .py usw.) und berechnen Sie die Gesamtdateigröße für jede Gruppe.

Sie können dies in Marcel wie folgt tun:

Der ls-Operator erzeugt einen Stream von Dateiobjekten (-fr bedeutet, Verzeichnisse rekursiv aufzurufen und nur Dateien zurückzugeben).

Die File-Objekte werden an den nächsten Befehl, „map“, weitergeleitet. Die map gibt in den äußersten Klammern eine Python-Funktion an, die jede Datei einem Tupel zuordnet, das die Dateierweiterung und ihre Größe enthält. (Marcel lässt zu, dass das Schlüsselwort lambda weggelassen wird.)

Der Operator red (reduce) gruppiert nach dem ersten Teil des Tupels (extension) und summiert dann die Größen innerhalb jeder Gruppe. Das Ergebnis wird nach Erweiterung sortiert.

Ausführbare Hostdateien und die Marcel-Pipeline

Pipelines können eine Mischung aus Marcel-Operatoren und ausführbaren Hostdateien enthalten. Operatoren leiten Objekte weiter, aber an den Grenzen zwischen Operator und ausführbarer Datei leitet Marcel stattdessen Zeichenfolgen weiter.

Dieser Befehl kombiniert beispielsweise Operatoren und ausführbare Dateien und listet die Benutzernamen von Benutzern auf, deren Shell /bin/bash ist.

cat /etc/passwd \
| map (line: line.split(':')) \
| select (*line: line[-1] == '/bin/bash') \
| map (*line: line[0]) \
| xargs echo

cat ist eine ausführbare Linux-Datei. Es liest /etc/passwd und Marcel leitet seinen Inhalt an die Marcel-Operator-Map weiter.

Das in Klammern gesetzte Argument für die Zuordnung ist eine Python-Funktion, die die Zeilen an den Trennzeichen : teilt und so 7 Tupel ergibt. Ein select ist ein Marcel-Operator, dessen Argument eine Python-Funktion ist, die jene Tupel identifiziert, in denen das letzte Feld /bin/bash ist.

Der nächste Operator, eine andere Karte, behält das Benutzernamenfeld jedes Eingabetupels. Schließlich kombiniert xargs echo die eingehenden Benutzernamen in einer einzigen Zeile, die auf stdout ausgegeben wird.

Skripterstellung in Marcel Shell

Obwohl Python manchmal als Skriptsprache angesehen wird, eignet es sich für diesen Zweck eigentlich nicht gut. Das Problem besteht darin, dass das Ausführen von Shell-Befehlen und anderen ausführbaren Dateien aus Python umständlich ist. Sie können os.system() verwenden, was einfach ist, aber oft nicht für den Umgang mit stdin, stdout und stderr geeignet ist. subprocess.Popen() ist leistungsfähiger, aber komplexer in der Verwendung.

Marcels Ansatz besteht darin, ein Modul bereitzustellen, das Marcel-Operatoren mit den Sprachfunktionen von Python integriert. Um ein früheres Beispiel noch einmal aufzugreifen, finden Sie hier den Python-Code zur Berechnung der Summe der Dateigrößen nach Erweiterung:

from marcel.api import *

for ext, size in (ls(file=True, recursive=True)
                  | map(lambda f: (f.suffix, f.size))
                  | red('.', '+')):
    print(f'{ext}: {size})

Die Shell-Befehle sind bis auf syntaktische Konventionen dieselben wie zuvor. Also wird ls -fr zu ls(file=True, recursive=True). Die Map- und Red-Operatoren sind ebenfalls vorhanden und wie in der Shell-Version mit Pipes verbunden. Der gesamte Shell-Befehl (ls … red) liefert einen Python-Iterator, sodass der Befehl mit Pythons for-Schleife verwendet werden kann.

Datenbankzugriff mit Marcel Shell

Sie können den Datenbankzugriff mit Marcel-Pipelines integrieren. Zuerst müssen Sie den Datenbankzugriff in der Konfigurationsdatei ~/.marcel.py konfigurieren, z. B.

define_db(name='jao',
          driver='psycopg2',
          dbname='acme',
          user='jao')

DB_DEFAULT = 'jao'

Dadurch wird der Zugriff auf eine Postgres-Datenbank namens acme unter Verwendung des psycopg2-Treibers konfiguriert. Verbindungen von Marcel werden über den Benutzer jao hergestellt und das Datenbankprofil heißt jao. (DB_DEFAULT gibt das jao-Datenbankprofil als das zu verwendende Profil an, wenn kein Profil angegeben ist.) Nachdem diese Konfiguration abgeschlossen ist, kann die Datenbank nun mit dem SQL-Operator abgefragt werden, z. B.

sql 'select part_name, quantity from part where quantity < 10' \
| out --csv –-file ~/reorder.csv

Dieser Befehl fragt eine Tabelle mit dem Namen part ab und speichert das Abfrageergebnis im CSV-Format in der Datei ~/reorder.csv.

Fernzugriff mit Marcel Shell

Ähnlich wie der Datenbankzugriff kann der Fernzugriff in ~/.marcel.py konfiguriert werden. Dies konfiguriert beispielsweise einen 4-Knoten-Cluster:

define_remote(name='lab',
              user='frankenstein',
              identity='/home/frankenstein/.ssh/id_rsa',
              host=['10.0.0.100', 
                    '10.0.0.101',
                    '10.0.0.102',
                    '10.0.0.103'])

Der Cluster kann in Marcel-Befehlen als ein Labor identifiziert werden. Die Benutzer- und Identitätsparameter geben Anmeldeinformationen an und der host-Parameter gibt die IP-Adressen der Knoten im Cluster an.

Sobald der Cluster konfiguriert ist, können alle Knoten gleichzeitig betrieben werden. So erhalten Sie beispielsweise eine Liste der Prozess-PIDs und Befehlszeilen im gesamten Cluster:

@lab [ps | map (proc: (proc.pid, proc.commandline))]

Dies gibt einen Stream von (IP-Adresse, PID, Befehlszeilen-)Tupeln zurück.

Für weitere Informationen besuchen Sie:

  • https://www.marceltheshell.org/
  • https://github.com/geophile/marcel

Marcel ist ziemlich neu und befindet sich in aktiver Entwicklung. Kontaktieren Sie uns, wenn Sie helfen möchten.