Rust语言实践:从零开始构建Shell

Posted 虫虫搜奇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust语言实践:从零开始构建Shell相关的知识,希望对你有一定的参考价值。

关注过Rust或者之前看过虫虫相关文章的人都知道,Rust是一个类似于C,但是内存安全、支持很多扩展功能,不用GC,高性能的底层语言。Rust源于Mozilla的一个内部员工的私人开发项目,2009年Mozilla官方开始资助该项目,2015年Rust发布1.0版本。Rust是一个非常有意思的项目,由于它"异于常语"而且也功能强大,所以现在开始变得很热门。本文虫虫就实例来展示下Rust语言的强大功能和魅力,实例开发一个shell程序。


shell的概念

shell是一个人机交互的终端控制程序。通过shell实现用户交互式的命令执行,简化应用程序和内核的交互。用户通过客户端(比如putty、xshell等)远程ssh登陆系统,并开启一个tty终端模拟器(pts,pseudo-tty)窗口。它运行在一个基于文本的程序,默认情况下是你登录的shell(一般linux中是bash)。当你在窗口中键入命令时候,该命令会在窗口中打印,并传递给shell标准输入stdin之外。然后又shell和内核进行通讯获得结果,结果通过 shell标准输出stdout和标准错误stderr(如果期间有任何异常的话),并在终端窗口中打印出来。

Rust语言实践:从零开始构建Shell


起步

最简单的shell,不需要多少 Rust代码。下面的代码中我们创建一个新字符串,用于保存用户输入stdin().read_line函数阻塞集成,等待用户输入回车键,然后将整个用户输入(包括按下输入的换行符)写入到字符串。然后我们对输入进行处理,通过input.trim()去除换行符,然后执行命令。

Rust语言实践:从零开始构建Shell


cargo run运行后,在终端中看到一个等待输入的闪烁光标。尝试键入ls并按回车键,会列出ls命令打印当前目录的内容,然后shell将退出。

执行多命令

一个真正的shell,在用户输入单个命令后执行后会,还可以继续执行下一个命令,而不是退出shell,这就shell的多命令执行。为支持执行多命令支持,我们将上面的代码打包到一个循环中,并在每个子进程上添加一个等待调用的问题,以确保在当前进程完成之前,不会提示用户输入其他内容。我们还增加了命令提示符"c>",用户提醒输入和执行的动作。

Rust语言实践:从零开始构建Shell


运行此代码,在运行第一个命令后,提示会返回输入界面,显示提示符"c>",因此你可以输入第二个命令。例如,下面我们使用ls、pwd和ps命令执行一下。

Rust语言实践:从零开始构建Shell


处理参数

如果你尝试在上面的shell上运行命令ls -a,程序就会崩溃。由于它不知道参数,它会尝试运行一个名为"ls -a"的命令。但正确的行为是使用运行ls命令,其参数为"-a"。

Rust语言实践:从零开始构建Shell


下面程序,通过用空白字符上拆分用户输入,并将第一个空格之前内容作为命令的名称(例如ls)处理,空格之后的内容作为参数(例如-a),并将参数传递给该命令来执行:

Rust语言实践:从零开始构建Shell


再带参数执行就ok,不会报错了

Rust语言实践:从零开始构建Shell


Shell内部命令

在shell中有一些命令,shell不能简单地分派给另一个进程,必须由shell本身来实现,一方面是为了性能原因或者其他使用频繁度来说,直接在shell中实现。比如cd、echo、exec等命令。下面代码中,我们在实例中,增加个内置的cd命名。

Rust语言实践:从零开始构建Shell


其他更多内部命令,可以参考cd实现做更多的扩展。

错误处理

在参数处理部分,我们如果不对单数处理时,执行"ls -a"就会报错,崩溃退出。为了应对这种异常,我们有必要增加错误处理部分,用来处理并提示错误,并继续下一条命令,而不是崩溃退出。

由于输入一个错误的命令是一个简单的方法来退出shell,我们在此也实现了exit内部命令。


管道|

Linux shell中很方便很好使得一个方面就是他强大的管道机制,管道简而言之就是"cmd1| cmd2",把shell将第一个命令cmd1的输出重定向到第二个命令cmd2的输入。例如,运行命令"ls | grep chongchong"将触发以下一系列操作:

1. ls将列出当前目录中的所有文件

2. shell将上面的文件列表传递给grep

3. grep将过滤列表并仅输出包含字符串chongchong的文件

下面代码的递增部分实现管道支持:


在本文中,我们利用不到100行的Rust代码实现了一个基本的shell程序。更多功能可以不断添加和完善,如果对本项目代码感兴趣,请关注虫虫,给虫虫留言索取。