万字长文深入理解Linux系统管理

发布于 2021-09-01 10:29 ,所属分类:中小学阅读学习资料


一.Shell基本命令

一直以来Shell 以其稳定、高效和灵活成为系统管理员的首选。本文主要介绍Shell的基本命令,包括切换目录、查找并查看文件、查看用户信息等。本文过后,读者还能够向用户手册寻求帮助。在开始这些内容之前,首先简要介绍一下究竟什么是 Shell。

1.Shell简介

命令行和 Shell这两个概念常常是令人困惑的。在很多并不正式的场合,这两个名词代表着相同的概念,即命令解释器。然而从严格意义上讲,命令行指的是供用户输入命令的界面,其本身只是接受输入,然后把命令传递给命令解释器。后者就是Shell。从本质上讲,Shell 是一个程序,它在用户和操作系统之间提供了一个面向行的可交互接口。用户在命令行中输入命令,运行在后台的Shell 把命令转换成指令代码发送给操作系统。Shell 提供了很多高级特性,使得用户和操作系统间的交互变得简便和高效。


目前,在Linux环境下有几种不同类型的Shell,常用的有Bourne Again Shell(BASH),TCSH Shcll、Z-Shell等。不同的Shell提供不尽相同的语法和特性,用户可以使用任何一种Shell。在 Linux 上,BASH shell 是默认安装和使用的Shell。本文章中所有的命令都在BASH下测试通过。当然,读者如果有兴趣,也可以尝试使用其他类型的Shell.


查看你正在使用的shell解释器


echo $0

2.约定

Linux命令行界面有一个输入行,用于输入命令。在 BASH中,命令行以一个美元符号“$”作为提示符,表示用户可以输入命令了。下面就是一个Shell提示符,表示命令行的开始。

$

如果正在以root身份执行命令,那么Shell提示符将成为“#”,如下所示。

#


本文中的命令将以 提示符+命令+注释 的形式给出。以下面这个命令为例


$ sudo dpkg -i linuxqq_1.0-Preview1_i386.deb ##安装QQ for Linux

其中,“$”符号为命令行提示符,“sudo dpkg -i linuxqq_1.0-Preview1_i386.deb”是命令,而“##”后面的文字则是注释。注释是为了更清楚地解释命令用途而添加的,在实际使用过程中并不会出现。读者在使用时只需要输入命令部分。需要提醒的是,Linux的命令和文件名都是区分大小写的。也就是说,SUDO和 sudo是不一样的。

注意:在BASH的美元提示符前,一般还会有一段信息,包括用户名、主机名和当前目录。一个完整的提示符如下:


[root@localhost ~]$

3.快速上手,浏览你的硬盘

本文将全程采用权限最高的root用户。


本节将带领读者浏览自己计算机上的文件系统。这里的命令都非常简单,以期给读者带来一个整体的印象。稍后将详细讲解各类基本命令。


首先,打开终端进入根目录看看里面都有些什么。


可以看到,Linux安装完毕后自动在根目录下生成了大量目录和文件。在后续章节中,将逐一讨论这些目录的用途。


下面选择home进入。这个目录中存放着系统中所有用户的主目录。主目录的名字就是用户名。在作者的计算机上,只有一个mzc用户。


可以使用不带任何参数的cd命令进入用户主目录。主目录下存放着一些配置文件和用户的私人文件。用户主目录默认对其他用户关闭访问权限。


下面到/etc目录下看一看。这个目录存放着系统以及绝大部分应用软件的配置文件(这里只列出了其中的一部分)。和 Windows不同,Linux 使用纯文本文件来配置软件。修改配置文件可以很方便地对软件进行订制。


查看一下 fstab这个文件,其中定义了各硬盘分区所挂载到的目录路径。


小伙伴们还可以选择其他目录进入并察看相应的文件,看看Linux 都安装了一些什么。接下来。在正式介绍命令之前,首先来看一些BASH的特性,这些特性可以帮助我们提高工作效率。

4.提高效率,使用命令行补全和通配符

文件名是命令中最为常见的参数,然而每次完整输入文件名是一件很麻烦的事情,特别是当文件名还特别长的时候。幸运的是,BASII 提供了这样一种特性——命令行补全。在输入文件名的时候,只需要输入前面几个字符,然后按下Tab键,Shell 会自动把文件名补全。

例如在/etc目录下输入cat fs +键盘tab键 Shell 会自动将其补全为cat fstab:


[root@localhost etc]# cat fstab 


如果以已键入的字符开头的文件不止一个,那么可以连续按下Tab键两次,Shell 会以列表的形式给出所有以键入字符开头的文件,例如在/etc/目录下:


[root@localhost etc]# cat bbash_completion.d/ bashrc             binfmt.d/          bluetooth/         brltty/            brltty.conf  


事实上,命令行补全也适用于所有Linux命令。例如输入ca并按下 Tab键两次时,如下:



[root@localhost etc]# cacacertdir_rehash cache_metadata_size cairo-sphinx calibrate_ppa canberra-gtk-play capsh case catman cache_check cache_repair cal caller cancel captoinfo cat cache_dump cache_restore ca-legacy canberra-boot cancel.cups caribou-preferences catchsegv



注意:系统命令本质上就是一些可执行文件,可以在/usr/bin/目录下找到。从这种意义上讲,命令补全和文件名补全其实是一回事。


另外,Shell有一套被称作通配符的专用符号,它们是*、?和[ ]。这些通配符可以搜索并匹配文件名的一部分。从而大大简化命令的输入,这使得批量操作成为可能。


*用于匹配文件名中任意长度的字符串。例如需要列出当前目录中所有的.login结尾的文件,命令如下:


[root@localhostetc]#ls
[root@localhost etc]# ls *.logincsh.login[root@localhost etc]#



和*相类似的通配符是?。但和*匹配任意长度的字符串不同,?只匹配一个字符。下面的例子中,?用以匹配文件名中以text开头而后跟一个字符的文件。



[root@localhost opt]# lsrh testA test_A testB testBS testD[root@localhost opt]# ls test?testA:

testB:

testD:[root@localhost opt]#



5.查看目录和文件

本节将介绍目录和文件的操作命令,这些可能是用户最常用到的命令了。其中的一些在“快速上手”环节已经尝试过了,这里将作进一步讲解,详细讨论命令各个常用选项。小伙伴们应该始终牢记的一点是,应该用肌肉,而不是头脑去记忆这些命令和选项。

显示当前目录:pwd

pwd命令会显示当前所在的位置,即工作目录。例如,执行如下命令:


小贴士:读者可能会问一个问题,既然在BASH的命令提示符前,会显示当前工作路径名,那么为什么还需要pwd这个命令呢?答案是这个特性并不是所有Shell都采用的.在Freebsd等操作系统中,BASH并不自动显示当前目录。因此即便在某个版本的Linux 中,pwd 显得完全没有必要,这并不意味着在其他版本的UNIX/Linux系统中,pwd也是无用的。


改变目录:cd

cd命令是在Linux文件系统的不同部分之间移动的基本工具。当登录系统之后,总是处在用户主目录中。这个目录有一个名字,也就是“路径名”,它是由/home/开头,后面跟着登录的用户名。


输入cd命令,后面跟着一个路径名作为参数,就可以直接进入另外一个子目录中去。举例来说,使用下面的命令进入/usr/bin子目录。


在/usr/bin子目录时,可以用以下命令进入/usr子目录


在/usr/bin子目录中还可以使用下面的命令直接进入根目录,即“/”目录。


最后,总能够用下面的命令回到自己的用户主目录。


提示:在Shell 中,“..”代表当前目录的上一级目录。而“.”则代表当前目录.另外,“~”代表用户主目录,这个符号通常位于Esc键下方。


列出目录内容:ls

ls命令是list的简化形式,ls 的命令选项非常之多,这里只讨论一些最常用的选项。


不带任何参数的ls命令,用于列出当前目录下的所有文件和子目录。

白色:表示普通文件

蓝色:表示目录

绿色:表示可执行文件

红色:表示压缩文件

浅蓝色:链接文件 主要是使用ln命令建立的文件

红色闪烁:表示链接的文件有问题

黄色:表示设备文件

灰色:表示其他文件

但是这些文件就是主目录下所有的文件了吗?尝试一下-a选项。


这次看到了很多头部带“.”的文件名。在 Linux上,这些文件被称作隐含文件,在默认情况下并不会显示。除非指定了-a选项,用于显示所有文件。


