1. bash 命令

小心

bash 命令的原理是在当前环境真实执行命令, 需要非常慎重, 请勿尝试危险的命令, 比如 rm, reboot 等命令.

如果你想渲染控制台的某条指令, 你可以使用 bash 命令, 比如如下 reST 代码,

代码 1.1 执行并渲染命令
.. bash:: ping www.baidu.com -c 4

可以产生以下效果.

$ ping www.baidu.com -c 4
PING www.wshifen.com (104.193.88.123) 56(84) bytes of data.
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=1 ttl=51 time=71.9 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=2 ttl=51 time=71.9 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=3 ttl=51 time=71.9 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=4 ttl=51 time=71.9 ms

--- www.wshifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 71.892/71.907/71.927/0.013 ms

bash 命令提供两种风格的渲染风格, 分别是 darklight, 默认的渲染风格是 dark, 如果你想使用 light 风格的渲染方式, 可以使用 :theme: 参数来指定渲染风格.

代码 1.2 指定渲染风格
.. bash:: ping www.baidu.com -c 4
    :theme: light
$ ping www.baidu.com -c 4
PING www.wshifen.com (104.193.88.77) 56(84) bytes of data.
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=1 ttl=46 time=71.8 ms
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=2 ttl=46 time=71.8 ms
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=3 ttl=46 time=71.8 ms
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=4 ttl=46 time=71.8 ms

--- www.wshifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 71.759/71.762/71.767/0.003 ms

如果你想修改渲染的字体大小, 你可以使用 :font-size: 参数来指定.

代码 1.3 指定字体大小
.. bash:: ping www.baidu.com -c 4
    :theme: light
    :font-size: 14px
$ ping www.baidu.com -c 4
PING www.wshifen.com (104.193.88.123) 56(84) bytes of data.
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=1 ttl=51 time=71.9 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=2 ttl=51 time=71.9 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=3 ttl=51 time=71.9 ms
64 bytes from 104.193.88.123 (104.193.88.123): icmp_seq=4 ttl=51 time=71.9 ms

--- www.wshifen.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 71.893/71.915/71.937/0.015 ms

bash 命令默认会执行后面的这条指令, 如果你只想显示命令, 而不想执行, 可以使用 :do-not-run: 参数, 如下 reST 代码.

代码 1.4 不执行, 只渲染命令
.. bash:: ping www.baidu.com -c 4
    :do-not-run:

可以产生以下效果.

$ ping www.baidu.com -c 4

某些命令会无限循环, 比如 ping www.baidu.com, 这条命令会一直执行下去, 直到用户使用 Ctrl + C 组合键将其中断. bash 遇到这种命令会有超时机制, 默认是 30 秒, 也就是一条指令最多运行 30 秒, 30 秒后 bash 命令会终止该进程并输出其渲染结果.

如果你想修改超时时间, 可以使用 :timeout: 参数来修改超时时间, 如下 reST 代码.

代码 1.5 设置超时时间
.. bash:: ping www.baidu.com
    :timeout: 4

可以产生以下效果.

$ ping www.baidu.com
PING www.wshifen.com (104.193.88.77) 56(84) bytes of data.
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=1 ttl=46 time=71.8 ms
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=2 ttl=46 time=71.8 ms
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=3 ttl=46 time=72.1 ms
64 bytes from 104.193.88.77 (104.193.88.77): icmp_seq=4 ttl=46 time=71.8 ms

如果你想执行的命令和渲染的命令不同, 可以使用 :display-command: 参数来单独指定渲染的命令.

代码 1.6 修改被渲染命令
.. bash:: echo "+1s"
    :display-command: 苟利国家生死以 岂因祸福避趋之

可以产生如 Bash 1.1 所示效果.

Bash 1.1 修改被渲染命令
$ 苟利国家生死以 岂因祸福避趋之
+1s

如果你想在执行某些命令后需要一些交互, 那么可以使用 :interactions: 参数. :interactions: 参数是一个 JSON, 其格式为 \(n \times 2\) 的字符串矩阵, 其中 \(n\) 表示交互次数. 对于每一次交互, 都由两部分组成, 前半部分是匹配模式, 如果控制台输出满足该匹配模式, 则启动交互, 而后半部分为交互的输入1. 代码 1.7 所示代码, 可以产生 Bash 1.2 所示结果.

