Marcel是一个新的Shell。它在许多方面与传统的shell相似,但是在功能上有所不同:

  • 管道:所有Shell程序都使用管道将文本从一个命令的输出发送到另一个命令的输入。Marcel用管道传输结构化数据而不是字符串。
  • Python:Marcel是用Python实现的,并以多种方式公开Python。如果您的命令中需要一点逻辑,可以使用marcel用Python表示它。
  • 脚本编写:Marcel采用了一种不寻常的脚本编写方法。当然,您可以简单地在文本文件中编写一系列marcel命令并执行它们。但是Marcel还提供了Python模块形式的API。您可以导入该模块以比普通Python更加方便的方式执行Python脚本编写。

Marcel已获得GPLv3许可。

在Linux中安装Marcel Modern Shell

Marcel需要Python 3.6或更高版本。它已经在Linux上进行了开发和测试,并且主要在macOS运行。(如果您想帮助移植到Windows或修复macOS的缺陷,请联系。)

要安装marcel以供您自己使用:

linuxmi@linuxmi:~/www.linuxmi.com$ python3 -m pip install marcel

或者,如果您想为所有用户安装(例如,至/usr/local):

linuxmi@linuxmi:~/www.linuxmi.com$ sudo python3 -m pip install --prefix /usr/local marcel

一旦安装了marcel,请通过运行marcel命令检查其是否正常运行,然后在marcel提示符下运行version命令:

linuxmi@linuxmi:~/www.linuxmi.com$ marcel
/home/linuxmi/www.linuxmi.com $ version
0.10.7

检查Marcel Shell版本

定制Marcel Shell

您可以自定义文件中的marcel,该文件~/.marcel.py在启动时会读取(修改后会重新读取)。从文件名可以看出,marcel的自定义是在Python中完成的。

您可能想做的一件事是自定义提示。为此,您将一个列表分配给PROMPT变量。例如,如果希望您的提示成为当前目录,则以绿色打印,然后>以蓝色打印:

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

结果提示如下:

更改Marcel Shell提示颜色

这将替代PS1您需要在bash中进行的难以理解的配置。Color(0,4,0)指定green,(参数为RGB值,范围为0-5)。PWD是代表您当前目录的环境变量,并在此变量之前添加lambda:一个函数,该函数在每次显示提示时都会进行评估。

~/.marcel.py还可以导入Python模块。例如,如果要在marcel命令中使用math模块的功能:

from math import *

完成此操作后,您可以引用该模块中的符号,例如pi

Marcel Shell 符号

请注意,pi用括号括起来。通常,marcel使用括号来分隔Python表达式。因此,(pi)对检索变量pi的值的Python表达式求值。您还可以通过这种方式访问​​传统的环境变量,例如(USER)(HOME),或任何依赖于marcel命名空间中符号的有效Python表达式。

当然,您可以定义自己的Symbols(符号表)。例如,如果将此函数定义放在~/.marcel.py

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

然后您可以在命令行上使用阶乘函数factorial,例如

/home/linuxmi/www.linuxmi.com> (factorial(20))
2432902008176640000

在Marcel中创建自己的Symbols(符号表)

Marcel Shell的例子

在这里,我们将学习marcel shell中的一些命令示例。

按扩展名查找文件大小

递归浏览当前目录,按文件扩展名对文件进行分组(例如.txt.py依此类推),然后计算每个组的总文件大小。

linuxmi@linuxmi:~/www.linuxmi.com$ marcel
/home/linuxmi/www.linuxmi.com> ls -fr \
/home/linuxmi/www.linuxmi.com + | map (file: (file.suffix, file.size)) \
/home/linuxmi/www.linuxmi.com + | red . + \
/home/linuxmi/www.linuxmi.com + | sort

您可以按以下方式进行处理:


按扩展名查找文件大小

该ls操作符生成文件对象流,(-fr表示递归访问目录,只返回文件)。

file对象被输送到下一个命令map。该map在最外面的括号中指定了一个Python函数,该函数将每个文件映射到一个包含文件扩展名及文件大小的元组。(Marcel允许省略lambda关键字。)

red (reduce)运算符根据元组(扩展)的第一部分进行分组,然后对每个组内的大小进行求和。结果按扩展排序。

主机可执行文件和Marcel管道

管道可以混合包含marcel运算符和主机可执行文件。运算符通过管道传递对象,但在运算符/可执行文件的边界,以marcel代替字符串。

例如,这个命令组合了操作符和可执行文件,并列出shell为/bin/bash用户的用户名。

$ cat /etc/passwd \
| map (line: line.split(':')) \
| select (*line: line[-1] == '/bin/bash') \
| map (*line: line[0]) \
| root linuxmi jenkins
列出用户外shell

cat是一个Linux可执行文件。它读取/etc/passwd,然后marcel将其内容传输到下游的marcel操作符映射。

map的圆括号参数是一个Python函数,它在:分隔符处拆分行,生成7元组。select是一个marcel操作符,它的参数是一个Python函数,用于标识最后一个字段为/bin/bash的那些元组。

下一个运算符,另一个map保留每个输入元组的用户名字段。最后,xargs echo将输入的用户名合并为一行,并打印输出到屏幕。

Marcel Shell中的脚本编写

虽然Python有时被认为是一种脚本语言,但实际上它并不能很好地实现这一目的。问题是运行shell命令和Python的其他可执行程序很麻烦。您可以使用os.system(),它很简单,但通常不足以处理stdin,stdout和stderr。subprocess.Popen()功能更强大,但使用起来更复杂。

Marcel的方法是提供一个模块,该模块集成了Marcel运算符和Python的语言特性。回到前面的例子,下面是Python代码,用于按扩展名计算文件大小的总和:

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

除了语法约定外,shell命令与以前的命令相同。因此ls -fr变成ls(file=Truerecursive=True。映射和red运算符也在那里,并通过管道连接,就像在shell版本中一样。整个shell命令(ls…red)产生一个Python迭代器,因此该命令可以与Python一起使用来进行循环。

使用Marcel Shell进行数据库访问

您可以将数据库访问与marcel管道集成在一起。首先,您需要在config文件中配置数据库访问~/.marcel.py,例如

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

DB_DEFAULT = 'linuxmi'

这将使用psycopg2驱动程序配置对名为acmePostgres数据库的访问。来自marcel的连接将使用linuxmi用户进行,数据库配置文件名为linuxmi。(如果未指定概要文件,则DB_DEFAULT将linuxmi数据库概要文件指定为要使用的概要文件。)完成此配置后,现在可以使用sql运算符查询数据库。

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

此命令查询名为part的表,并将查询结果~/linuxmi.csv以CSV格式转储到文件中。

使用Marcel Shell进行远程访问

与数据库访问类似,可以在中配置远程访问~/.marcel.py。例如,这配置了一个4节点集群:

define_remote(name='lab',
              user='linuxmi',
              identity='/home/linuxmi/.ssh/id_rsa',
              host=['192.168.1.100', 
                    '192.168.1.101',
                    '192.168.1.102',
                    '192.168.1.103'])

可以在marcel命令中将集群标识为lab。用户和身份参数指定登录信息,host参数指定集群上节点的IP地址。

一旦配置了群集,即可立即操作所有节点。例如,要获取集群中的进程pid和命令行的列表:

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

这将返回(IP地址,PID,命令行)元组的流。

有关更多信息,请访问:

Marcel目前正在积极开发中。如果你愿意帮忙,请与我们联系。

发表评论

电子邮件地址不会被公开。 必填项已用*标注