Ricerca nel sito web

Marcel - Una shell più moderna per Linux


Marcel è una nuova shell. È simile alle shell tradizionali in molti modi, ma fa alcune cose in modo diverso:

  • Piping: tutte le shell utilizzano pipe per inviare un testo dall'output di un comando all'input di un altro. Marcel trasmette dati strutturati anziché stringhe.
  • Python: Marcel è implementato in Python ed espone Python in diversi modi. Se hai bisogno di un po' di logica nei tuoi comandi, Marcel ti permette di esprimerla in Python.
  • Scripting: Marcel adotta un approccio insolito allo scripting. Ovviamente puoi semplicemente scrivere una sequenza di comandi Marcel in un file di testo ed eseguirli. Ma Marcel fornisce anche un'API sotto forma di modulo Python. Puoi importare questo modulo per eseguire script Python in un modo molto più conveniente di quanto sia possibile con il semplice Python.

Marcel è concesso in licenza GPLv3.

Installazione di Marcel Modern Shell in Linux

Marcel richiede Python 3.6 o versione successiva. È stato sviluppato e testato su Linux e funziona principalmente su macOS. (Se desideri aiutare il porting su Windows o correggere le carenze di macOS, contattaci.)

Per installare marcel per uso personale:

python3 -m pip install marcel

Oppure se desideri eseguire l'installazione per tutti gli utenti (ad esempio, su /usr/local):

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

Una volta installato marcel, verifica che funzioni eseguendo il comando marcel, quindi al prompt di marcel esegui la versione comando:

marcel

Personalizzazione di Marcel Shell

Puoi personalizzare marcel nel file ~/.marcel.py, che viene letto all'avvio (e riletto quando modificato). Come puoi capire dal nome del file, la personalizzazione di Marcel viene eseguita in Python.

Una cosa che probabilmente vorrai fare è personalizzare il prompt. Per fare ciò, assegna un elenco alla variabile PROMPT. Ad esempio, se vuoi che il tuo prompt sia la directory corrente, stampata in verde, seguita da > stampato in blu:

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

Il prompt risultante è simile al seguente:

Questo sostituisce l'imperscrutabile configurazione PS1 che dovresti fare in bash. Colore(0, 4, 0) specifica verde, (gli argomenti sono valori RGB, nell'intervallo 0-5). PWD è la variabile di ambiente che rappresenta la directory corrente e anteponendo questa variabile a lambda: genera una funzione, valutata ogni volta che viene visualizzato il prompt.

~/.marcel.py può anche importare moduli Python. Ad esempio, se vuoi utilizzare le funzioni del modulo matematico nei tuoi comandi Marcel:

from math import *

Dopo averlo fatto, puoi fare riferimento ai simboli di quel modulo, ad es. pi:

Tieni presente che pi è racchiuso tra parentesi. In generale, marcel usa le parentesi per delimitare le espressioni Python. Quindi (pi) valuta l'espressione Python che recupera il valore della variabile pi. Puoi anche accedere alle variabili di ambiente tradizionali in questo modo, ad es. (USER) e (HOME) o qualsiasi espressione Python valida che si basa sui simboli nello spazio dei nomi di Marcel.

E puoi, ovviamente, definire i tuoi simboli. Ad esempio, se inserisci questa definizione di funzione in ~/.marcel.py:

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

quindi puoi utilizzare la funzione fattoriale sulla riga di comando, ad es.

Esempi di Marcel Shell

Qui impareremo alcuni esempi di comandi nella shell Marcel.

Trova le dimensioni dei file per estensione

Esplora la directory corrente in modo ricorsivo, raggruppa i file in base alla loro estensione (ad esempio .txt, .py e così via) e calcola la dimensione totale del file per ciascun gruppo.

Puoi farlo in Marcel come segue:

L'operatore ls produce un flusso di oggetti File (-fr significa visitare le directory in modo ricorsivo e restituire solo file).

