Skip to main content

Linux&Shell

1.简介与基本概念

1-1.发展简史——Unix、Minix到Linux

Unix是一种古老的操作系统(上世纪七十年代)。在Unix之前,操作系统基本都只能进行批处理作业,相当于你给计算机一批任务,然后计算机逐项去自动执行,执行完了反馈给你结果,在此过程中是不具可交互性的。为了满足交互性、及时性和多用户同时访问的需要,人们希望研制分时操作系统——通过时间片轮转为很多用户同时提供交互式服务。早期的尝试能支持的用户量很有限(MIT推动的MAC计划只能让30名左右的使用者同时共享IBM的大型计算机,到了1965年还最终不堪负荷),于是MIT决定研制更大型的分时计算机系统——MULTICS——其中通用电子公司参与了硬件开发,贝尔实验室承包了软件也就是操作系统。但是这一由众多大名鼎鼎的机构联合执行的计划最终失败了,MULTICS被传为笑柄。

但是,当时在贝尔实验室参与分时操作系统开发的成员在此项目中获得了宝贵的经验。贝尔实验室虽然退出了MULTICS项目,但为创建交互式计算环境的努力从未停止,后来汤姆森(Ken Thompson) 与里奇(Dennis Ritchie)在一些机缘巧合之下开发了Uniplexed Information and Computing System,被简称Unix,其中Uniplexed是对MULTICS首字母Multiplexed的嘲讽。历经很多版本的改进(其中重大的改进如将内核从由汇编语言写改成由高级语言写,他们尝试过世界上第一个被正式推广使用的高级语言Fortran,后来又产生出了B语言,但是都不理想,最后改良了B语言,开发出了C语言,因而里奇被称作C语言之父。这一改进大大增强了Unix的多平台可移植性),人们发现Unix相比于批处理系统有很多优势,应用规模逐渐扩大,最终贝尔实验室的所有者AT&T公司宣布要将Unix商业化。由于众多衍生版的出现,在随后的几十年中,Unix的发展经常伴随着产权纠纷。目前它的商标权由国际开放标准组织所拥有。

20世纪80年代,随着硬件计算能力的提升,计算机市场不断扩大。可供选用的操作系统中,Unix是商业软件,AT&T制定的价格昂贵;DOS系统是单用户单任务的,且源代码被微软当作商业秘密;MacOS系统只能用于苹果电脑。这在教学上为老师提了难题,因为找不到开源的例子。一名教授就编写了一个操作系统Minix来讲解操作系统内部工作原理。虽然Minix比较简单,但好处是完全开源的。全世界学计算机的学生都通过钻研Minix的源代码来学习操作系统,芬兰赫尔辛基大学大学二年级的学生Linus Torvalds就是其中一个。借鉴了Minix和Unix的思想,Linus在1991年写出了Linux操作系统。他把Linux的源码放到网上,所有人都可以免费获取,甚至可以进行商业应用。这就使得Linux迅速得到了全世界计算机企业和爱好者的支持,出现了很多发行版,用户可以根据自己的需要自由增添、剪裁Linux系统。这样以来,一个庞大的社区来不断更新和维护使Linux具有了长久的生命力。

1-2.Linux主要特点

(1)Linux是开源的,遵循GNU通用公共许可证(GPL)。这意味着任何人都可以基于Linux底层代码创建一个符合自己需求的Linux 发行版。

(2)一切皆文件。我们说Linux是类Unix系统,借鉴的思想主要就是这一点。无论是大家通常理解的文件,还是外设、命令、各种进程,对于操作系统内核而言都是文件,只不过文件的类型不同而已。

(3)多用户、多任务。同Unix一样,Linux是分时操作系统,各个用户可以同时登陆,由操作系统来保证各用户对于各类文件有合适的权限。Linux系统可以同时连接多个终端并且每隔一段时间重新扫描进程,重新分配进程的优先级,动态分配系统资源,从而在多进程同时运行时保持良好性能。

(4)交互性。Linux具有良好的交互性,用户可以得到及时响应。一般用的是字符界面,但是如果想要图形界面的话也可以单独安装GUI软件。支持多平台(还可嵌入式)、支持多处理器、有强大的网络功能等等。

