Búsqueda de sitios web

Marcel: un Shell más moderno para Linux


Marcel es un nuevo caparazón. Es similar a los caparazones tradicionales en muchos aspectos, pero hace algunas cosas de manera diferente:

  • Tuberías: todos los shells utilizan tuberías para enviar un texto desde la salida de un comando a la entrada de otro. Marcel canaliza datos estructurados en lugar de cadenas.
  • Python: Marcel está implementado en Python y expone Python de varias maneras. Si necesitas un poco de lógica en tus comandos, marcel te permite expresarla en Python.
  • Secuencias de comandos: Marcel adopta un enfoque inusual respecto de las secuencias de comandos. Por supuesto, puedes simplemente escribir una secuencia de comandos marcel en un archivo de texto y ejecutarlos. Pero Marcel también proporciona una API en forma de módulo de Python. Puede importar este módulo para realizar secuencias de comandos Python de una manera mucho más conveniente que con Python simple.

Marcel tiene licencia GPLv3.

Instalación de Marcel Modern Shell en Linux

Marcel requiere Python 3.6 o posterior. Ha sido desarrollado y probado en Linux y funciona principalmente en macOS. (Si desea ayudar a migrar a Windows o corregir las deficiencias de macOS, póngase en contacto).

Para instalar marcel para su propio uso:

python3 -m pip install marcel

O si desea instalar para todos los usuarios (por ejemplo, en /usr/local):

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

Una vez que haya instalado marcel, verifique que esté funcionando ejecutando el comando marcel y luego, en el indicador de marcel, ejecute la versión comando:

marcel

Personalización de Marcel Shell

Puede personalizar marcel en el archivo ~/.marcel.py, que se lee al inicio (y se vuelve a leer cuando se modifica). Como puede ver por el nombre del archivo, la personalización de marcel se realiza en Python.

Una cosa que probablemente quieras hacer es personalizar el mensaje. Para hacer esto, asigna una lista a la variable PROMPT. Por ejemplo, si desea que su mensaje sea el directorio actual, impreso en verde, seguido de > impreso en azul:

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

El mensaje resultante se ve así:

Esto reemplaza la configuración inescrutable de PS1 que necesitarías hacer en bash. Color(0, 4, 0) especifica verde (los argumentos son valores RGB, en el rango 0-5 fuerte>). PWD es la variable de entorno que representa su directorio actual y antepone esta variable con lambda: genera una función, evaluada cada vez que se muestra el mensaje.

El ~/.marcel.py también puede importar módulos de Python. Por ejemplo, si desea utilizar las funciones del módulo matemático en sus comandos marcel:

from math import *

Una vez que haya hecho esto, puede consultar los símbolos de ese módulo, p. pi:

Tenga en cuenta que pi está entre paréntesis. En general, marcel usa paréntesis para delimitar expresiones de Python. Entonces (pi) evalúa la expresión de Python que recupera el valor de la variable pi. También puede acceder a variables de entorno tradicionales de esta manera, p. (USUARIO) y (INICIO), o cualquier expresión válida de Python que dependa de símbolos en el espacio de nombres de marcel.

Y, por supuesto, puedes definir tus propios símbolos. Por ejemplo, si pones esta definición de función en ~/.marcel.py:

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

entonces puedes usar la función factorial en la línea de comando, p.e.

Ejemplos de Marcel Shell

Aquí aprenderemos algunos ejemplos de comandos en Marcel Shell.

Buscar tamaños de archivos por extensión

Explore el directorio actual de forma recursiva, agrupe los archivos por su extensión (por ejemplo, .txt, .py, etc.) y calcule el tamaño total del archivo para cada grupo.

Puedes hacer esto en marcel de la siguiente manera:

El operador ls produce una secuencia de objetos Archivo (-fr significa visitar directorios de forma recursiva y devolver solo archivos).