代码 1.7 执行命令并与其交互
.. bash:: python3
    :interactions: [[">>>", "1 + 2"], [">>>", "exit()"]]
Bash 1.2 执行命令并与其交互
$ python3
Python 3.9.17 (main, Jul 27 2023, 08:42:23) 
[GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 + 2
3
>>> exit()

如果遇到输出非常长的命令, bash 命令会自动添加横向滚动条.

代码 1.8 渲染内容过长, 会添加横向滚动条
.. bash:: pip3 install requests
$ pip3 install requests
Requirement already satisfied: requests in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (2.31.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (3.3.0)
Requirement already satisfied: idna<4,>=2.5 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (2.0.6)
Requirement already satisfied: certifi>=2017.4.17 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (2023.7.22)

如果你不喜欢滚动条, 可以通过修改 :overflow: 参数的值来让 bash 自动换行.

代码 1.9 渲染内容过长, 会自动断行
.. bash:: pip3 install requests
    :overflow: wrap
$ pip3 install requests
Requirement already satisfied: requests in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (2.31.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (3.3.0)
Requirement already satisfied: idna<4,>=2.5 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (2.0.6)
Requirement already satisfied: certifi>=2017.4.17 in /home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/lib/python3.9/site-packages (from requests) (2023.7.22)

如果你想在运行某个命令前执行某个命令, 运行之后再执行另一个命令, 你可以使用 :setup::teardown: 参数.

比如, 运行某个命令需要提前安装依赖, 如果没有安装就会报错.

代码 1.10 调用命令, 缺少依赖报错
.. bash:: python3 -m rich.panel

直接运行会报错, 如下所示.

$ python3 -m rich.panel
/home/docs/checkouts/readthedocs.org/user_builds/sphinx-console/envs/latest/bin/python3: Error while finding module specification for 'rich.panel' (ModuleNotFoundError: No module named 'rich')

你可以用 :setup: 参数提前安装 rich 库, 然后再安装. 安装完成后, 使用 :teardown: 参数卸载.

代码 1.11 调用命令, 提前安装依赖, 成功执行
.. bash:: python3 -m rich.panel
    :setup: python3 -m pip install rich
    :teardown: python3 -m pip uninstall rich -y
$ python3 -m rich.panel

╔═════════════════════════════════ rich.Panel ═════════════════════════════════╗
║                                                                              ║
║ Hello, World!                                                                ║
║                                                                              ║
╚══════════════════════════════════════════════════════════════════════════════╝

如果你对 rich.panel 命令了解的话, 你应该知道 rich.panel 命令会填充整个控制台, 那么, 控制台的大小可以控制吗? 答案是可以的, bash 命令提供 :window-height::window-width: 两个参数来设置控制台的大小.

你可以用如下代码将控制台的宽度缩小至 40 字符.

代码 1.12 设置控制台宽度
.. bash:: python3 -m rich.panel
    :setup: python3 -m pip install rich
    :teardown: python3 -m pip uninstall rich -y
    :window-width: 40
$ python3 -m rich.panel

╔═════════════ rich.Panel ═════════════╗
║                                      ║
║ Hello, World!                        ║
║                                      ║
╚══════════════════════════════════════╝

你可以用 代码 1.13 中的命令来查看当前窗口的大小.

代码 1.13 查看控制台尺寸
.. bash:: python3 -c "import os; print(os.get_terminal_size())"
    :window-width: 40
    :window-height: 10
$ python3 -c "import os; print(os.get_terminal_size())"
os.terminal_size(columns=40, lines=10)

如果你想自定义命令的输出, 你可以为 bash 命令添加内容.

代码 1.14 自定义输出结果.
.. bash:: 说一句新年贺词

    春节玉快,
    合家欢络,
    谢谢大家.
$ 说一句新年贺词
春节玉快,
合家欢络,
谢谢大家.

提示

如果自定义了命令的输出, 则命令不会被执行.

footnotes

1

不需要手动添加 \n, bash:interactions: 参数会自动帮你添加 \n.