另一个常用选项是-1选项。这个选项可以用来查看文件的各种属性。


total:代表总用量

-表示是普通文件,第一个字符有几种情况:-表示普通文件,d代表目录,l代表连接文件,b代表设备文件。

-rwxrw-rw- 表示文件的权限,linux中有三种文件操作权限:分别为读(r),写(w),执行(x).

第一个root表示这个文件的所属用户是root

第二个root表示这个文件的所属用户组是lan这个组

接下类的数字 101 表示文件的大小,也就是字节数。101表示101字节

接下来的是,文件最近一次修改的时间

最后就是文件名了

在ls命令后跟上路径名可以查看该子目录中的内容。


列出目录内容:dir和vdir

Windows用户可能更熟悉dir这个命令。在Linux 中,dir除了比ls的功能更少,其他都是一样的。


vdir 相当于为ls命令加上-1选项,默认情况下列出目录和文件的完整信息。


查看文本文件:cat和more

cat命令用于查看文件内容(通常这是一个文本文件),后跟文件名作为参数。


cat可以跟多个文件名作为参数。当然也可以使用通配符:


对于程序员而言,为了调试方便,常常需要显示行号。为此,cat命令提供了-n选项,在每一行前显示行号。



cat命令会一次将所有内容全部显示在屏幕上,这看起来是一个致命的缺陷。因为对于一个长达几页甚至几十页的文件而言,cat显得毫无用处。为此,Linux 提供more命令来一页一页地显示文件内容。more命令会在最后显示一个百分比,表示已显示内容占整个文件的比例。按下空格键向下翻动一页,按Enter键向下滚动一行。按Q键退出。

阅读文件的开头和结尾:head和tail

另两个常用的查看文件的命令是head和 tail。分别用于显示文件的开头和结尾。可以使用-n参数来指定显示的行数。


注意,head命令的默认输出是包括了文件名的(放在-->和<--之间)。tail的用法和head相同。


更好的文本阅读工具:less

less 和 more非常相似,但其功能更为强大。less 改进了more命令的很多细节,并添加了许多的特性。这些特性让 less 看起来更像是一个文本编辑器——只是去掉了文本编辑功能。总体来说,less命令提供了下面这些增强功能。

命令符号 描述

/字符串 向下搜索“字符串”的功能

?字符串 向上搜索“字符串”的功能

n 重复前一个搜索(与 / 或 ? 有关)

N 反向重复前一个搜索(与 / 或 ? 有关)

b 向前翻一页

d 向后翻半页

q 退出 less 命令

空格键 向后翻一页

向上键 向上翻动一行

向下键 向下翻动一行


使用带参数-M的less命令可以显示更多的文件信息,如下:


可以看到,lcss 在输出的底部显示了这个文件的名字、当前页码、总的页码,以及表示当前位置在整个文件中的位置百分比数值。最后按下Q键可以退出less程序并返回Shell提示符。

查找文件内容:grep

在很多时候,并不需要列出文件的全部内容,用户要做的只是找到包含某些信息的一行。这个时候,如果使用more命令一行一行去找的话,无疑是费时费力的。当文件特别大的时候,这样的做法则完全不可行了。为了在文件中寻找某些信息,可以使用grep命令。

grep [OPTIONS] PATTERN [FILE...]


例如,为了在文件drirc中查找包含 device的行,可以使用如下命令:


可以看到,grep 有两个类型不同的参数。第一个是被搜索的模式(关键词),第二个是所搜索的文件。grep 会将文件中出现关键词的行输出。可以指定多个文件来搜索,例如:


严格地说,grep通过“基础正则表达式( basic regular expression)”进行搜索。和grep相关的一个工具是cgrep,除了使用“扩展的正则表达式( extended regular expression)”,egrep 和grep 完全一样。“扩展正则表达式”能够提供比“基础正则表达式”更完整地表达规范。正则表达式将在后续文章中详细讨论。

指定目录下查找文件:find

随着文件增多,使用搜索工具成了顺理成章的事情。find 就是这样一个强大的命令,它能够迅速在指定范围内查找到文件。find命令的基本语法如下:

find [OPTION] [path...] [expression]


例如,希望在/usr/bin/目录中查找zip命令:


从这个例子中可以看到,find 命令需要一个路径名作为查找范围,在这里是/usr/bin/ 。find 会深入到这个路径的每一个子目录中去寻找,因此如果指定/,那么就查找整个文件系统。-name选项指定了文件名,在这里是zip。可以使用通配符来指定文件名。如find~/ -name *.c-print将列出用户主目录下所有的c程序文件。-print 表示将结果输出到标准输出(在这里也就是屏幕)。注意find命令会打印出文件的绝对路径。

find命令还能够指定文件的类型。在 Linux 中,包括目录和设备都以文件的形式表现,可以使用-type选项来定位特殊文件类型。例如,在/etc/目录中查找名叫init.d的目录:


find命令的-type选项可供使用的参数


参数 含义

b 块设备文件

c 字符设备文件

d 目录文件

f 普通文件

p 命名管道

l 符号链接

还可以通过指定时间来指导find命令查找文件。-atime n用来查找最后一次使用在n天前的文件,-mtime n则用来查找最后一次修改在n天前的文件。但是在实际使用过程中,很少能准确确定n的大小。在这种情况下,可以用+n表示大于n,用-n表示小于n。例如,在/usr/bin/中查找最近100天内没有使用过的命令(也就是最后一次使用在100天或100天以前的命令)。


类似地,下面这个命令查找当前目录中,在最近一天内修改过的文件。


快速定位文件:locate

尽管find命令已经展现了其强大的搜索能力,但对于大批量的搜索而言,还是显得慢了一些,特别是当用户完全不记得自己的文件放在哪里的时候。这时,locate命令会是一个不错的选择。如下:


这些搜索结果几乎是一瞬间就出现了。这不禁让人疑惑,locate 究竟是如何做到这一点的?事实上,locate并没有进入子目录搜索,它有一点类似于Google的桌面搜索,通过检索文件名数据库来确定文件的位置。locate命令自动建立整个文件名数据库,不需要用户插手。如果希望立刻生成该数据库文件的最新版本,那么可以使用updatedb命令。运行这个命令需要有root权限,更新整个数据库大概耗时1分钟。

查找特定程序:whereis

whereis命令主要用于查找程序文件,并提供这个文件的二进制可执行文件、源代码文件和使用手册页存放的位置。例如,查找find命令:

- 可以使用-b选项让 whereis命令只查找这个程序的二进制可执行文件。


如果whereis无法找到文件,那么将返回一个空字符串。


whereis无法找到某个文件的可能原因是,这个文件没有存在于任何whereis命令搜索的子目录中。whereis命令检索的子目录是固定编写在它的程序中的。这看起来多少有点像是个缺陷,但把搜索限制在固定的子目录如/usr/bin、/usr/sbin和/usr/share/man中可以显著加快文件查找的进度。

用户及版本信息查看:who

在一台服务器上,同一时间往往会有很多人同时登录。who命令可以查看当前系统中有哪些人登录,以及他们都工作在哪个控制台上。


有些时候,可能会忘记自己是以什么身份登录到系统,特别当需要以特定身份启动某个服务器程序时。这个时候, whoami这个命令会很有用。正如这个命令的名字那样, whoami会回答“我是谁”这个问题。


另一个常用的命令是uname,用于显示当前系统的版本信息。带-a选项的uname命令会给出当前操作系统的所有有用信息。


在大部分时候,需要的只是其中的内核版本信息。此时可以使用-r选项。


寻求帮助:man

在Linux中获取帮助是一件非常容易的事情。Linux为几乎每一个命令和系统调用编写了帮助手册。使用man命令可以方便地获取某个命令的帮助信息。

- man命令在显示手册页时实际调用的是less程序。可以通过方向键或J键(表示向下)、K(表示向上)键上下翻动。空格键用于向下翻动一页。按下Q键则退出手册页面。man手册一般被分成9节,各部分内容如表5.2所示。


man手册的组织


目录 内容

/usr/share/man/man1 普通命令和应用程序

/usr/share/man/man2 系统调用

/usr/share/man/man3 库调用,主要是libc()函数的使用文档

/usr/share/man/man4 设备驱动和网络协议

/usr/share/man/man5 文件的详细格式信息

/usr/share/man/man6 游戏

/usr/share/man/man7 文档使用说明

/usr/share/man/man8 系统管理命令