Los objetos Archivo se canalizan al siguiente comando, mapa. El mapa especifica una función de Python, entre paréntesis más externos, que asigna cada archivo a una tupla que contiene la extensión del archivo y su tamaño. (Marcel permite que se omita la palabra clave lambda).

El operador rojo (reducir), agrupa por la primera parte de la tupla (extensión) y luego suma los tamaños dentro de cada grupo. El resultado está ordenado por extensión.

Ejecutables de host y Marcel Pipeline

Las canalizaciones pueden contener una combinación de operadores marcel y ejecutables de host. Los operadores canalizan objetos, pero en los límites operador/ejecutable, marcel canaliza cadenas.

Por ejemplo, este comando combina operadores y ejecutables y enumera los nombres de usuario de los usuarios cuyo shell es /bin/bash.

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

cat es un ejecutable de Linux. Lee /etc/passwd y marcel canaliza su contenido al mapa del operador marcel.

El argumento entre paréntesis para mapear es una función de Python que divide las líneas en los separadores :, produciendo 7 tuplas. Un select es un operador marcel cuyo argumento es una función de Python que identifica aquellas tuplas en las que el último campo es /bin/bash.

El siguiente operador, otro mapa, mantiene el campo de nombre de usuario de cada tupla de entrada. Finalmente, xargs echo combina los nombres de usuario entrantes en una sola línea, que se imprime en la salida estándar.

Secuencias de comandos en Marcel Shell

Si bien a veces se considera que Python es un lenguaje de programación, en realidad no funciona bien para ese propósito. El problema es que ejecutar comandos de shell y otros ejecutables desde Python es engorroso. Puede utilizar os.system(), que es simple pero a menudo inadecuado para tratar con stdin, stdout y stderr. subprocess.Popen() es más potente pero más complejo de usar.

El enfoque de Marcel es proporcionar un módulo que integre los operadores de Marcel con las características del lenguaje Python. Para volver a un ejemplo anterior, aquí está el código Python para calcular la suma de tamaños de archivos por extensión:

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

Los comandos del shell son los mismos que antes, excepto por las convenciones sintácticas. Entonces ls -fr se convierte en ls(file=True, recursive=True). Los operadores mapa y rojo también están ahí, conectados con tuberías, como en la versión shell. El comando de shell completo (ls … red) produce un iterador de Python para que el comando pueda usarse con un bucle for de Python.

Acceso a la base de datos con Marcel Shell

Puede integrar el acceso a la base de datos con marcel pipelines. Primero, necesita configurar el acceso a la base de datos en el archivo de configuración, ~/.marcel.py, por ejemplo.

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

DB_DEFAULT = 'jao'

Esto configura el acceso a una base de datos Postgres llamada acme, utilizando el controlador psycopg2. Las conexiones desde marcel se realizarán utilizando el usuario jao y el perfil de la base de datos se denomina jao. (DB_DEFAULT especifica el perfil de la base de datos jao como el que se utilizará si no se especifica ningún perfil). Una vez realizada esta configuración, la base de datos ahora se puede consultar utilizando el operador SQL, por ejemplo.

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

Este comando consulta una tabla denominada part y vuelca el resultado de la consulta en el archivo ~/reorder.csv, en formato CSV.

Acceso remoto con Marcel Shell

De manera similar al acceso a la base de datos, el acceso remoto se puede configurar en ~/.marcel.py. Por ejemplo, esto configura un clúster de 4 nodos:

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 se puede identificar como un laboratorio en los comandos de Marcel. Los parámetros de usuario e identidad especifican la información de inicio de sesión y el parámetro host especifica las direcciones IP de los nodos en el clúster.

Una vez configurado el clúster, se pueden operar todos los nodos a la vez. Por ejemplo, para obtener una lista de pids de procesos y líneas de comando en todo el clúster:

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

Esto devuelve un flujo de tuplas (dirección IP, PID, línea de comando).

Para más información visite:

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

Marcel es bastante nuevo y está en desarrollo activo. Ponte en contacto si quieres ayudar.