Marcel - Un Shell més modern per a Linux


Marcel és una nova carcassa. És similar a les petxines tradicionals de moltes maneres, però fa algunes coses de manera diferent:

  • Piping: tots els shells utilitzen canalitzacions per enviar un text des de la sortida d'una ordre a l'entrada d'una altra. Marcel canalitza dades estructurades en lloc de cadenes.
  • Python: Marcel s'implementa a Python i exposa Python de diverses maneres. Si necessiteu una mica de lògica a les vostres ordres, Marcel us permet expressar-ho en Python.
  • Guions: en Marcel adopta un enfocament inusual de la creació de guions. Per descomptat, podeu escriure una seqüència d'ordres de Marcel en un fitxer de text i executar-les. Però Marcel també proporciona una API en forma de mòdul Python. Podeu importar aquest mòdul per fer scripts Python d'una manera molt més còmoda que no és possible amb Python normal.

Marcel té una llicència GPLv3.

Instal·lació de Marcel Modern Shell a Linux

Marcel requereix Python 3.6 o posterior. S'ha desenvolupat i provat a Linux i funciona principalment amb macOS. (Si voleu ajudar a portar a Windows o corregir les deficiències de macOS, poseu-vos en contacte.)

Per instal·lar Marcel per al vostre propi ús:

# python3 -m pip install marcel

O si voleu instal·lar-lo per a tots els usuaris (p. ex., a /usr/local):

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

Un cop hàgiu instal·lat marcel, comproveu que funciona executant l'ordre marcel i, a continuació, a l'indicador de marcel, executeu l'ordre version:

$ marcel

Personalització de Marcel Shell

Podeu personalitzar en Marcel al fitxer ~/.marcel.py, que es llegeix a l'inici (i es rellegeix quan es modifica). Com es pot veure pel nom del fitxer, la personalització de Marcel es fa a Python.

Una cosa que probablement vulgueu fer és personalitzar el missatge. Per fer-ho, assigneu una llista a la variable PROMPT. Per exemple, si voleu que la vostra sol·licitud sigui el directori actual, imprès en verd, seguit de > imprès en blau:

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

El missatge resultant té aquest aspecte:

Això substitueix la configuració inescrutable de PS1 que hauríeu de fer a bash. Color(0, 4, 0) especifica el verd (els arguments són valors RGB, en el rang 0-5). PWD és la variable d'entorn que representa el vostre directori actual i posant el prefix d'aquesta variable amb lambda: genera una funció, avaluada cada vegada que es mostra l'indicador.

El ~/.marcel.py també pot importar mòduls de Python. Per exemple, si voleu utilitzar les funcions del mòdul de matemàtiques a les vostres ordres de Marcel:

from math import *

Un cop hàgiu fet això, podeu fer referència als símbols d'aquest mòdul, p. pi:

Tingueu en compte que pi està entre parèntesis. En general, marcel utilitza parèntesis per delimitar expressions de Python. Així, (pi) avalua l'expressió Python que recupera el valor de la variable pi. També podeu accedir a les variables d'entorn tradicionals d'aquesta manera, p. (USUARI) i (INICIA), o qualsevol expressió de Python vàlida que es basi en símbols de l'espai de noms de Marcel.

I, per descomptat, podeu definir els vostres propis símbols. Per exemple, si poseu aquesta definició de funció a ~/.marcel.py:

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

llavors podeu utilitzar la funció factorial a la línia d'ordres, p.

Exemples de Marcel Shell

Aquí, aprendrem alguns exemples d'ordres a l'intèrpret d'ordres de marcel.

Exploreu el directori actual de manera recursiva, agrupeu els fitxers per la seva extensió (per exemple, .txt, .py, etc.) i calculeu la mida total del fitxer per a cada grup.

Podeu fer-ho a Marcel de la següent manera:

L'operador ls produeix un flux d'objectes File, (-fr significa visitar directoris de manera recursiva i retornar només fitxers).

