用Python从头开发一个自己的Shell(下)
gudong366 2025-07-23 14:56 4 浏览
编程派微信号:codingpy
平常工作中经常用到 shell 吧?好不好奇 shell 的具体执行方式?今天推送的这两篇文章,将利用 Python 实现一些简单的 shell 功能。
本文原作者为 Supasate Choochaisri ,由 PythonTG 翻译组的 Justin 翻译,校对为 EarlGrey。译者简介:Justin,python工程师一枚,对go、docker感兴趣,还在成长ing。
在第一部分中,我们已经实现了主要的 shell 循环,切分了命令输入,并通过 fork
和 exec
执行了输入命令。在本文中,我们将解决剩下的问题。第一个问题是 cd test_dir2
并未改变当前目录。第二个问题是我们仍不能优雅地退出 shell。
Step 4: 内置命令
cd test_dir2
并未改变当前目录,这种说法在某种意义上说既是对的又是错误的。正确是因为执行命令之后,仍在相同的目录。然而,目录确实改变了,不过是在子进程中改变的。
还记得我们 fork
了一个子进程,然后执行命令,这个命令并不会在父进程中执行,导致仅仅改变了子进程的目录,而没有改变父进程的目录。
之后,子进程终止,父进程仍保持原先的目录。
因此,这类命令必须为 shell 本身内置,并得在 shell 进程中执行,而不是通过 fork
。
cd
我们先从 cd
命令开始。
首先建立一个 builtins
目录,来存放内建命令。
在 cd.py
中,通过使用系统调用 os.chdir
实现自己的 cd
命令:
注意到在内建函数中会返回 shell 的运行状态,所以,我们把常量写进 yosh/constants.py
中供项目使用。
在 constants.py
中定义 shell 状态常量:
现在,内建的 cd
命令已经就绪。接下来修改 shell.py
来处理内建函数。
使用 Python 字典 built_in_cmds
,作为存储内建函数的哈希表。在 execute
函数中,将命令名及参数取出,如果命令名在哈希表中,就调用对应的函数。
(注意:built_in_cmds[cmd_name]
返回可以使用用参数立即调用的函数引用)
我们马上就可以使用内建的 cd
函数了,最后一步是将 cd
函数加到 built_in_cmds
中。
定义 register_command
函数来向内建命令哈希表中添加内建函数,然后定义 init
函数,并注册内建 cd
函数。
注意 register_command("cd", cd)
这一行代码。第一个参数是命令名,第二个参数是函数的引用。为了使第二个参数 cd
指向 yosh/builtins/cd.py
中的 cd
函数,我们需要在 yosh/builtins/__init__.py
中添加下面的代码:
from yosh.builtins.cd import *
因此,在 yosh/shell.py
中,当从 yosh.builtins
中 import *
时,就得到了 cd
函数的引用。
代码已经准备就绪,来尝试在 yosh
同级目录下运行 python -m yosh.shell
。
现在,我们的 cd
命令应该能够正确改变 shell 目录,同时哪些非内建命令也同样有效。
退出
下面是最后一步:优雅地退出。
我们需要一个函数将 shell 的状态改变为 SHELL_STATUS_STOP
,这样 shell 循环将会中断,shell 程序也将会结束并退出。
像 cd
一样,如果在子进程中 fork
并执行 exit
命令,对父进程不会有影响。因此,exit
函数必须为内建函数。
在 builtins
文件夹下新建 exit.py
:
exit.py
中定义了 exit
函数,用来返回终止主循环的状态值:
然后,在 yosh/builtins/__init__.py
中导入 exit
函数的引用:
from yosh.builtins.cd import *
from yosh.builtins.exit import *
最后,在 shell.py
中的 init()
函数中注册 exit
函数:
大功告成!
尝试运行 python -m yosh.shell
,现在输入 exit
就可以优雅地退出程序了。
一些思考
我希望你像我一样,享受创造 yosh
(属于自己的shell)的过程,但是 yosh
现在还是粗糙,我没有处理可能导致 shell 中断的特殊情况,也有很多内建功能没有覆盖到。一些非内建函数也可以作为内建函数实现,以提高性能(避免创建新进程的时间开销),还有很多功能没有实现(参考常见功能和特殊功能)
我在 github 上提供了源码,欢迎 fork 并把玩。
现在,轮到你来创造属于自己的 shell 了。
祝编码愉快!
Python 翻译组是EarlGrey@编程派发起成立的一个专注于 Python 技术内容翻译的小组,目前已有近 30 名 Python 技术爱好者加入。
翻译组出品的内容(包括教程、文档、书籍、视频)将在编程派微信公众号首发,欢迎各位 Python 爱好者推荐相关线索。
推荐线索,可直接在编程派微信公众号推文下留言即可。
相关推荐
- linux进程间的通信方式有哪些(linux怎么看这个进程在哪个路径下)
-
管道通信(PIPE)两个进程利用管道进行通信时.发送信息的进程称为写进程.接收信息的进程称为读进程。管道通信方式的中间介质就是文件.通常称这种文件为管道文件.它就像管道一样将一个写进程和一个读进程连接...
- Linux守护进程 daemonize 命令(linux 守护进城)
-
daemonize:作为守护进程运行命令的工具daemonize是一个命令行实用程序,它作为Unix/Linux守护进程运行命令。daemonize工具是用C语言编写的。大多数程序被设计为作为守护...
- linux进程间通信—信号(linux查看进程之间的通信指令i)
-
Linux环境进程间通信(二)信号(下)一、信号生命周期从信号发送到信号处理函数的执行完毕对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个重要的阶段,这三个阶段由四个...
- Linux 上以树状查看文件和进程(linux如何查看进程树)
-
提供了一些方便的命令,用于以树状分支形式查看文件和进程,从而易于查看它们之间的关系。在本文中,我们将介绍、和命令以及它们提供的一些选项,这些选项可帮助你将注意力集中在要查看的内容上。ps我们用...
- 文件搜不到?进程理不清?掌握这3个Linux技巧,效率直接翻倍!
-
哎家人们,今天必须跟你们唠唠Linux里那些“用了就回不去”的效率神器!我猜屏幕前肯定有不少朋友跟我之前一样——明明装着Linux当开发机/服务器,结果每天被命令行折腾得够呛:找个文件翻遍目录,看进程...
- 如何在 Linux 中使用 PID 号查找进程名称?
-
在Linux的复杂世界中,进程是系统运行的核心,每个进程都由一个唯一的「进程ID」(PID)标识。无论是系统管理员在排查失控进程,还是开发者在调试应用程序,知道如何将PID映射到对应的进程名称都是一项...
- Linux进程深度解析(1):进程结构、内存布局与资源管理
-
0.简介进程是系统执行的核心单元,理解进程是我们诊断性能问题、开发高并发程序的基础。Linux进程深度解析系列将会从原理角度对进程进行深入分析,帮助读者系统的理解其设计的思路,让读者在理解原理的基础...
- Linux 下如何查看进程的资源限制信息?
-
简介Linux上的cat/proc/$pid/limits命令提供有关特定进程的资源限制的信息,其中$pid是相关进程的进程ID(pid)。该文件是`/proc文件系统的一部分,该...
- Linux 8种进程状态及状态转换(linux进程状态切换)
-
Linux8种进程状态通过psaux可以看到进程的状态。O:进程正在处理器运行,这个状态从来没有见过.S:休眠状态(sleeping)R:等待运行(runable)RRunningorrun...
- 如何查看linux后台运行的进程?如何查看后台运行进程的状态?
-
linux系统中挂在后台的进程,如何能够被运维人员知道呢?以及挂在后台的进程当前状态是怎样的?是否可以继续执行?如何杀死一个在后台挂起的进程?后台进程可以通过‘&’符号或nohup命令,让程序进入...
- 最新保姆级、超详细介绍VMware的使用(一)软件的安装
-
一、VMware简介VMWare虚拟机软件是一个“虚拟PC”软件,它使你可以在一台机器上同时运行二个或更多Windows、DOS、LINUX系统。与“多启动”系统相比,VMware采用了完全不同的概...
- Shell脚本怎么写?(0)(shell脚本怎么写变量)
-
各位不好意思,最近加班+感冒,有三四天没更新了,python自动化脚本系列总共六期,基本已经囊括了编写python自动化脚本的所有基础函数和语法了。大家如果没看过这个系列的话,可以参考下面的链接:...
- 用Python从头开发一个自己的Shell(下)
-
编程派微信号:codingpy平常工作中经常用到shell吧?好不好奇shell的具体执行方式?今天推送的这两篇文章,将利用Python实现一些简单的shell功能。本文原作者为Su...
- Linux编程Shell之入门——Shell函数返回值
-
在Shell中,函数可以通过返回值将结果传递给调用者。返回值可以是一个整数、字符串或其他类型的数据。以下是关于Shell函数返回值的详细介绍:使用return语句在Shell函数中,使用return...
- Linux shell编程中易混淆的符号(linux中shell编程详解)
-
符号主要功能执行环境是否解析变量典型用例()子Shell执行命令子进程是隔离环境操作{}代码块或扩展当前Shell是(代码块内)组合命令或生成序列""弱引用字符串-是含变量...
- 一周热门
- 最近发表
-
- linux进程间的通信方式有哪些(linux怎么看这个进程在哪个路径下)
- Linux守护进程 daemonize 命令(linux 守护进城)
- linux进程间通信—信号(linux查看进程之间的通信指令i)
- Linux 上以树状查看文件和进程(linux如何查看进程树)
- 文件搜不到?进程理不清?掌握这3个Linux技巧,效率直接翻倍!
- 如何在 Linux 中使用 PID 号查找进程名称?
- Linux进程深度解析(1):进程结构、内存布局与资源管理
- Linux 下如何查看进程的资源限制信息?
- Linux 8种进程状态及状态转换(linux进程状态切换)
- 如何查看linux后台运行的进程?如何查看后台运行进程的状态?
- 标签列表
-
- linux一键安装 (31)
- linux运行java (33)
- ln linux (27)
- linux 磁盘管理 (31)
- linux 内核升级 (30)
- linux 运行python (28)
- linux 备份文件 (30)
- linux 网络测试 (30)
- linux 网关配置 (31)
- linux jre (32)
- linux 杀毒软件 (32)
- linux语法 (33)
- linux博客 (33)
- linux 压缩目录 (37)
- linux 查看任务 (32)
- 制作linux启动u盘 (35)
- linux 查看存储 (29)
- linux乌班图 (31)
- linux挂载镜像 (31)
- linux 软件源 (28)
- linux题目 (30)
- linux 定时脚本 (30)
- linux 网站搭建 (28)
- linux 远程控制 (34)
- linux bind (31)