现在我们用的操作系统(Windows、Mac OS、Android、iOS 等)都是带图形界面的,简单直观,容易上手,对专业用户(程序员、网管等)和普通用户(家庭主妇、老年人等)都非常适用。然而在计算机早期并没有图形界面,只能通过一个个的命令来控制控制计算机,这些命令成千上万,先不说这些命令记不记得住,每天面对没有任何色彩的黑屏就是一件很难受的事。其实通过图形界面和命令行开启某个程序过程都是类似的,都需要查找程序在硬盘上的位置,然后将他们加载到内存中运行。本质都是:让用户控制计算机。
然而,真正能够控制计算机硬件(CPU、内存、显示器等)的只有操作系统内核(Kernel),图形界面和命令行只是架设在用户和内核之间的一座桥梁。
由于安全、复杂、繁琐等原因,用户不能直接接触内核(也没有必要),需要另外再开发一个程序,让用户直接使用这个程序;该程序的作用就是接收用户的操作(点击图标、输入命令),并进行简单的处理,然后再传递给内核,这样用户就能间接地使用操作系统内核了。
用户界面和命令行就是这个另外开发的程序,就是这层“代理”。在Linux下,这个命令行程序叫做 Shell。Shell 是一个应用程序,它连接了用户和 Linux 内核,让用户能够更加高效、安全、低成本地使用 Linux 内核,这就是 Shell 的本质。
Shell 能接收用户输入的命令,并对命令进行处理,处理完命令后再将结果反馈给用户,比如输出到显示器、写入到文件等。你看,我一直都在使用 Shell,哪有使用内核哦?我也没有看到 Shell 将我和内核连接起来呀?
其实,Shell 程序本身的功能是很弱的,比如文件操作、输入输出、进程管理等都得依赖内核。我们运行一个命令,大部分情况下 Shell 都会去调用内核暴露出来的接口,这就是在使用内核,只是这个过程被 Shell 隐藏了起来,它自己在背后默默进行,我们看不到而已。
接口其实就是一个一个的函数,使用内核就是调用这些函数。这就是使用内核的全部内容了吗?对!除了函数,你没有别的途径使用内核。
在 Shell 中输入的命令,有一部分是 Shell 本身自带的,这叫做内置命令;有一部分是其它的应用程序(一个程序就是一个命令),这叫做外部命令。
Shell 本身支持的命令不多,功能也有限,但是 Shell 可以调用其他的程序,每个程序就是一个命令,这使得 Shell 命令的数量可以无限扩展,其结果就是 Shell 的功能非常强大,完全能够胜任 Linux 的日常管理工作,如文本或字符串检索、文件的查找或创建、大规模软件的自动部署、更改系统设置、监控服务器性能、发送报警邮件、抓取网页内容、压缩文件等。
更加厉害的就是,Shell 还可以让多个外部程序发生连接,在它们之间很方便地传递数据,也就是把一个程序的输出结果传递给另一个程序作为输入。
由此可见Shell的功能强大之处并不是本身,而是它擅长使用和组织其他的程序。Shell 就是一个领导者,这正是 Shell 的魅力所在。
可以将 Shell 在整个 Linux 系统中的地位描述成下图所示:
注意:由于用户启动 Linux 后直接面对的是 Shell,通过 Shell 才能运行其它的应用程序,所以用户”和“其它应用程序”是通过虚线连接的
Shell 并不是简单的堆砌命令,我们还可以在 Shell 中编程,这和使用 C++、C#、Java、Python 等常见的编程语言差不多。
Shell 虽然没有 C#、Java、Python 等强大,但也支持基本的编程元素,例如:
if…else 选择结构,case…in 开关语句,for、while、until 循环;
变量、数组、字符串、注释、加减乘除、逻辑运算等概念;
函数,包括用户自定义的函数和内置函数(例如 printf、export、eval 等)。
从这个角度讲,Shell 也是一种编程语言,它的编译器(解释器)是 Shell 这个程序。我们平时所说的 Shell,有时候是指连接用户和内核的这个程序,有时候又是指 Shell 编程。
Shell 主要用来开发一些实用的、自动化的小工具,而不是用来开发具有复杂业务逻辑的中大型软件,例如检测计算机的硬件参数、搭建 Web 运行环境、日志分析等,Shell 都非常合适。
在计算机中,任何代码最终都要转换为二进制的形式才能在计算机中执行。
有的编程语言,比如C/C++、GO语言等必须要将所有的代码翻译成二进制形式(也就是生成可执行文件)然后才能执行,因而执行速度更快、效率更高对硬件的要求低。
这个过程叫做编译(Compile),这样的编程语言叫做编译型语言,完成编译过程的软件叫做编译器(Compiler)。
而有的编程语言,如Shell、python、PHP等,需要一边执行一边翻译不会生成任何可执行文件。用户必须拿到源码才能执行,程序运行后会及时翻译,翻译一部分执行一部分,不用等到所有的代码全部翻译完。
这个过程叫做解释,这样的编程语言叫做解释型语言或者脚本语言(Script),完成解释过程的软件叫做解释器。
两种类型语言的比较:
语言类型 | 特点 | 适用范围 |
---|---|---|
编译性语言 | 执行速度快、对硬件要求低、保密性好 | 开发操作系统、大型应用程序等 |
解释性语言 | 使用灵活、部署简单、跨平台性好 | 适合WEB开发以及制作小工具 |
常见的 Shell 有 sh、bash、csh、tcsh、ash 等。
几乎所有编程语言的教程都是从使用著名的“Hello World”开始的,作为中国人要弘扬传统,我的第一个 Shell 脚本也从输出“Hello World”开始。
①打开Linux终端,通过文本编辑器创建一个名字为test.sh的文件。
②给文件输入以下内容:
#!/bin/bash
echo "Hello World !" #这是一条语句
第 1 行的#!是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell;后面的/bin/bash就是指明了解释器的具体位置。
第 2 行的 echo 命令用于向标准输出文件(Standard Output,stdout,一般就是指显示器)输出文本。在.sh文件中使用命令与在终端直接输入命令的效果是一样的。
第 2 行的**#及其后面的内容是注释**。Shell 脚本中所有以#开头的都是注释(当然以**#!开头的除外**)。写脚本的时候,多写注释是非常有必要的,以方便其他人能看懂你的脚本,也方便后期自己维护时看懂自己的脚本。
③退出保存文件内容
④通过ls -l test.sh
查看文件权限
我们会发现文件权限是可读可写,却不可执行,这是因为它只是一个文本文件。当然不能执行喽!
那么接下来我们就要通过chmod 命令来给文件赋予执行的权限
⑤通过命令chmod test.sh
给文件赋予可执行权限
执行命令后再次查看文件的权限时发现文件已经可以执行了。
⑥通过命令./test.sh
执行脚本
会发现控制台已经打印出来了Hello World !
为什么什么要加这个./
呢?是不是有点多余呢?
当我们把./
去掉时会发现控制台会打印“command not found”,这又是为什么呢?这是因为在Shell的标准搜索路径($PATH)中找不到test.sh因此加上./
是很有必要的。