Els objectes File es canalitzen a la següent comanda, map. El mapa especifica una funció Python, entre els parèntesis més externs, que assigna cada fitxer a una tupla que conté l'extensió del fitxer i la seva mida. (Marcel permet ometre la paraula clau lambda.)

L'operador vermell (reduir), agrupa per la primera part de la tupla (extensió) i després suma les mides dins de cada grup. El resultat s'ordena per extensió.

Els pipelines poden contenir una barreja d'operadors Marcel i executables d'amfitrió. Els operadors canalitzen objectes, però als límits de l'operador/executable, Marcel canalitza les cadenes.

Per exemple, aquesta ordre combina operadors i executables i enumera els noms d'usuari dels usuaris el shell dels quals és /bin/bash.

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

cat és un executable de Linux. Llegeix /etc/passwd i en Marcel canalitza el seu contingut aigües avall al mapa de l'operador de Marcel.

L'argument entre parèntesis per mapejar és una funció de Python que divideix les línies als separadors :, donant 7 tuples. Un select és un operador marcel l'argument del qual és una funció de Python que identifica aquelles tuples en què l'últim camp és /bin/bash.

El següent operador, un altre mapa manté el camp de nom d'usuari de cada tupla d'entrada. Finalment, xargs echo combina els noms d'usuari entrants en una sola línia, que s'imprimeix a stdout.

Guió en Marcel Shell

Tot i que de vegades es considera que Python és un llenguatge de script, en realitat no funciona bé per a aquest propòsit. El problema és que executar ordres de shell i altres executables de Python és complicat. Podeu utilitzar os.system(), que és senzill però sovint inadequat per tractar amb stdin, stdout i stderr. subprocess.Popen() és més potent però més complex d'utilitzar.

L'enfocament de Marcel és proporcionar un mòdul que integri els operadors de Marcel amb les característiques del llenguatge de Python. Per revisar un exemple anterior, aquí teniu el codi de Python per calcular la suma de les mides dels fitxers per extensió:

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

Les ordres de l'intèrpret d'ordres són les mateixes que abans, excepte per les convencions sintàctiques. Així, ls -fr es converteix en ls(file=True, recursive=True). El mapa i els operadors vermells també hi són, connectats amb canonades, com en la versió shell. Tota l'ordre de l'intèrpret d'ordres (ls ... vermell) produeix un iterador de Python perquè l'ordre es pugui utilitzar amb Python per a un bucle.

Accés a la base de dades amb Marcel Shell

Podeu integrar l'accés a la base de dades amb marcel pipelines. Primer, heu de configurar l'accés a la base de dades al fitxer de configuració, ~/.marcel.py, p.

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

DB_DEFAULT = 'jao'

Això configura l'accés a una base de dades Postgres anomenada acme, mitjançant el controlador psycopg2. Les connexions de marcel es faran mitjançant l'usuari jao i el perfil de la base de dades s'anomena jao. (DB_DEFAULT especifica el perfil de la base de dades jao com el que s'utilitzarà si no s'especifica cap perfil.) Amb aquesta configuració feta, ara es pot consultar la base de dades mitjançant l'operador sql, p.

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

Aquesta ordre consulta una taula anomenada part i aboca el resultat de la consulta al fitxer ~/reorder.csv, en format CSV.

Accés remot amb Marcel Shell

De manera similar a l'accés a la base de dades, l'accés remot es pot configurar a ~/.marcel.py. Per exemple, això configura un clúster de 4 nodes:

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

El clúster es pot identificar com un laboratori a les ordres de Marcel. Els paràmetres d'usuari i d'identitat especifiquen la informació d'inici de sessió i el paràmetre d'amfitrió especifica les adreces IP dels nodes del clúster.

Un cop configurat el clúster, es poden operar tots els nodes alhora. Per exemple, per obtenir una llista de dades de procés i línies d'ordres al clúster:

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

Això retorna un flux de tuples (adreça IP, PID, línia d'ordres).

Per a més informació visiteu:

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

Marcel és bastant nou i en desenvolupament actiu. Posa't en contacte si vols ajudar.