Zoeken op website

Marcel - Een modernere shell voor Linux


Marcel is een nieuw schild. Het lijkt in veel opzichten op traditionele schelpen, maar doet een paar dingen anders:

  • Piping: Alle shells gebruiken pipelines om tekst van de uitvoer van het ene commando naar de invoer van een ander commando te sturen. Marcel gebruikt gestructureerde data in plaats van strings.
  • Python: Marcel is geïmplementeerd in Python en maakt Python op een aantal manieren toegankelijk. Als je een beetje logica in je commando's nodig hebt, kun je met Marcel dit in Python uitdrukken.
  • Scripting: Marcel hanteert een ongebruikelijke benadering van scripting. Je kunt natuurlijk eenvoudigweg een reeks Marcel-opdrachten in een tekstbestand schrijven en deze uitvoeren. Maar Marcel levert ook een API in de vorm van een Python-module. U kunt deze module importeren om Python-scripts op een veel gemakkelijkere manier uit te voeren dan mogelijk is met gewone Python.

Marcel beschikt over een licentie onder GPLv3.

Marcel Modern Shell installeren onder Linux

Marcel heeft Python 3.6 of hoger nodig. Het is ontwikkeld en getest op Linux, en werkt meestal op macOS. (Als u wilt helpen met de portering naar Windows, of de tekortkomingen van macOS wilt oplossen, kunt u contact met ons opnemen.)

Om Marcel voor eigen gebruik te installeren:

python3 -m pip install marcel

Of als u voor alle gebruikers wilt installeren (bijvoorbeeld naar /usr/local):

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

Nadat je marcel hebt geïnstalleerd, controleer je of het werkt door de opdracht marcel uit te voeren en vervolgens bij de marcel-prompt de versie uit te voeren commando:

marcel

Maatwerk van Marcel Shell

Je kunt Marcel aanpassen in het bestand ~/.marcel.py, dat wordt gelezen bij het opstarten (en opnieuw wordt gelezen bij wijziging). Zoals je aan de bestandsnaam kunt zien, wordt het aanpassen van Marcel gedaan in Python.

Eén ding dat u waarschijnlijk wilt doen, is de prompt aanpassen. Om dit te doen wijst u een lijst toe aan de PROMPT variabele. Als u bijvoorbeeld wilt dat uw prompt de huidige map is, afgedrukt in groen, gevolgd door > afgedrukt in blauw:

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

De resulterende prompt ziet er als volgt uit:

Dit vervangt de ondoorgrondelijke PS1-configuratie die je in bash zou moeten doen. Kleur(0, 4, 0) specificeert groen (de argumenten zijn RGB-waarden, in het bereik 0-5 sterk>). PWD is de omgevingsvariabele die uw huidige map vertegenwoordigt en als u deze variabele voorafgaat met lambda:, wordt een functie gegenereerd die wordt geëvalueerd telkens wanneer de prompt wordt weergegeven.

De ~/.marcel.py kan ook Python-modules importeren. Als u bijvoorbeeld de functies van de wiskundemodule wilt gebruiken in uw Marcel-opdrachten:

from math import *

Zodra u dit heeft gedaan, kunt u verwijzen naar symbolen uit die module, b.v. pi:

Merk op dat pi tussen haakjes staat. Over het algemeen gebruikt Marcel haakjes om Python-expressies af te bakenen. Dus (pi) evalueert de Python-expressie die de waarde van de variabele pi ophaalt. Op deze manier kunt u ook toegang krijgen tot traditionele omgevingsvariabelen, b.v. (USER) en (HOME), of een geldige Python-expressie die afhankelijk is van symbolen in de naamruimte van Marcel.

En u kunt uiteraard uw eigen symbolen definiëren. Als u bijvoorbeeld deze functiedefinitie in ~/.marcel.py plaatst:

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

dan kunt u de faculteitsfunctie op de opdrachtregel gebruiken, b.v.

Marcel Shell-voorbeelden

Hier zullen we enkele voorbeelden leren van opdrachten in de Marcel-shell.

Zoek bestandsgroottes op extensie

Verken de huidige map recursief, groepeer de bestanden op hun extensie (bijvoorbeeld .txt, .py enzovoort) en bereken de totale bestandsgrootte voor elke groep.

Dit doe je in Marcel als volgt:

De ls-operator produceert een stroom File-objecten (-fr betekent dat mappen recursief worden bezocht en alleen bestanden worden geretourneerd).