/usr/share/man/man9 内核源代码或模块的技术指标

获取命令简介:whatis和apropos

man手册中的长篇大论有时候显得太啰嗦了——很多情况下,人们只是想要知道一个命令大概可以做些什么。于是,whatis满足了大家的好奇心。

- whatis从某个程序的使用手册页中抽出一行简单的介绍性文字,帮助用户了解这个程序的大致用途。whatis的原理同locate命令基本一致。


与之相反的一个命令是 apropos,这个命令可以通过使用手册中反查到某个命令。举例来说,如果用户想要搜索一个文件,而又想不起来应该使用哪个命令的时候,可以这样求助于apropos。


可以看到,apropos将命令简介(其实就是whatis的输出)中包含“search”的条目一并列出,用户总能够从中找到自己想要的。

二.文件目录管理

使用文件和目录是工作中不可回避的环节。通过前面的章节,读者已经积累了一些文件和目录的操作经验。本章将进一步介绍如何使用Shell管理文件和目录。在正式讲解相关命令之前,有必要介绍一下Linux目录结构的组织形式。小伙伴们应该已经在之前的文章大概了解了整个文件系统,但仍对此心存疑惑。

1.Linux 文件系统的架构

正如大家看到的一样,Linux目录结构的组织形式和 Windows有很大的不同。首先Linux没有盘符的概念,也就是说Linux 系统不存在所谓的C盘、D盘等。已建立文件系统的硬盘分区被挂载到某一个目录下,用户通过操作目录来实现磁盘读写。正如读者在安装Linux时所注意到的那样。其次,Linux似乎不存在像Windowsl这样的系统目录。在安装完成后,就有一堆目录出现在根目录下,并且看起来每一个目录中都存放着系统文件。最后一个小小的区别是,Linux使用正斜杠/而不是反斜杠\来标识目录。


既然Linux将文件系统挂载到目录下,那么究竟是先有文件系统还是先有目录?和“先有鸡还是先有蛋”一样,这个问题初看起来有点让人犯晕。正确的说法是,Linux需要首先建立一个根/文件系统,并在这个文件系统中建立一系列空目录,然后将其他硬盘分区(如果有的话)中的文件系统挂载到这些目录中。


理论上说,可以为根目录下的每一个目录都单独划分一个硬盘分区,这样根分区的容量就可以设置得很小(因为几乎所有的东西都存放在其他分区中,根分区中的目录只是起到了映射的作用),不过这对于普通用户而言没有太大必要。


如果某些目录没有特定的硬盘分区与其挂钩的话,该目录中的所有内容将存放在根分区中。


提示:说了那么多,有一个概念始终没有作解释,究竟什么是文件系统?这个问题将在后续的文章中详细讨论。这里,读者只要简单地把它理解为磁盘或者分区的同义词就可以了。


Linux系统主要目录以及其内容


目录 内容

/bin 构建最小系统所需要的命令(最常用的命令)

/boot 内核与启动文件

/dev 各种设备文件

/etc 系统软件的启动和配置文件

/home 用户的主目录

/lib C编译器的库

/media 可移动介质的安装点

/opt 可选的应用软件包(很少使用)

/proc 进程的映像

/root 超级用户root的主目录

/sbin 和系统操作有关的命令

/tmp 临时文件存放点

/usr 非系统的程序和命令

/var 系统专用的数据和配置文件

2.共享文件

共享文件对一个团队而言非常重要。团队的成员常常需要在一台服务器上共同完成一项任务(如开发一套应用软件)。下面介绍如何实现用户间文件的共享。假设这个团队的成员在服务器上的用户名分别是zll、fjn,它们都属于workgroup这个用户组,可以用以下的命令模拟这个场景。


首先在/home目录下建立一个名为work 的目录,作为这个小组的工作目录,注意需要root权限。


现在,任何人都可以访问这个新建的目录,而只有root用户才拥有该目录的写权限。现在希望让 workgroup组的成员拥有这个目录的读写权限,并禁止其他无关的用户查看这个目录。



接下来需要将这个目录交给一个组长zll(现在 work目录的所有者还是root 用户)。


现在,所有属于这个组的成员都可以访问并修改这个目录中的内容了,而其他未经授权的用户(除了root)则无法看到其中的内容。举例来说,zll在/home/work目录下新建了一个名为test的空文件,那么同属一个组的用户fjn 如果认为这个文件没有必要,可以有权限删除它。

3.建立文件和目录

本节将介绍如何在Linux中建立文件和目录,这是文件和目录管理的第一步。

建立目录:mkdir

mkdir命令可以一次建立一个或几个目录。下面的命令在用户主目录下建立document、picture两个目录。


用户也可以使用绝对路径来新建目录。


相信大家创建的时候会报这个错误,这是因为当前在用户主目录下并没有test这个目录,自然也无法在 test下创建job目录了。为此mkdir提供了-p选项,用于完整地创建一个子目录结构。


在这个例子中,mkdir会首先创建test目录,然后创建job。在需要创建一个完整目录结构的时候,这个选项是非常有用的。

建立一个空文件:touch

touch命令的使用非常简单,只需要在后面跟上一个文件名作为参数。下面这个命令在当前目录下新建一个名为hello的文件。


用touch命令建立的文件是空文件(也就是不包含任何内容的文件)。空文件对建立某些特定的实验环境是有用。另外,当某些应用程序因为缺少文件而无法启动,而这个文件实际上并不那么重要时,可以建立一个空文件暂时“骗过”这个程序。


用touch命令建立的文件是空文件(也就是不包含任何内容的文件)。空文件对建立某些特定的实验环境是有用。另外,当某些应用程序因为缺少文件而无法启动,而这个文件实际上并不那么重要时,可以建立一个空文件暂时“骗过”这个程序。


touch命令的另一个用途是更新一个文件的建立日期和时间。例如,对于hello这个文件,使用ls-1命令显示这个文件的建立时间为11点43分。


使用touch命令更新后,建立时间变成了当前时间。


touch命令的这个功能在自动备份和整理文件时非常有用,这使得程序可以决定哪些文件已经被备份或整理过了。关于文件备份,可持续后续文章。

4.移动 复制和删除

通过上述的学习小伙伴们已经能够创建文件和目录。本节将继续讨论如何移动、复制和删除文件及目录,这是在文件和目录管理中另一个基本操作。下面首先从移动文件开始讨论。

移动和重命名:mv

mv取了move 的缩写形式。这个命令可以用来移动文件。下面这条命令将hello文件移动到bin目录下。


当然也可以移动目录。下面这条命令把 Photos目录移动到/home目录下。


Linux没有“重命名”这个命令,原因很简单,即没有这个必要。重命名无非就是将一个文件在同一个目录里移动,这是mv最擅长的工作。


因此对mv 比较准确的描述是,mv可以在移动文件和目录的同时对其重命名。

复制文件和目录:cp

cp命令用来复制文件和目录。下面这条命令将文件test复制到/home目录下。


cp命令在执行复制任务的时候会自动跳过目录。为此,可以使用-r选项。这个选项将子目录连同其中的文件一起复制到另一个子目录下。


删除目录和文件:rmdir和rm

rmdir命令用于删除目录。这个命令的使用非常简单,只需要在后面跟上要删除的目录名作为参数即可。


但是rmdir命令只能删除空目录,删除有内容的目录会提示错误。


因此,在使用rmdir 删除一个目录之前,首先要将这个目录下的文件和子目录删除。删除文件需要用到rm命令。稍后将会看到,rm同样可以用来删除目录,而且比 rmdir更为“高效”。由于这个原因,在实际使用中rmdir很少被用到。


rm命令可以一次删除一个或几个文件。下面这条命令可以搭配通配符使用删除Ptest目录下所有的所有文件。值得注意的是删除较多的文件避免一一确认可以使用下面选项,进行操作。


符号 作用

-i 删除前逐一询问确认。

-f 即使原档案属性设为唯读,亦直接删除,无需逐一确认。

-r 将目录及以下之档案亦逐一删除。


注意:使用rm命令的时候应该格外小心,特别是以 root身份执行该命令时。


5.文件和目录的权限

很难想像没有权限的世界会变成什么样子。随便哪个用户都可以大摇大摆地“溜”进别人的目录,然后对里面的文件乱改一气。当然,他自己的文件也可能正经历着同样的命运。Linux是一个多用户的操作系统,正确地设置文件权限非常重要。

权限设置针对的用户