Gli oggetti File vengono reindirizzati al comando successivo, map. La mappa specifica una funzione Python, tra parentesi più esterne, che mappa ogni file su una tupla contenente l'estensione del file e la sua dimensione. (Marcel consente di omettere la parola chiave lambda.)

L'operatore rosso (riduci), raggruppa in base alla prima parte della tupla (estensione) e quindi somma le dimensioni all'interno di ciascun gruppo. Il risultato è ordinato per estensione.

Eseguibili host e pipeline Marcel

Le pipeline possono contenere una combinazione di operatori Marcel ed eseguibili host. Gli operatori reindirizzano gli oggetti, ma ai limiti dell'operatore/eseguibile, Marcel reindirizza invece le stringhe.

Ad esempio, questo comando combina operatori ed eseguibili ed elenca i nomi utente degli utenti la cui shell è /bin/bash.

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

cat è un eseguibile Linux. Si legge /etc/passwd e marcel convoglia i suoi contenuti a valle della mappa dell'operatore marcel.

L'argomento tra parentesi per map è una funzione Python che divide le righe nei separatori :, producendo 7 tuple. Un select è un operatore Marcel il cui argomento è una funzione Python che identifica quelle tuple in cui l'ultimo campo è /bin/bash.

L'operatore successivo, un'altra mappa, mantiene il campo nome utente di ciascuna tupla di input. Infine, xargs echo combina i nomi utente in entrata in un'unica riga, che viene stampata su stdout.

Scripting in Marcel Shell

Sebbene Python sia talvolta considerato un linguaggio di scripting, in realtà non funziona bene per questo scopo. Il problema è che eseguire comandi di shell e altri eseguibili da Python è complicato. Puoi usare os.system(), che è semplice ma spesso inadeguato per gestire stdin, stdout e stderr. subprocess.Popen() è più potente ma più complesso da usare.

L’approccio di Marcel è quello di fornire un modulo che integri gli operatori Marcel con le funzionalità del linguaggio Python. Per rivisitare un esempio precedente, ecco il codice Python per calcolare la somma delle dimensioni dei file per estensione:

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

I comandi della shell sono gli stessi di prima, ad eccezione delle convenzioni sintattiche. Quindi ls -fr diventa ls(file=True, recursive=True). Ci sono anche la mappa e gli operatori rossi, collegati con pipe, come nella versione shell. L'intero comando di shell (ls … red) produce un iteratore Python in modo che il comando possa essere utilizzato con Python per un ciclo.

Accesso al database con Marcel Shell

È possibile integrare l'accesso al database con le pipeline Marcel. Innanzitutto, devi configurare l'accesso al database nel file di configurazione, ~/.marcel.py, ad es.

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

DB_DEFAULT = 'jao'

Ciò configura l'accesso a un database Postgres denominato acme, utilizzando il driver psycopg2. Le connessioni da Marcel verranno effettuate utilizzando l'utente jao e il profilo del database si chiamerà jao. (DB_DEFAULT specifica il profilo del database jao come quello da utilizzare se non viene specificato alcun profilo.) Una volta effettuata questa configurazione, il database può ora essere interrogato utilizzando l'operatore sql, ad es.

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

Questo comando interroga una tabella denominata part e scarica il risultato della query nel file ~/reorder.csv, in formato CSV.

Accesso remoto con Marcel Shell

Analogamente all'accesso al database, l'accesso remoto può essere configurato in ~/.marcel.py. Ad esempio, questo configura un cluster a 4 nodi:

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

Il cluster può essere identificato come un laboratorio nei comandi marcel. I parametri utente e identità specificano le informazioni di accesso e il parametro host specifica gli indirizzi IP dei nodi sul cluster.

Una volta configurato il cluster, è possibile utilizzare tutti i nodi contemporaneamente. Ad esempio, per ottenere un elenco di pid di processo e righe di comando nel cluster:

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

Ciò restituisce un flusso di tuple (indirizzo IP, PID, riga di comando).

Per maggiori informazioni visita:

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

Marcel è piuttosto nuovo e in fase di sviluppo attivo. Contattaci se desideri dare una mano.