De File-objecten worden doorgestuurd naar de volgende opdracht, map. De kaart specificeert een Python-functie, tussen de buitenste haakjes, die elk bestand toewijst aan een tupel die de extensie van het bestand bevat, en de grootte ervan. (Marcel staat toe dat het trefwoord lambda wordt weggelaten.)

De operator rood (verminderen), groepeert op het eerste deel van het tupel (extensie) en somt vervolgens de grootten binnen elke groep op. Het resultaat wordt gesorteerd op extensie.

Host-uitvoerbare bestanden en de Marcel Pipeline

Pijplijnen kunnen een combinatie van Marcel-operators en uitvoerbare hostbestanden bevatten. Operators pijpen objecten, maar op de grenzen van operator/uitvoerbaar pijpt Marcel in plaats daarvan snaren.

Dit commando combineert bijvoorbeeld operators en uitvoerbare bestanden en vermeldt de gebruikersnamen van gebruikers wiens shell /bin/bash is.

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

cat is een uitvoerbaar Linux-bestand. Het leest /etc/passwd, en Marcel stuurt de inhoud stroomafwaarts naar de Marcel-operatorkaart.

Het argument tussen haakjes dat moet worden toegewezen, is een Python-functie die de regels opsplitst bij de :-scheidingstekens, wat 7-tupels oplevert. Een select is een Marcel-operator waarvan het argument een Python-functie is die de tupels identificeert waarin het laatste veld /bin/bash is.

De volgende operator, een andere kaart, bewaart het gebruikersnaamveld van elke invoertupel. Ten slotte combineert xargs echo de binnenkomende gebruikersnamen in één enkele regel, die naar stdout wordt afgedrukt.

Scripten in Marcel Shell

Hoewel Python soms wordt beschouwd als een scripttaal, werkt het eigenlijk niet goed voor dat doel. Het probleem is dat het uitvoeren van shell-opdrachten en andere uitvoerbare bestanden vanuit Python omslachtig is. Je kunt os.system() gebruiken, wat eenvoudig is maar vaak niet geschikt voor het omgaan met stdin, stdout en stderr. subprocess.Popen() is krachtiger maar complexer in gebruik.

De aanpak van Marcel is om een module te bieden die Marcel-operators integreert met de taalfuncties van Python. Om een eerder voorbeeld opnieuw te bekijken: hier is de Python-code voor het berekenen van de som van de bestandsgroottes per extensie:

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})

De shell-opdrachten zijn hetzelfde als voorheen, behalve syntactische conventies. Dus ls -fr verandert in ls(file=True, recursive=True). De kaart en rode operatoren zijn er ook, verbonden met pijpen, zoals in de shell-versie. Het volledige shell-commando (ls … red) levert een Python-iterator op, zodat het commando met Python's voor een lus kan worden gebruikt.

Databasetoegang met Marcel Shell

U kunt databasetoegang integreren met Marcel-pijplijnen. Eerst moet u de databasetoegang configureren in het configuratiebestand, ~/.marcel.py, b.v.

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

DB_DEFAULT = 'jao'

Dit configureert de toegang tot een Postgres database met de naam acme, met behulp van het psycopg2 stuurprogramma. Verbindingen vanuit Marcel worden gemaakt met behulp van de jao-gebruiker, en het databaseprofiel heet jao. (DB_DEFAULT specificeert het databaseprofiel jao als het profiel dat moet worden gebruikt als er geen profiel is opgegeven.) Als deze configuratie is voltooid, kan de database nu worden opgevraagd met behulp van de sql-operator, b.v.

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

Met deze opdracht wordt een query uitgevoerd op een tabel met de naam part, en wordt het queryresultaat in het bestand ~/reorder.csv gedumpt, in CSV-indeling.

Toegang op afstand met Marcel Shell

Net als databasetoegang kan externe toegang worden geconfigureerd in ~/.marcel.py. Hiermee configureert u bijvoorbeeld een cluster met 4 knooppunten:

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'])

Het cluster kan worden geïdentificeerd als een lab in Marcel-opdrachten. De gebruikers- en identiteitsparameters specificeren aanmeldingsgegevens, en de parameter host specificeert de IP-adressen van de knooppunten in het cluster.

Zodra het cluster is geconfigureerd, kunnen alle knooppunten tegelijk worden bediend. Om bijvoorbeeld een lijst met proces-pids en opdrachtregels voor het hele cluster te krijgen:

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

Dit retourneert een stroom van (IP-adres, PID, opdrachtregel) tupels.

Voor meer informatie bezoek:

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

Marcel is vrij nieuw en wordt actief ontwikkeld. Neem contact op als je wilt helpen.