Linux 为3种人准备了权限——文件所有者(属主)、文件属组用户和其他人。因为有了“其他人”,这样的分类将世界上所有的人都包含进来了。但读者应该已经敏感地意识到,root用户其实是不应该被算在“其他人”里面的。root 用户可以查看、修改、删除所有人的文件——不要忘了root拥有控制一台计算机的完整权限。


文件所有者通常是文件的创建者,但这也不是一定的。可以中途改变一个文件的属主用户,这必须直接由root用户来实施。这句话换一种说法或许更贴切:文件的创建者自动成为文件所有者(属主),文件的所有权可以转让,转让“手续”必须由root 用户办理。


可以(也必须)把文件交给一个组,这个组就是文件的属组。组是一群用户组成的一个集合,类似于学校里的一个班、公司里的一个部门……文件属组中的用户按照设置对该文件享有特定的权限。通常来说,当某个用户(如zll)建立一个文件时,这个文件的属主就是zll,文件的属组是只包含一个用户zll的zll 组。当然,也可以设置文件的属组是一个不包括文件所有者的组,在文件所有者执行文件操作时,系统只关心属主权限,而组权限对属主是没有影响的。


提示:关于用户和用户组的概念,在后面文章会进行详细讲解


最后,“其他人”就是不包括前两类人和root 用户在内的“其他”用户。通常来说,“其他人”总是享有最低的权限(或者干脆没有权限)。

需要设置那些权限