1-3.Shell是什么?——CLI、Terminal、Console、Shell的区别与联系

CLI (Command-line Interface),即命令行界面,与GUI (Graphical User Interface),即图形用户界面相对。CLI/GUI只是一种界面形式,对应着敲命令或点鼠标,并不代表着某类具体软件。

Terminal ,即终端,是人与计算机进行交互的接口。一台大型机可以连接很多终端机,用户在这些终端机上跟计算机进行交互,这些早期终端一般是电传打字机(TTY),电传打字机也是第一个Unix终端。因此,在历史上,终端是连接到计算机上的一种带输入输出功能的外设。

Console ,即控制台,是一个特殊的终端。这个终端的特殊之处在于,它是计算机自身的一个组成成分,是系统管理员的终端,拥有比普通用户的终端更大的权限。一台大型机一般只有一个控制台,却可以连接很多终端。在个人计算机上,由于你既能做一般工作,也能做管理员的工作,因此控制台与终端的界限也就消失了。

随着个人计算机的普及和进化,大型机时代的专门的终端硬件早已消失,我们只用自己的键盘、鼠标来控制计算机。但是终端的思想保留了下来,变成了操作系统中的软件——终端模拟器(如Win32控制台)。终端模拟器可以捕获你的键盘输入,发送至命令行程序,拿到输出结果后再调用图形接口,将输出渲染至屏幕上。由于人们除了在博物馆再也见不到TTY这样的终端硬件了,于是就直接称终端模拟器为终端。

特别的,由于在早期Unix多用户系统当中的终端都是TTY,于是所有的终端硬件设备在Unix/Linux系统当中都以TTY命名,这一习惯延续至今。在现在,TTY和终端设备已不再区分了。

Shell ,即“壳层”,是帮助用户与内核交互的一类程序。操作系统内核直接负责管理计算机硬件,处于操作系统最底层,由于其重要性是不能轻易由用户直接操作的,因此需要有Shell程序来作为用户操作系统的入口。Shell是一类程序,可以有CLI形式的(如sh、bash、zsh;cmd、powershell等),也可以有GUI形式的(如Windows资源管理器explorer.exe等)。

至于为什么叫“壳层”,看下面这张图或许就感觉有点形象了。

或许现在你仍有些困惑,我们再来梳理一下。在用户用键盘和鼠标输入后,终端(Terminal)将这些输入发送给你选用的壳层(Shell),Shell解析你的命令发送给操作系统内核去执行,并把执行结果返回给终端,终端调用图形接口将结果显示到屏幕上。

以上这些基础知识我们有一些了解即可,目的是让我们跟计算机打交道时头脑更清楚,如果现在没搞清楚也不要紧,每个人对理论知识的理解角度都可能不同。只要掌握下面讲的实用技能,就足以在日常工作中得心应手。


2.Linux文件管理

Linux的设计哲学: 一切皆文件

2-1.系统目录结构

系统文件

  • /boot:存放着启动Linux时使用的内核文件,包括连接文件以及镜像文件。
  • /etc:存放所有的系统需要的配置文件和子目录列表。
  • /lib:存放基本代码库(比如c++库),几乎所有的应用程序都需要用到这些共享库。
  • /sys:该目录下安装了Linux2.6内核中新出现的一个文件系统 sysfs ,当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中。

指令/程序(文件)

  • /bin:存放着最常用的程序和指令。
  • /sbin:只有系统管理员能使用的程序和指令。

外部设备(文件)

  • /dev:Device的缩写,存放的是Linux的外部设备。注意:在Linux中访问设备和访问文件的方式是相同的。
  • /media:类windows的其他设备,例如U盘、光驱等等,识别后linux会把设备放到这个目录下。
  • /mnt:用于临时挂载别的文件系统,在讲docker时可能还会遇到。

临时文件

  • /run:是一个临时文件系统,存储系统启动以来的信息。
  • /lost+found:一般情况下为空的,系统非法关机后,这里就存放一些文件。
  • /tmp:这个目录是用来存放一些临时文件的。

