Marcel - 更现代的 Linux Shell
Marcel 是一个新的外壳。它在很多方面与传统 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 供您自己使用:
python3 -m pip install marcel
或者,如果您想为所有用户安装(例如,安装到 /usr/local
):
sudo python3 -m pip install --prefix /usr/local marcel
安装 marcel 后,通过运行命令 marcel 检查它是否正常工作,然后在 marcel 提示符下运行 版本命令:
marcel
Marcel Shell 的定制
您可以在文件~/.marcel.py
中自定义marcel,该文件在启动时读取(并在修改时重新读取)。从文件名可以看出,marcel 的定制是用 Python 完成的。
您可能想做的一件事是自定义提示。为此,您可以将一个列表分配给 PROMPT 变量。例如,如果您希望提示符为当前目录,以绿色打印,后跟以蓝色打印的 >
:
PROMPT = [
Color(0, 4, 0),
lambda: PWD,
Color(0, 2, 5),
'> '
]
生成的提示如下所示:
这取代了您需要在 bash 中执行的难以理解的 PS1
配置。 Color(0, 4, 0) 指定绿色,(参数为RGB值,范围为0-5强>)。 PWD 是代表当前目录的环境变量,并在该变量前加上 lambda: 前缀会生成一个函数,每次显示提示时都会对其进行评估。
~/.marcel.py
还可以导入 Python 模块。例如,如果您想在 marcel 命令中使用 math 模块的函数:
from math import *
完成此操作后,您可以引用该模块中的符号,例如圆周率:
请注意,pi
带括号。一般来说,marcel 使用括号来分隔 Python 表达式。因此,(pi)
计算检索变量 pi 值的 Python 表达式。您还可以通过这种方式访问传统的环境变量,例如(USER) 和 (HOME),或任何依赖于 marcel 命名空间中符号的有效 Python 表达式。
当然,您可以定义自己的符号。例如,如果您将此函数定义放在 ~/.marcel.py
中:
def factorial(n):
f = 1
for i in range(1, n + 1):
f *= i
return f
然后您可以在命令行上使用阶乘函数,例如
马塞尔外壳示例
在这里,我们将学习 marcel shell 中的一些命令示例。
按扩展名查找文件大小
递归地探索当前目录,按扩展名对文件进行分组(例如 .txt
、.py
等),并计算每组的总文件大小。
您可以在 marcel 中执行此操作,如下所示:
ls 运算符生成 File 对象流(-fr
表示递归访问目录,并仅返回文件)。
File 对象通过管道传送到下一个命令,map。 map 在最外面的括号中指定一个 Python 函数,它将每个文件映射到一个包含文件扩展名及其大小的元组。 (Marcel 允许省略 lambda 关键字。)
red(减少)运算符按元组的第一部分(扩展)进行分组,然后对每组内的大小求和。结果按扩展名排序。
主机可执行文件和 Marcel 管道
管道可能包含 marcel 运算符和主机可执行文件的混合体。运算符通过管道传输对象,但在运算符/可执行文件边界处,marcel 通过管道传输字符串。
例如,此命令组合了运算符和可执行文件,并列出 shell 为 /bin/bash
的用户的用户名。
cat /etc/passwd \
| map (line: line.split(':')) \
| select (*line: line[-1] == '/bin/bash') \
| map (*line: line[0]) \
| xargs echo
cat 是一个 Linux 可执行文件。它读取 /etc/passwd,并且 marcel 将其内容向下游传送到 marcel 操作符映射。
map 的括号参数是一个 Python 函数,它在 :
分隔符处分割行,产生 7 元组。 select 是一个 marcel 运算符,其参数是一个 Python 函数,用于标识最后一个字段为 /bin/bash 的元组。
下一个运算符,另一个映射保留每个输入元组的用户名字段。最后,xargs echo 将传入的用户名组合成一行,并打印到标准输出。
在 Marcel Shell 中编写脚本
虽然 Python 有时被认为是一种脚本语言,但它实际上并不能很好地实现这一目的。问题是从 Python 运行 shell 命令和其他可执行文件很麻烦。您可以使用 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=True, recursive=True)。地图和红色运算符也在那里,通过管道连接,就像 shell 版本中一样。整个 shell 命令(ls … red) 生成一个 Python 迭代器,以便该命令可以与 Python 的 for 循环一起使用。
使用 Marcel Shell 访问数据库
您可以将数据库访问与 marcel 管道集成。首先,您需要在配置文件 ~/.marcel.py
中配置数据库访问,例如
define_db(name='jao',
driver='psycopg2',
dbname='acme',
user='jao')
DB_DEFAULT = 'jao'
这将使用 psycopg2 驱动程序配置对名为 acme 的 Postgres 数据库的访问。来自 marcel 的连接将使用 jao 用户进行,数据库配置文件名为 jao。 (如果未指定配置文件,则 DB_DEFAULT 将 jao 数据库配置文件指定为要使用的数据库配置文件。)完成此配置后,现在可以使用 sql 运算符查询数据库,例如
sql 'select part_name, quantity from part where quantity < 10' \
| out --csv –-file ~/reorder.csv
此命令查询名为 part 的表,并将查询结果以 CSV 格式转储到文件 ~/reorder.csv
中。
使用 Marcel Shell 进行远程访问
与数据库访问类似,远程访问可以在~/.marcel.py
中配置。例如,这配置了 4 节点集群:
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'])
该集群可以在 marcel 命令中被识别为实验室。 user 和identity 参数指定登录信息,host 参数指定集群上节点的IP 地址。
集群配置完成后,所有节点都可以同时运行。例如,要获取集群中的进程 pid 和命令行列表:
@lab [ps | map (proc: (proc.pid, proc.commandline))]
这将返回(IP 地址、PID、命令行)元组流。
欲了解更多信息,请访问:
- https://www.marceltheshell.org/
- https://github.com/geophile/marcel
Marcel 是一个相当新的项目,正在积极开发中。如果您想提供帮助,请联系我们。