可以赋予某类用户对文件和目录享有3种权限:读取(r)、写入(w 和执行(x)。对于文件而言,拥有读取权限意味着可以打开并查看文件的内容,写入位控制着对文件的修改权限。而是否能够删除和重命名一个文件则是由其父目录的权限设置所控制的。


要让一个文件可执行,必须设置其执行权限。可执行文件有两类,一类是可以直接由CPU执行的二进制代码;另一类是Shell脚本程序。


对目录而言,所谓的执行权限实际控制了用户能否进入该目录;而读取权限则负责确定能否列出该目录中的内容;写入权限控制着在目录中创建、删除和重命名文件。因此目录的执行权限是其最基本的权限。


查看文件和目录的属性

使用带选项-1的ls命令可以查看一个文件的属性,包括权限。首先来看一个例子:


这条命令列出了/bin/login文件的主要属性信息。下面逐段分析这一行字符串所代表的含义。

第1个字段的第1个字符表示文件类型,在上例中是-,表示这是一个普通文件。

接下来的rwxr-xr-X就是3组权限位。这9个字符应该被这样断句:rwX、r-X、T-X,分别表示属主、属组和其他人所拥有的权限。r表示可读取,w表示可写,x表示可执行。如果某个权限被禁用,那么就用一个短划线-代替。在这个例子中,属主拥有读、写和执行权限,属组和其他人拥有读和执行权限。

第3个和第4个字段分别表示文件的属主和属组。在这个例子中,login 文件的属主是root 用户,而属组是root组。

紧跟着3组权限位的数字表示该文件的链接数目。这里是1,表示该文件只有一个

最后的4个字段分别表示文件大小(37208字节)、最后修改的日期,以及这个文件的完整路径(/bin/login)。

最后,不带文件名作为参数的ls-1命令列出当前目录下所有文件(不包括隐藏文件)的属性。


改变文件所有权:chown和chgrp

chown命令用于改变文件的所有权。chown命令的基本语法如下:

sudo [OPTION]... [OWNER][:[GROUP]] FILE...


这命令将文件FILE的属主更改为OWNER,属组更改为GROUP。下面这条命令将文件 test的属主更改为zll,而把其属组更改为root组。


如果只需要更改文件的属主,那么可以省略参数 GROUP 。下面这条命令把 test文件的属主更改为fjn用户,而保留其属组设置。


相应地,可以省略参数OWNER,而只改变文件的属组。注意,不能省略组名GROUP前的那个冒号:。下面这条命令把 test 文件的属组更改为 fjn 组,而保留其属主设置。


Linux单独提供了另一个命令chgrp用于设置文件的属组。下面这条命令将文件 test的属组设置为workgroup组。


chgrp命令实际上只是实现了chown 的一部分功能,但这个命令至少在名字上更直观地告诉人们它要干什么。在实际工作中,是否使用chgrp仅仅是个人习惯的问题。

改变文件权限:chmod

chmod用于改变一个文件的权限。这个命令使用“用户组+/-权限”的表述方式来增加/删除相应的权限。具体来说,用户组包括了文件属主(u)、文件属组(g)、其他人(o)和所有人(a),而权限则包括了读取(r)、写入(w)和执行(x)。例如,下面这条命令增加了属主对文件test的执行权限。

chmod u+x test


chmod可以用a同时指定所有的3种人。下面这条命令删除所有人(属主、属组和其他人)对test的执行权限。

chmod a-x test


还可以通过“用户组=权限”的规则直接设置文件权限。同样应用于文件 test,下面这条命令赋予属主和属组的读取/写入权限,而仅赋予其他用户读取权限。

chmod ug=rw,o=r test


最后一条常用规则是“用户组1=用户组2”,用于将用户组1的权限和用户组2的权限设为完全相同。应用于文件test中,下面这条命令将其他人的权限设置为和属主的权限一样。

chmod o=u test


注意:只有文件的属主和root用户才有权修改文件的权限。


文件权限的八进制表示

chmod的助记符尽管意义明确,但有些时候显得太啰嗦了。系统管理员更喜欢用chmod的八进制语法来修改文件权限——这样就可以不用麻烦左右手的小指了。为此,管理员至少应该熟练掌握8以内的加法运算——能口算是最好的。


首先简单介绍一下八进制记法的来历。每一组权限rwx在计算机中实际上占用了3位,每一位都有两种情况。例如对于写入位,只有“设置(r)”和没有设置(-)两种情况。这样计算机就可以使用二进制0和1来表示每一个权限位,其中0表示没有设置,而1表示设置。例如rwx就被表示为111,“-w-”表示为010等。


由于3位二进制数对应于1位八进制数,因此可以进一步用一个八进制数字来表示一组权限。下方图片显示了八进制、二进制、文件权限之间的对应关系。




不必记住上面所有这些数字的排列组合。在实际使用中,只要记住1代表x,2代表w,4代表r,然后简单地做加法就可以了。举例来说,rwx =4+2+1=7,r-x =4+0+1=5。这样一来,完整的9位权限位就可以用3个八进制数表示了,例如“rwxr-X–x”就对应于“751”。下面这条命令将文件 test 的所有权限赋予属主,而属组用户和其他人仅有执行权限:



6.文件类型

小伙伴们很快会意识到,Linux中的一切都被表示成文件的形式。这包括程序进程、硬件设备、通信通道甚至是内核数据结构等。这种设置给很多人带来了理解上的困难——除了Linux程序员,因为这给他们带来了一致的编程接口。Linux中一共有7种文件类型,下面简要介绍阅读文件类型的方法,并着重介绍一下符号链接。

查看文件类型

使用带 -l 选项的 ls命令可以查看文件类型。



命令显示的第1个字符就是文件类型。在上面这个例子中,days文件夹中的所有文件都是普通文件所有使用-来表示。


Linux中的文件类型




正如大家已经知道的那样,Linux用设备文件来标识一个特定的硬件设备。Linux中有两类设备文件:字符设备文件和块设备文件。字符设备指的是能够从它那里读取成字符序列的设备,如磁带和串行线路;块设备指的是用来存储数据并对其各部分内容提供同等访问权的设备,如磁盘。和字符设备有时又被称为顺序访问设备一样,块设备有时也被称为随机访问设备。顾名思义,使用块设备,可以从硬盘的任何随机位置获取数据;而使用字符设备则必须按照数据发送的顺序从串行线路上获取。


拥有某个设备文件并不意味着一定有一个相对应的硬件设备存在,这只是表明 Linux有处理这种设备的“潜能”。设备文件可以用mknod命令来创建,对这个命令的讨论已经超出了这篇文章的范围。


本地域套接口和有名管道都是有关进程间通信的。Linux 程序员需要了解这些内容,普通用户可能永远也不会接触这两个东西。


符号链接有点像Windows里的快捷方式,用户可以通过别名去访问另一个文件。


建立链接:ln

符号链接(也被称作“软连接”)需要使用带-s参数的ln命令来创建。下面是这个命令最简单的形式,这条命令给目标文件test 取了一个别名my_test。如下:


下面的例子具体说明了符号链接的作用。



从my_test的属性中可以看到,这个文件被指向test。从此访问my_test就相当于访问test。例如:


修改my_test的内容


查看test内容


my_test只是文件 test的一个“别名”,因此删除my_test并不会影响到test。但如果把 test删除了,那么my_test虽然还保留在那里,但已经没有任何意义了。


符号链接还可用于目录,下面这条命令建立了一个指向/usr/local/share 的符号链接local_share。


查看local_share的属性的确可以看到这一点。


Linux 在中还有一种链接被称为“硬链接”。这种链接用于将两个独立的文件联系在一起。硬链接和符号链接本质的不同在于:硬链接是直接引用,而符号链接是通过名称进行引用。使用不带选项的ln命令建立硬链接。



上面这条命令建立了一个链接到days 的新文件hard_days。查看两者的属性可以看到,这是两个完全独立的文件,只是被联系在一起了而已。



这两个文件拥有相同的内容,对其中一个文件的改动会反映在另一个文件中。用熟悉的文本编辑器打开test,添加一个a,可以看到 my_test中的内容也改变了。



在实际工作中,人们更多地选择使用符号连接(软连接),硬链接已经很少使用。


7.输入输出重定向和管道

重定向和管道是 Shell 的一种高级特性,这种特性允许用户人为地改变程序获取输入和产生输出的位置。这个有趣的功能并不是 Linux的专利,几乎所有的操作系统(包括Windows)都能支持这样的操作。

输出重定向

程序在默认情况下输出结果的地方被称为标准输出(stdout)。通常来说,标准输出总是指向显示器。例如,下面的ls命令获取当前目录下的文件列表,并将其输出到标准输出,于是用户在屏幕上看到了这些文件名。


输出重定向用于把程序的输出转移到另一个地方去。下面这条命令将ls 的输出重定向到ls_out文件中。


这样,ls的输出就不会在显示器上显示出来,而是出现在用户主目录的ls_out文件中,每一行显示一个文件名。


注意:如果ls_out文件不存在,那么输出重定向符号“>”会试图建立这个文件。如果 ls_out 文件已经存在了,那么“>”会删除文件中原有的内容,然后用新内容替代。


可以看到,“>”并不会礼貌地在原来那堆文件名的后面添上版本信息,而是直接覆盖了。如果要保留原来文件中的内容,应该使用输出重定向符号“>>”。


输入重定向

和标准输出类似,程序默认情况下接收输入的地方被称为标准输入( stdin)。通常来说,标准输入总是指向键盘。例如,如果使用不带任何参数的cat命令,那么 cat会停在那里,等待从标准输入(也就是键盘)获取数据。

cat


用户的每一行输入会立即显示在屏幕上,直到使用Ctrl+D快捷键提供给cat命令一个文件结束符。


通过使用输入重定向符号“<”可以让程序从一个文件中获取输入。


上面这条命令将文件 test作为输入传递给cat命令,cat读取 test中的每一行,然后输出读到的内容。最后当cat遇到文件结束符时,就停止读取操作。整个过程同先前完全一致。


正如大家已经想到的,cat命令可以通过接受一个参数来显示文件内容,因此“cat <test”完全可以用cat test来替代。事实上,大部分命令都能够以参数的形式在命令行上指定输入档的文件名,因此输入重定向并不经常使用。


另一种输入重定向的例子被称为立即文档((here document))。这种重定向方式使用操作符“<<”。立即文档明确告诉Shell从键盘接受输入,并传递给程序。现在看下面这个例子:


cat命令从键盘接受两行输入,并将其送往标准输出。和本节开头的例子不同的是,立即文档指定了一个代表输入结束的分隔符 (在这里是单词EOF),当Shell 遇到这个单词的时候,即认为输入结束,并把刚才的键盘输入一起传递给命令。所以这次 cat命令会将用户的输入一块显示,而不是每收到一行就迫不及待地把它打印出来。


用户可以选择任意一个单词作为立即文档的分隔符,像 EOF、END、eof 等都是不错的选择,只要可以确保它不是正文的一部分。


那么,是否可以让输入重定向和输出重定向结合在一起使用?这听起来是一个不错的主意。


这条命令首先让 cat命令以立即文档的方式获取输入,然后再把 cat 的输出重定向到hello文件。查看hello文件,应该可以看到下面这些内容:


管道

管道将“重定向”再向前推进了一步。通过一根竖线“I”,将一条命令的输出连接到另一条命令输入。下面这条命令显示了如何在文件列表中查找文件名中包含某个特定字符串的文件。


ls首先列出当前目录下的所有文件名,管道“I”接收到这些输出,并把它们发送给grep命令作为其输入。最后grep在这堆文件列表中查找包含字符串hello的文件名,并在标准输出(也就是显示器)显示。


可以在一行命令中使用多个管道,从而构造出复杂的Shell 命令。最初这些命令可能看起来晦涩难懂,但它们的确很高效。合理使用管道是提高工作效率的有效手段,随着使用的深入,大家会逐渐意识到这一点。


三.软件包管理

RPM(RedHat Package Manager),RedHat软件包管理工具,类似windows里面的setup.exe。是Linux这系列操作系统里面的打包安装工具,它虽然是RedHat的标志,但理念是通用的。

1.rmp包的由来

软件包的最原始的 形式肯定是源码的形式,rmp包是把别人写好的源码包编译好了存放成rpm这种格式了,这样做有什么好处能,下次你要安装的时候直接安装rpm包就行,不用去重新编码源码包了。那么通常都是谁来做源码包转换成rpm包这个工作呢,一般都是各Linux发行版的官方,例如CentOS的官方,Redhat的官方,他们去把一些运行比较稳定的,bug比较少的源码包给你编译成二进制形式的rpm包,以后有人要想使用这个软件的时候,直接安装rpm包就可以了。


我们经常看到官方发行的rpm版本都会比最新的源码包的版本滞后,为什么会滞后,因为官方都图稳定,他们会把一些稳定的发布到自己的平台上。如果你要使用最新最强大的功能,你只能去找源码包,但是需要注意的是,最新的源码包可能有许多bug。其实你自己也可以把源码包转化成rpm包。


我们可以通过命令查看系统虚拟光盘中的rpm包


[root@localhost ~]# ls /run/media/root/CentOS\ 7\ x86_64/Packages/


2.操作rmp包

rmp包的命名格式 : Apache-1.3.23-11.i386.rpm


“apache” 软件名称

“1.3.23-11”软件的版本号,主版本和此版本

“i386”是软件所运行的硬件平台,Intel 32位微处理器的统称

“rpm”文件扩展名,代表RPM包

查询所安装的所有rpm软件包

rpm -qa


由于软件包比较多,一般都会通过上面学到的 | 符进行过滤。比如我们想查询firefox软件的安装情况。


rpm安装命令

rpm -ivh RPM包全名


选项说明


选项 功能

-i install,安装

-v verbose,显示详细信息

-h hash,进度条

–nodeps 不检测依赖进度

安装firefox软件


安装完成后我们上客户端看看


rpm卸载命令

rpm -e RPM软件包


选项说明


选项 说明

-e 卸载软件包

–nodeps 卸载软件时,不检查依赖。这样的话,那些使用该软件包的软件在此之后可能就不能正常工作了。

卸载firefox软件


我们再来看一下我们的客户端


3.什么是yum

Yum是使用RPM软件包管理器的Linux操作系统的免费开放源代码命令行软件包管理应用程序。Yum是rpm的前端工具,可自动解决软件包的依赖性。它从发行官方存储库和其他第三方存储库安装RPM软件包。Yum允许您从系统中安装、更新、搜索和删除软件包。如果您想使系统保持最新,则可以通过yum-cron启用自动更新。此外,如果需要,它还允许您从yum更新中排除一个或多个软件包。默认情况下已安装Yum,您无需安装它。

4.yum和rpm的区别在哪里

RPM YUM

红帽于1997年推出了RPM Yellowdog UPdater(YUP)于1999-2001年开发,YUM在2003年取代了原始的YUP实用程序

RPM代表RPM软件包管理器(以前称为Red Hat软件包管理器) YUM代表经过修改的Yellowdog Updater

RPM文件命名约定:httpd-2.4.6-92.el7.x86_64.rpm,即:httpd-实际软件包的名称,2.4.6-软件包发行版本,92-Subversion包发行版,el7-红帽版,x86_64-硬件架构,rpm-文件扩展名 它在后端使用rpm数据库

它不能解决依赖关系,您必须手动安装它们 它会自动解决依赖关系并同时安装它们(任何软件包都将与其依赖关系一起安装)

这使您可以一次安装该软件包的多个版本 这不允许并且表明该软件包已经安装

使用RPM命令安装软件包时,必须提供“.rpm”软件包的确切位置 您可以安装存储库中可用的任何软件包,但只需要知道软件包名称

RPM不依赖YUM 它是一个前端工具,使用后端上的RPM软件包管理器来管理软件包

在软件包安装方面很难管理RPM YUM是管理RPM软件包的最简单方法

RPM不允许您将整个系统升级到最新的可用版本 YUM允许您将系统升级到最新的可用版本(次要版本升级,例如7.0到7.x)

RPM不允许您自动更新/升级系统上安装的软件包 YUM允许您自动更新/升级系统上可用的更新

它不使用在线存储库执行任何操作 它完全依靠在线存储库来完成所有工作

RPM是一种软件包格式,它是执行基本操作的低级软件包管理器 这是一个顶级的前端程序包管理工具,可以完成您需要的一切

5.yum仓库配置

默认的系统YUM源,需要连接国外apache网站,网速比较慢,可以修改关联的网络YUM源为国内镜像的网站,比如网易163。


配置国内源

访问该网络地址:http://mirrors.163.com/.help/centos.html,在使用说明中点击CentOS6,再点击保存


通过Xshell工具把下载的文件上传至指定的安装位置(直接拉进来就上传完成了)。


把下载的文件移动到/etc/yum.repos.d/目录


备份CentOS-Base.rep并用CentOS6-Base-163.repo替换CentOS-Base.rep(这里备份就重新命名了,替换就是直接改为原文件名称)


清理旧缓存数据,缓存新数据。

yum clean all


yum makecache


安装测试


yum -y install firefox.x86_6


6.压缩工具

经过压缩后的文件能够占用更少的磁盘空间。现在几乎所有的计算机用户都懂得使用压缩工具,尽管在大部分情况下是为了“打包”而不是“压缩”。在 Linux 的世界里,有太多的源代码需要压缩,读者将会看到这些压缩工具的确非常有用。

压缩文件:gzip

gzip是目前Linux下使用最广泛的压缩工具,尽管它的地位正持续受到bzip2的威胁。gzip 的使用非常方便,只要简单地在 gzip命令后跟上一个想要压缩的文件作为参数就可以了。

gzip 文件名


在默认情况下,gzip命令会给被压缩的文件加上一个“gz”扩展名。经过这番处理后,文件badpro就变成了badpro.gz。


提示:“.tar.gz”可能是 Linux世界中最流行的压缩文件格式。这种格式的文件是首先经过tar打包程序的处理,然后用gzip压缩的成果。


要解压缩.gz文件,可以使用gunzip命令或者带“-d”选项的gzip命令。


gunzip 文件名


或者


gzip -d 文件名


应该保证需要解压的文件有合适的扩展名。gzip(或者gunzip)支持的扩展名有.gz、.Z、-gZ、.Z、-z和z。


gzip提供了-1选项用于查看压缩效果,文件的大小以字节为单位。


可以看到,文件badpro在压缩前后的大小分别为158字节(约几kb),压缩率为30.4%。


最后,gzip命令的-t选项可以用来测试压缩文件的完整性。如果文件正常,gzip命令不会给出任何显示。如果一定要让gzip 说点什么,可以使用-tv选项。

更高的压缩率:bzip2

bzip2可以提供比 gzip更高的压缩率,当然这是以压缩速度为代价的。不过伴随着摩尔定律惊人的持续性,这种速度上的劣势将变得越来越难以察觉。bzip2以及类似的压缩算法也因此流行起来。


bzip2的使用方法同gzip基本一致。


bzip2 文件名

解压缩.bz2文件可以使用bunzip2或者带-d选项的bzip2命令:

或者

bzip2 -d 文件名

bzip2可以识别的压缩文件格式包括.bz2、.bz、.tbz2、.tbz和 bzip2。如果使用bzip2压缩的文件不幸被改成了其他名字,那么经过解压缩的文件名后面会多出一个“.out”作为扩展名。


同样可以使用-tv选项检查压缩文件的完整性。


bzip2 -tv 文件名

支持rar格式

rar俨然已经取代zip成为 Windows下的标准压缩格式。尽管rar相比较zip最大的优势在于其更好的压缩效果,但Windows用户通常只是简单地把它作为打包工具。在Linux下处理rar文件可以使用RAR for linux。这是一个命令行工具,可以从 www.rarlab.com/download.htm 上下载。


要解压一个文件,只要简单地使用命令rar和选项x。


rar x 文件名

四.用户与用户组管理

本章介绍Linux 上用户和用户组的管理。作为一种多用户的操作系统,Linux 可以允许多个用户同时登录到系统上,并响应每一个用户的请求。对于系统管理员而言,一个非常重要的工作就是对用户账户进行管理。这些工作包括添加和删除用户、分配用户主目录、限制用户的权限等。接下来将逐一讨论这些方面。


计算机科学还没有进展到让每一台电脑都能通过生物学特征识别人的程度。在绝大多数情况下,用户名是身份的唯一标志,计算机通过用户提供的口令来验证这一标志。这种简单而实用的方式被广泛应用于几乎所有的计算机系统中。遗憾的是,也是由于这种“简单”的验证方式,使得在世界各地,每一天都有无数的账号被盗取。因此选择一个合适的用户名和一个不易被破解的密码非常重要。


Linux也运用同样的方法来识别用户:用户提供用户名和密码,经过验证后登录到系统。Linux会为每一个用户启动一个进程,然后由这个进程接受用户的各种请求。在建立用户的时候,需要限定其权限,例如不能修改系统配置文件,不能查看其他用户的目录等。就像在一个银行安全系统中,每一个人只能处理其职权范围内的事情。另外,系统中有一个特殊的root 用户,这个用户有权对系统进行任何操作而不受限制。


所谓“人以群分”,可以把几个用户归在一起,这样的组被称为“用户组”。可以设定一个用户组的权限,这样这个组里的用户就自动拥有了这些权限。对于一个多人协作的项目而言,定义一个包含项目成员的组往往是非常有用的。


在某些服务器程序安装时,会生成一些特定的用户和用户组,用于对服务器进行管理。例如,可以使用mysql用户启动和停止MySQL服务器。之所以不使用root用户启动某些服务,主要是出于安全性的考虑。因为当某个运行中进程的UID属于一个受限用户的话,那么即使这个进程出了什么问题,也不会对系统安全产生毁灭性打击。


1.为朋友 John 添加账户

fjn的笔记本送去维修了,希望借台电脑用几天。但是电脑上有一些私人文件,或许不应该让John看到。因此应该为fjn单独添加一个账户,而不是使用当前系统上

已有的账户。


打开终端,输入:


注意,在输入口令的时候,出于安全考虑,屏幕上并不会有任何显示(包括“*”号)。现在,应该把John叫过来,让他自己输入一个密码。


现在,John可以使用自己的账号登录到系统了。只要将私人文件设置为他人不可读,那么就不用担心John会查看到这些文件。

2.添加用户

添加用户是系统管理的例行工作,在文章开头大家已经实践了添加用户的基本步骤。接下来将详细讨论useradd和groupadd命令的各个常用选项,以及如何追踪用户状态。

使用命令行工具:useradd 和 groupadd

在默认情况下,不带-m参数的useradd命令不会为新用户建立主目录。在这种情况下,用户可以登录到系统的Shell,但不能够登录到图形界面。这是因为桌面环境无论是 KDE还是GNOME,需要用到用户主目录中的一些配置文件。例如,以下面的方式使用useradd命令添加一个用户nox。

useradd nox

passwd nox



当使用nox用户账号登录GNOME 时,系统会提示无法找到用户主目录,并拒绝登录。如果在字符界面的2号控制台(可以使用快捷键Ctrl+Alt+F2进入)使用nox账号登录,系统会引导nox用户进入根目录。此后,用户可以继续操作.


useradd命令中另一个比较常用的参数是-g。该参数用于指定用户所属的组。下面这条命令建立名为mike的用户账号,并指定其属于users组。


useradd -g users mike


在用户建立的时候为其指定一个组看上去是一个很不错的想法。但遗憾的是,这样的设置增加了用户由于不经意地设置权限而能够彼此读取文件的可能性,尽管这通常不是用户的本意。因此一个好的建议是,在新建用户的时候用户单独创建一个同名的用户组,然后把用户归入这个组中。这正是不带-g 参数的useradd命令的默认行为。


useradd 的-s参数用于指定用户登录后所使用的Shell。下面的命令建立名为mike的用户账号,并指定其登录后使用bash 作为Shell。


useradd -s /bin/bash mike


可以在/bin目录下找到特定的Shell。常用的有BASH、TCSH、ZSH (Z-Shell) 、SH(Bourne Shell)等。如果不指定-s 参数,那么默认将使用sh(在大部分系统中,这是指向BASH的符号链接)登录系统。


添加组可以使用groupadd命令,下面这条命令在系统中添加一个名为newgroup 的组。


groupadd newgroup


记录用户操作:history

Linux,准确地说是Shell,会记录用户的每一条命令。通过history命令,用户可以看到自己曾经执行的操作。


注意: history命令仅在 BASH中适用。


history会列出所有使用过的命令并加以编号。这些信息被存储在用户主目录的.bash_history文件中,这个文件默认情况下可以存储1000条命令记录。当然,一次列出那么多命令除了让人迷茫外,没有其他什么用途。为此,可以指定让history列出最近几次输入的命令。


但是,history只能列出当前用户的操作记录。对于管理员而言,有时候需要查看其他用户的操作记录,此时可以读取该用户主目录下的.bash_history文件。现在看看john都干了些什么。


注意:.bash_history这个文件对于其他受限用户是不可读的。


直接编辑 passwd 和 shadow文件

在Linux 中所做的一切基本配置最终都将反映到配置文件中,用户管理也不例外。所有的用户信息都登记在/etc/passwd文件中,而/etc/shadow文件则保存着用户的登录密码。


诸如useradd这样的工具实际上对用户隐藏了用户管理的细节。可以通过手动编辑passwd和 shadow这两个文件实现 useradd 等工具的所有功能。其中,passwd文件对所有用户可读,而 shadow则只能用root账号查看。为了保证口令的安全性,这一点很容易理解。当然,修改这两个文件都需要root权限。


3.删除用户:userdel

userdel命令用于删除用户账号。下面这条命令删除mike这个账号。



可以看到 在默认情况下,userdel并不会删除用户的主目录。除非使用了-r选项。下面这条命令将john的账号删除,同时删除其主目录。


在删除用户的同时删除其主目录,以释放硬盘空间,这看起来无可厚非。但是,在输入-r选项之前,仍然有一个问题需要问问自己:需要这么着急吗?如果被删除的用户又要恢复,或者用户的某些文件还需要使用(这样的情况在服务器上经常出现)那么有必要暂时保留这些文件。比较妥当的方法是,将被删用户的主目录保留几周,然后再手动删除。在实际的工作环境中,这个做法显得尤为重要。

4.管理用户账号:usermod

可以使用usermod 命令来修改已有的用户账号。这个命令有多个不同的选项,对应于账号的各个属性。如表9.1列举了usermod命令的各个常用选项及其含义。

选项 含义

-d 修改用户主目录

-e 修改账号的有效期限,以公元月/日/年的形式表示(MM/DD/YY)

-g 修改用户所属组

-l 修改用户账号名称

-s 修改用户登陆后所使用的Shell

下面这条命令将zll改名为mike2,主目录改为/home/mike2,并设置账号有效期至2022年12月31日。


和 useradd的原理一样,usermod也通过修改/etc/passwd、/etc/shadow和/etc/group这3个文件来实现用户属性的设置。

5.查看用户信息:id

id命令用于查看用户的UID、GID及其所属的组。这个命令以用户名作为参数,下面这条命令显示了nobody用户的UID、GID及其属于的组信息。


使用不带任何参数的id命令显示当前登录用户的信息。


6.用户间切换:su

前面文章中曾经介绍过,使用root账号一个比较好的做法是使用su 命令。不带任何参数的su命令会将用户提升至root权限,当然首先需要提供root 口令。通过su命令所获得的特权将一直持续到使用exit命令退出为止。


也可以使用su命令切换到其他用户。下面这个命令将当前身份转变为mzc。


系统会要求输入mzc口令。通过验证后,就可以访问mzc账号了。通过 exit 命令回到之前的账号。


安全性提示:尽量通过绝对路径使用su命令,这个命令通常保存在/bin目录下。这将在一定程度上防止溜入到搜索路径下的名为su的程序窃取用户口令。


五.进程管理

无论是系统管理员还是普通用户,监视系统进程的运行情况,并适时终止一些失控的进程是每天的例行事务(读者或许对Windows的任务管理器非常熟悉)。系统管理员可能还要兼顾到任务的重要程度,并相应调整进程的优先级策略。无论是哪一种情况,本文都会有所帮助。本文的任务将完全在 Shell中完成。

1.结束一个失控的程序

终止一个失控的应用程序或许是用户最常使用的“进程管理”任务,尽管没有人愿意经常执行这样的“管理”。为了模拟这个情况,本节手动构建了一个程序。这个古老而有名的“恶作剧”程序在 Shell 中不停地创建目录和文件。如果不赶快终止,那么它将在系统中创建一棵很深的目录树。

#! /bin/bashwhile echo "I'm making files!!"do        mkdir adir        cd adir         touch afile                        sleep 5sdone

这是一个Shell脚本,现在并没有必要搞清楚其中的每一句话,后面文章会详细介绍Shell编程。如果读者曾经接触过一门编程语言,应该能够大致看出这个程序做了些什么。为了让这个恶作剧表现得尽可能“温和”,这里让它在每次建完目录和文件后休息5秒钟。


将这个文件加上可执行权限,并从后台执行。


注意:运行这个程序存在一些风险。千万不要漏了sleep 5s这一行,否则创建的目录树的深度会很快超出系统的允许范围。在这种情况下,读者可能必须要使用rm -fr adir 来删除这些“垃圾”目录。


为什么要从后台运行?原因只有一个,即迫使自己使用kill命令杀死这个进程。


现在程序已经运行起来了,可以看到它在终端不停地输出I’m making files!!。打开另一个终端,运行ps命令查看这个程序的PID号(PID号用于唯一表示一个进程)。


这里为了方便寻找,使用了管道配合grep命令。在ps命令的输出中,第2个字段就是进程的PID号。通过最后一个字段可以判断出 58250是属于这个失控进程。


使用 kill 命令“杀死这个进程”。


回到刚才那个运行badpro 的终端,可以看到这个程序已经被终止了。最后不要忘记把这个程序建立的目录和文件删除(当然,读者如果非常好奇,可以到这个目录中看一看)。


2.什么是进程

看似简单的概念往往很难给出定义,一个比较“正规”的说法是:进程是操作系统的一种抽象概念,用来表示正在运行的程序。其实,读者可以简单地把进程理解为正在运行的程序。Linux是一种多用户、多进程的操作系统。在 Linux的内核中,维护着一张表。这张表记录了当前系统中运行的所有进程的各种信息。Linux 内核会自动完成对进程的控制和调度——当然,这是所有操作系统都必须拥有的基本功能。内核中一些重要的进程信息如下:

进程的内存地址;

进程当前的状态;

进程正在使用的资源;

进程的优先级(谦让度);

进程的属主。

Linux提供了让用户可以对进程进行监视和控制的工具。在这方面,Linux对系统进程和用户进程一视同仁,使用户能够用一套工具控制这两种进程。

3.进程的属性

一个进程包含有多个属性参数。这些参数决定了进程被处理的先后顺序、能够访问的资源等。这些信息对于系统管理员和程序员都非常重要。下面讨论几个常用的参数,其中的一些参数大家可能已经有所接触了。

PID:进程的ID号

系统为每个用户都分配了用于标识其身份的ID号(UID)。同样地,进程也有这样一个D号,被称作PID。用ID确定进程的方法是非常有好处的——对于计算机而言,认识数字永远比认识一串字符方便得多,Linux没有必要去理解那些对人类非常“有意义”的进程名。


Linux 不仅自己使用PID来确定进程,还要求用户在管理进程时也提供相应的PID号。几乎所有的进程管理工具都接受PID号,而不是进程名。这也是为什么在“快速上手”环节中必需要使用ps命令获得PID号的原因。


PPID:父进程的PID

在Linux 中,所有的进程都必须由另一个进程创建——除了在系统引导时,由内核自主创建并安装的那几个进程。当一个进程被创建时,创建它的那个进程被称作父进程,而这个进程则相应地被称作子进程。子进程使用 PPID 指出谁是其“父亲”,很容易可以理解,PPID就等于其父进程的PID。


在刚才的叙述中,多次用到了“创建”这个词,这是出于表述和理解上的方便。事实上在 Linux中,进程是不能被“凭空”创建的。也就是说,Linux 并没有提供一种系统调用让应用程序“创建”一个进程。应用程序只能通过克隆自己来产生新进程。因此,子进程应该是其父进程的克隆体。这种说法听起来的确有点让人困惑,不过不要紧,这些概念只是对Linux程序员非常重要。大家如果对此感兴趣,可以参考Linux编程方面的书籍。


UID和 EUID:真实和有效的用户ID

只有进程的创建者和root用户才有权利对该进程进行操作。于是,记录一个进程的创建者(也就是属主)就显得非常必要。进程的UID就是其创建者的用户ID号,用于标识进程的属主。


Linux还为进程保存了一个“有效用户ID号”,被称作EUID。这个特殊的UID号用来确定进程对某些资源和文件的访问权限。在绝大部分情况下,进程的UID和EUID是一样的——除了著名的setuid程序。


什么是setuid程序?上文中的passwd命令,这个命令允许用户修改自己的登录口令。但读者是否考虑过这个问题:密码保存在/etc/shadow文件中,这个文件对普通用户是不可读的,那么用户怎么能够通过修改shadow文件来修改自己的口令呢?这就是setuid的妙处了,通过使passwd在执行阶段具有文件所有者(也就是root)的权限,让用户临时有了修改shadow文件的能力(当然这种能力是受到限制的)。因此,passwd就是一个典型的setuid程序,其UID是当前执行这个命令的用户ID,而EUID则是root用户的ID(也就是0)。


除此之外,Linux还给进程分配了其他几个UID,例如 saved UID和FSUID。这种多UID体系的设置非常耐人寻味,对它的解释超出了本文的范围,有兴趣的小伙伴们可以自己查阅相关资料。


谦让度和优先级

顾名思义,进程的优先级决定了其受到CPU“优待”的程度。优先级高的进程能够更早地被处理,并获得更多的处理器时间。Linux内核会综合考虑一个进程的各种因素来决定其优先级。这些因素包括进程已经消耗的CPU时间、进程已经等待的时间等。在绝大多数情况下,决定进程何时被处理是内核的事情,不需要用户插手。


用户可以通过设置进程的“谦让度”来影响内核的想法。“谦让度”和“优先级”刚好是一对相反的概念,高“谦让度”意味着低“优先级”,反之亦然。需要注意的是,进程管理工具让用户设置的总是“谦让度”,而不是“优先级”。如果希望让一个进程更早地被处理,那么应该把它的谦让度设置得低一些,使其变得不那么“谦让”。关于如何设置谦让度,参考后面文章。


4.监视进程:ps命令

ps是最常用的监视进程的命令。这个命令给出了有关进程的所有有用信息。在“快速上手”环节,读者已经使用了这个命令,本节将给出这个命令的详细解释。


ps命令有多种不同的使用方法,这常常给初学者带来困惑。在各种Linux 论坛上,询问ps命令语法的帖子屡见不鲜。之所以会出现这样的情况,只能归咎于UNIX“悠久”的历史和庞杂的派系。在不同的UNIX变体上,ps命令的语法各不相同。Linux为此采取了一个折中的处理方式,即融合各种不同的风格,目的只是为了兼顾那些已经习惯了其他系统上ps命令的用户(尽管这种兼顾现在看起来似乎越来越没有必要了))。