账户文件

  • /root:系统管理员的用户主目录。
  • /home:用户的主目录,以用户的账号命名。
  • /usr:用户的很多应用程序和文件都放在这个目录下,类似于Windows下的program files目录。
  • /usr/bin:系统用户使用的应用程序与指令。
  • /usr/sbin:超级用户使用的比较高级的管理程序和系统守护程序。
  • /usr/src:内核源代码默认的放置目录。

程序运行中的文件

  • /var:存放经常修改的数据,比如程序运行的日志文件(/var/log 目录下)。
  • /proc:管理内存空间。虚拟的目录,是系统内存的映射,我们可以直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件来做修改。

2-2.磁盘管理

列出文件系统的整体磁盘用量

df [options] [file or directory path]
options -h 以人们较易阅读的 GB, MB, KB 等格式自行显示
-a 列出所有的文件系统
-k 以 KB 为单位显示各文件系统
-m 以 MB 为单位显示各文件系统
df命令会把file or directory path所在的文件系统的磁盘用量展示出来

列出某个文件或目录占用的磁盘空间

du [options] [file or directory path]
options -h 以人们较易读的容量格式 (G/M) 显示
-a 列出所有的文件与目录容量,因为默认仅统计目录底下的文件量而已
-s 列出总量而已,而不列出每个各别的目录占用容量
-S 不包括子目录下的总计,与 -s 有点差别
-k 以 KB 为单位显示容量
-m 以 MB 为单位显示容量
du命令会把file or directory path自身占用的磁盘空间大小展示出来

操作Linux磁盘分区表

sudo fdisk [option] [device name]
option -l 可以把整个系统内能够搜寻到的装置的分区均列出来

一般使用时,先通过df命令找出某个文件\目录所在的磁盘名称,然后再使用fdisk [找到的磁盘名称]对该磁盘进行分区管理。操作时,fdisk工具会有一步步的提示,只需跟着提示去做就可以了。离开时,按q不会保存修改;而按w会保存修改。

磁盘格式化

mkfs [option] [device name]
option -t [filesystem] 将指定的磁盘格式化为指定文件系统格式

磁盘挂载与卸载

mount [device name] [directory] # 将文件系统挂载到某个目录下
unmount [device name or directory] # 将某个文件系统或者某个目录挂载的文件系统卸载

3.常用Shell命令

tutorial_00

tutorial_01

tutorial_02

tutorial_03

tutorial_04

补充:

创建链接

软链接与硬链接的区别,详见:Linux软链接和硬链接

下面我们可以用ln命令来创建链接。一般不允许对目录制作硬链接,但是特别地可以通过-d选项允许超级用户制作目录的硬链接。

ln [options] [source path] [destination path]
options -b 覆盖以前建立的链接
-d 允许超级用户制作目录的硬链接
-f 强行建立文件或目录的连接,不论文件或目录是否存在
-i 覆盖既有文件之前先询问用户
-n 把软链接视为一般目录
-s 建立软链接(快捷方式)
-v 显示详细的处理过程
如果不加参数-s,则默认建立的是硬链接。

管道

所谓管道(pipe),就是将两个或者多个命令连接到一起,把一个命令的输出作为下一个命令的输入。Linux管道使用竖线| ,即管道符连接多个命令。语法格式如下:

[command1] | [command2] | [command3] ...

此时,管道符|左边命令的正确输出就变成了右边命令的输入,后续命令无法处理之前命令的错误输出。你可能会好奇,管道有什么用?下面我们举一个简单的例子。

查看某文件是否处于当前目录下

ls | grep [file name]

我们把ls命令的输出,也就是当前目录下的文件列表(不包含隐藏文件),送入“管道”作为grep命令的输入,之后grep命令匹配某文件名是否存在于文件列表当中,这样就达到了我们的目的。


4.Shell脚本

Shell脚本是一种在Shell中运行的脚本程序,由Shell作为脚本解释器,Shell脚本的一行就相当于一个命令,也可以用分号分隔一行之中的不同命令。

4-1.Shell脚本基础写法

注释

# hello!

变量

定义变量时,注意变量名和等号间不允许有空格。变量名也有限制,如只能包含英文字母、数字和下划线且不能以数字开头等。如:

a=1