幸运的是,普通用户根本不需要理会这些,这是内核开发人员应该考虑的事情。在绝大多数情况下,只需要用一种方式使用ps命令就可以了。


ps aux命令用于显示当前系统上运行的所有进程的信息。出于篇幅考虑,这里只选取了部分行。

字段 含义

USER 进程创建者的用户名

PID 进程的ID号

%CPU 进程占用的CPU百分比

%MEM 进程占用的内存百分比

VSZ 进程占用的虚拟内存大小

RSS 内存中页的数量(页是管理内存的单位,在PC上通常为4K)

TTY 进程所在终端的ID号

STAT 进程状态,常用字母代表的含义如下:R 正在运行/可运行,D 睡眠中(不可被唤醒,通常是在等待I/O设备),S 睡眠中(可被唤醒),T 停止(由于收到信号或被跟踪),Z 僵进程(已经结束而没有释放系统资源的进程)常用的附加标志有:< 进程拥有比普通优先级高的优先级,N 进程拥有比普通优先级低的优先级,L 有些页面被锁在内存中 s 会话的先导进程

ps的另一组选项lax可以提供父进程ID(PPID)和谦让度(NI)。ps lax 命令不会显示进程属主的用户名,因此可以提供更快的运行速度(ps aux需要把UID转换为用户名后才输出)。


5.即时跟踪进程信息: top命令

ps命令可以一次性给出当前系统中进程信息的快照,但这样的信息往往缺乏时效性。当管理员需要实时监视进程运行情况时,就必须不停地执行ps命令——这显然是缺乏效率的。为此,Linux提供了top命令用于即时跟踪当前系统中进程的情况。


top命令显示的信息会占满一页,并且在默认情况下每10s更新一次。那些使用CPU最多的程序会排在最前面。用户还可以即时观察到当前系统CPU使用率、内存占有率等各种信息。最后,使用命令q退出这个监视程序。

6.查看占用文件的进程:lsof

管理员有时候想要知道某个特定的文件正被哪些进程使用。lsof命令能够提供包括PID在内的各种进程信息。不带任何参数的lsof命令会列出当前系统中所有打开文件的进程信息,要找出占用某个特定文件的进程,需要提供文件名作为参数。

lsof 文件名

7.向进程发送信号:kill

看起来,kill命令总是用来“杀死”一个进程。但事实上,这个名字或多或少带有一定的误导性。从本质上讲,kill命令只是用来向进程发送一个信号,至于这个信号是什么,则是由用户指定的。kill命令的标准语法如下:

kill [-signal] pid


Linux定义了几十种不同类型的信号。可以使用kill -1命令显示所有信号及其编号。根据硬件体系结构的不同,下面这张列表会有所不同。