引用变量时,注意要在变量名前加“$”符号。如:

echo $a

我们还可以查看环境变量。如显示家目录:

echo $HOME

删除变量用unset命令。如:

unset a

数组

定义数组:

array=(value0 value1 value2 value3)

读取数组元素:

echo ${array[0]}

使用 @ 符号可以获取数组中的所有元素:

echo ${array_name[@]}

分支

if else 语法格式:

if condition
then
command1
command2
...
commandN
else
command
fi

if else-if else 语法格式:

if condition1
then
command1
elif condition2
then
command2
else
commandN
fi

循环

for循环语法格式:

for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done

while循环语法格式:

while condition
do
command
done

在循环中,也可以跟C语言一样使用break和continue。此外,还有until循环,但一般不用。

4-2.运行Shell脚本

直接运行shell脚本

在确保脚本具有可执行权限的前提下,可以直接执行脚本。

./test.sh # 注意不能写成test.sh,否则会去环境变量中查找

作为解释器参数运行shell脚本

bash test.sh # 参数是脚本路径

5.Shell环境变量

环境变量是存储有关shell的工作环境的数据,以便程序或shell中运行的脚本能够访问到它们。系统会创建好一些环境变量,我们在安装新程序等操作时也要留意是否需要设置环境变量,否则会出现“command not found”的错误。

5-1.查看环境变量

env # 查看全部全局变量
printenv HOME # 查看个别全局变量(HOME)
echo $HOME # 查看个别全局变量(HOME)

常用环境变量

  • HOME :当前用户的主目录
  • PATH : shell 查找命令的目录列表,由冒号分隔
  • PWD :当前工作目录

5-2.设置环境变量

设置临时环境变量

可通过将局部变量导出到环境当中来设置环境变量,在该进程及其所创建的子进程中,该环境变量都是可见的,且子进程中的修改不会作用到父进程的环境变量。但是,这种设置是临时的,一旦退出当前shell就消失了。

variable="test"
export variable # 导出环境变量
unset variable # 删除环境变量

设置持久环境变量

如想设置持久的环境变量,就需要修改系统启动时用于加载环境变量的文件。这些文件各自有不同功能,首先,/etc目录下的文件是系统级的,所有用户的终端都会加载;而~/也就是用户主目录下的文件是用户级的,只有该用户的终端会加载。其次,profile文件在交互式登录shell当中加载,而bashrc文件在交互式非登录shell当中加载,不过由于profile文件当中引用了bashrc文件中的环境变量,因此也可认为在登录shell当中将二者都加载了。所谓登录就是指“用户登录到系统的shell” ,而其他的都是非登录shell。

因此,一般我们修改的文件有以下四个(其实绝大多数情况下修改~/.bashrc就够了):

/etc/profile # 系统级,登录shell当中加载
/etc/bashrc # 系统级,可认为都会被加载
~/.profile # 用户级,登录shell当中加载
~/.bashrc # 用户级,可认为都会被加载

修改PATH环境变量时,一般采用追加导出的方式,即在文件的最后一行加上:

export PATH=/usr/local/src/mongodb/bin:$PATH

使设置的环境变量立即生效

如果想不重启终端使设置的环境变量立即生效,可以用source命令。source命令本意是在当前shell中依次执行一个文件中的每行命令,而不像sh file name与./file name 那样会建立一个子shell。通过执行profile或者bashrc中的全部命令,就重置了当前shell的全部环境变量。

source [file name]

6.SSH简介

SSH = Secure Shell,即安全外壳协议,是为远程登录会话提供安全性的协议,一般用作远程登录到服务器。有关SSH的通信过程和加密原理在此就不做介绍了,感兴趣的同学可以查找网络资料。

6-1.SSH基础用法

通过用户名和主机名连接到服务器

ssh user@hostname # 主机名可以是IP地址或者域名

如果有密码验证,会要求输入密码。(输入密码时密码不会显示在屏幕上)

连接时指定端口

ssh -p [port] user@hostname # SSH默认连接到目标主机的22端口,可以通过-p指定其他端口

在远程主机执行一条命令

ssh user@hostname [command] # 仅执行一条命令,之后返回本地工作