千万不要被这一堆字符吓到,在绝大多数情况下,这些信号中的绝大多数不会被使用。

常用的信号


注意:信号名的前缀SIG是可以省略的。也就是说,SIGTERM和TERM这两种写法kill命令都可以理解。


在默认情况下,kill命令向进程发送TERM信号,这个信号表示请求终止某项操作。


请回忆在“结束一个失控的程序”环节中使用的命令kill 58250,这实际上等同于下面这条命令:


kill -TERM 58250

kill -SIGTERM 58250

但是,使用kill命令是否一定可以终止一个进程?答案是否定的。既然 kill 命令向程序“发送”一个信号,那么这个信号就应该能够被程序“捕捉”。程序可以“封锁”或者干脆“忽略”捕捉到的信号。只有在信号没有被程序捕捉的情况下,系统才会执行默认操作。作为例子,来看一下bc程序(一个基于命令行的计算器程序)。



Linux中,快捷键Ctrl+C对应于信号INT。在这个例子中,bc程序捕捉并忽略了这个信号,并告诉用户应该使用quit命令退出应用程序。


这就意味着,只要本章开头的那个badpro程序能够忽略TERM信号,那么kill -TERM命令将对它不起作用。加入这个“功能”非常容易,只要把程序改成下面这样就可以了。



#! /bin/bash
trap "" TERM

while echo "I'm making files!!"do mkdir adir cd adir touch afile sleep 5sdone



大家应该已经猜到了,这里新加入的命令“trap"" TERM”用于忽略TERM信号。建议大家在阅读完下一段之前先不要运行这个程序,否则将可能陷入无法终止它的尴尬境地。

幸运的是,有一个信号永远不能被程序所捕捉,这就是KILL信号。KILL可以在内核级别“杀死”一个进程,在绝大多数情况下,下面这条命令可以确保结束进程号为pid 的进程。

kill -KILL pid

kill -SIGKILL pid

kill -9 pid


然而,有一些进程的生命力是如此“顽强”,以至于KILL信号都不能影响到它们。这种情况常常是由一些退化的IO(输入/输出)虚假锁定造成的。此时,重新启动系统是解决问题的唯一方法。




相关资源