一、什么是Shell
shell 就是一个程序,它接受从键盘输入的命令, 然后把命令传递给操作系统去执行。
date— 显示系统当前时间和日期cal— 默认显示当前月份的日历df— 查看磁盘剩余空间的数量free— 显示空闲内存的数量
如果提示符的最后一个字符是“#”, 而不是“$”, 那么这个终端会话就有超级用户权限。 这意味着,我们要么是以 root 用户的身份登录,要么是我们选择的终端仿真器提供超级用户(管理员)权限。
[root@iZ8vb3yphb2x30z813n1xpZ ~]# date2020年 08月 15日 星期六 19:33:21 CST[root@iZ8vb3yphb2x30z813n1xpZ ~]# cal八月 2020日 一 二 三 四 五 六12 3 4 5 6 7 89 10 11 12 13 14 1516 17 18 19 20 21 2223 24 25 26 27 28 2930 31[root@iZ8vb3yphb2x30z813n1xpZ ~]# df文件系统 1K-块 已用 可用 已用% 挂载点devtmpfs 1929764 0 1929764 0% /devtmpfs 1940124 0 1940124 0% /dev/shmtmpfs 1940124 692 1939432 1% /runtmpfs 1940124 0 1940124 0% /sys/fs/cgroup/dev/vda1 41152812 7909484 31339620 21% /tmpfs 388028 0 388028 0% /run/user/0overlay 41152812 7909484 31339620 21% /var/lib/docker/overlay2/e6ee7c3df0c2e89dc8d3ccae7e331293f468781c9ebd853dff7243b390b299e0/mergedshm 65536 0 65536 0% /var/lib/docker/containers/a3f74fe49934aa6512550db2924e385bb72bf1009ec843434b2d95c787b30a02/shm[root@iZ8vb3yphb2x30z813n1xpZ ~]# freetotal used free shared buff/cache availableMem: 3880248 1527296 162476 692 2190476 2075040Swap: 0 0 0
二、在文件中跳转
pwd- Print name of current working directory 打印出当前工作目录名cd- Change directory 更改目录ls- List directory contents 列出目录内容 ```shell [root@iZ8vb3yphb2x30z813n1xpZ ~]# pwd /root
[root@iZ8vb3yphb2x30z813n1xpZ ~]# ls ALTER mysql80-community-release-el7-1.noarch.rpm temp.txt
<a name="63e44963"></a>
## 绝对路径
绝对路径开始于根目录,紧跟着目录树的一个个分支,一直到达所期望的目录或文件。 例如,你的系统中有一个目录,大多数系统程序都安装在这个目录下。这个目录的 路径名是 /usr/bin。它意味着从根目录(用开头的”/”表示)开始,有一个叫 “usr” 的 目录包含了目录 “bin”。
```shell
[me@linuxbox ~]$ cd /usr/bin
[me@linuxbox bin]$ pwd
/usr/bin
[me@linuxbox bin]$ ls
...Listing of many, many files ...
相对路径
绝对路径从根目录开始,直到它的目的地,而相对路径开始于工作目录。 为了做到这个(用相对路径表示), 我们在文件系统树中用一对特殊符号来表示相对位置。 这对特殊符号是 “.” (点) 和 “..” (点点)。
符号 “.” 指的是工作目录,”..” 指的是工作目录的父目录。下面的例子说明怎样使用它。 让我们再次把工作目录切换到 /usr/bin:
[me@linuxbox ~]$ cd /usr/bin
[me@linuxbox bin]$ pwd
/usr/bin
我们想更改工作目录到 /usr/bin 的父目录 /usr。可以通过两种方法来实现。可以使用以下绝对路径名:
[me@linuxbox bin]$ cd /usr
[me@linuxbox usr]$ pwd
/usr
或者, 也可以使用相对路径:
[me@linuxbox bin]$ cd ..
[me@linuxbox usr]$ pwd
/usr
/usr 进入 bin目录
[me@linuxbox usr]$ cd /usr/bin
或者
[me@linuxbox usr]$ cd ./bin
在几乎所有的情况下,你可以省略”./”。直接输入cd bin。
cd快捷键
| 快捷键 | 运行结果 |
|---|---|
| cd | 更改工作目录到你的家目录。 |
| cd - | 更改工作目录到先前的工作目录。 |
| cd ~user_name | 更改工作目录到用户家目录。例如, cd ~bob 会更改工作目录到用户“bob”的家目录。 |
三、探究操作系统
ls— List directory contents 列出目录内容file— Determine file type 确定文件类型less— View file contents 浏览文件内容
ls可能是最常用的命令了
除了当前工作目录以外,也可以指定别的目录,就像这样:
me@linuxbox ~]$ ls /usr
bin games kerberos libexec sbin src
etc include lib local share tmp
甚至可以列出多个指定目录的内容。在这个例子中,将会列出用户家目录(用字符“~”代表)和/usr 目录的内容:
[me@linuxbox ~]$ ls ~ /usr
/home/me:
Desktop Documents Music Pictures Public Templates Videos
/usr:
bin games kerberos libexec sbin src
etc include lib local share tmp
我们也可以改变输出格式,来得到更多的细节:
[me@linuxbox ~]$ ls -l
total 56
drwxrwxr-x 2 me me 4096 2007-10-26 17:20 Desktop
drwxrwxr-x 2 me me 4096 2007-10-26 17:20 Documents
drwxrwxr-x 2 me me 4096 2007-10-26 17:20 Music
drwxrwxr-x 2 me me 4096 2007-10-26 17:20 Pictures
drwxrwxr-x 2 me me 4096 2007-10-26 17:20 Public
drwxrwxr-x 2 me me 4096 2007-10-26 17:20 Templates
drwxrwxr-x 2 me me 4096 2007-10-26 17:20 Videos
选项和参数
我们将学习一个非常重要的知识点,即大多数命令是如何工作的。命令名经常会带有一个或多个用来更正命令行为的选项, 更进一步,选项后面会带有一个或多个参数,这些参数是命令作用的对象。所以大多数命令看起来像这样:
command -options arguments
大多数命令使用的选项,是由一个中划线加上一个字符组成,例如,“-l”,但是许多命令,包括来自于 GNU 项目的命令,也支持长选项,长选项由两个中划线加上一个字组成。当然, 许多命令也允许把多个短选项串在一起使用。下面这个例子,ls 命令有两个选项, “l” 选项产生长格式输出,“t”选项按文件修改时间的先后来排序。
[me@linuxbox ~]$ ls -lt
加上长选项 “–reverse”,则结果会以相反的顺序输出:
[me@linuxbox ~]$ ls -lt --reverse
ls 命令有大量的选项。表4-1列出了最常使用的选项。
表 4-1: ls 命令选项
| 选项 | 长选项 | 描述 |
|---|---|---|
| -a | —all | 列出所有文件,甚至包括文件名以圆点开头的默认会被隐藏的隐藏文件。 |
| -d | —directory | 通常,如果指定了目录名,ls 命令会列出这个目录中的内容,而不是目录本身。 把这个选项与 -l 选项结合使用,可以看到所指定目录的详细信息,而不是目录中的内容。 |
| -F | —classify | 这个选项会在每个所列出的名字后面加上一个指示符。例如,如果名字是 目录名,则会加上一个’/‘字符。 |
| -h | —human-readable | 当以长格式列出时,以人们可读的格式,而不是以字节数来显示文件的大小。 |
| -l | 以长格式显示结果。 | |
| -r | —reverse | 以相反的顺序来显示结果。通常,ls 命令的输出结果按照字母升序排列。 |
| -S | 命令输出结果按照文件大小来排序。 | |
| -t | 按照修改时间来排序。 |
深入研究长格式输出
正如我们先前知道的,“-l”选项导致 ls 的输出结果以长格式输出。这种格式包含大量的有用信息。下面的例子目录来自 于 Ubuntu 系统:
-rw-r--r-- 1 root root 3576296 2007-04-03 11:05 Experience ubuntu.ogg
-rw-r--r-- 1 root root 1186219 2007-04-03 11:05 kubuntu-leaflet.png
-rw-r--r-- 1 root root 47584 2007-04-03 11:05 logo-Edubuntu.png
-rw-r--r-- 1 root root 44355 2007-04-03 11:05 logo-Kubuntu.png
-rw-r--r-- 1 root root 34391 2007-04-03 11:05 logo-Ubuntu.png
-rw-r--r-- 1 root root 32059 2007-04-03 11:05 oo-cd-cover.odf
-rw-r--r-- 1 root root 159744 2007-04-03 11:05 oo-derivatives.doc
-rw-r--r-- 1 root root 27837 2007-04-03 11:05 oo-maxwell.odt
-rw-r--r-- 1 root root 98816 2007-04-03 11:05 oo-trig.xls
-rw-r--r-- 1 root root 453764 2007-04-03 11:05 oo-welcome.odt
-rw-r--r-- 1 root root 358374 2007-04-03 11:05 ubuntu Sax.ogg
表 4-2: ls 长格式列表的字段
| 字段 | 含义 |
|---|---|
| -rw-r—r— | 对于文件的访问权限。第一个字符指明文件类型。在不同类型之间, 开头的“-”说明是一个普通文件,“d”表明是一个目录。其后三个字符是文件所有者的 访问权限,再其后的三个字符是文件所属组中成员的访问权限,最后三个字符是其他所 有人的访问权限。这个字段的完整含义将在第十章讨论。 |
| 1 | 文件的硬链接数目。参考随后讨论的关于链接的内容。 |
| root | 文件所有者的用户名。 |
| root | 文件所属用户组的名字。 |
| 32059 | 以字节数表示的文件大小。 |
| 2007-04-03 11:05 | 上次修改文件的时间和日期。 |
| oo-cd-cover.odf | 文件名。 |
事实上,在类 Unix 操作系统中比如说 Linux 中,有个普遍的观念就是“一切皆文件”。
当调用 file 命令后,file 命令会打印出文件内容的简单描述
[root@iZ8vb3yphb2x30z813n1xpZ img]# file lzx.jpg
lzx.jpg: JPEG image data, EXIF standard
用 less 浏览文件内容
为什么我们要查看文本文件呢? 因为许多包含系统设置的文件(叫做配置文件),是以文本格式存储的,阅读它们 可以更深入的了解系统是如何工作的。另外,许多系统所用到的实际程序(叫做脚本)也是以这种格式存储的。 在随后的章节里,我们将要学习怎样编辑文本文件以修改系统设置,还要学习编写自己的脚本文件,但现在我们只是看看它们的内容而已。
less filename
一旦 less 程序运行起来,我们就能浏览文件内容了。如果文件内容多于一页,那么我们可以上下滚动文件。按下“q”键, 退出 less 程序。
表 4-3: less 命令
| 命令 | 行为 |
|---|---|
| Page UP or b | 向上翻滚一页 |
| Page Down or space | 向下翻滚一页 |
| UP Arrow | 向上翻滚一行 |
| Down Arrow | 向下翻滚一行 |
| G | 移动到最后一行 |
| 1G or g | 移动到开头一行 |
| /charaters | 向前查找指定的字符串 |
| n | 向前查找下一个出现的字符串,这个字符串是之前所指定查找的 |
| h | 显示帮助屏幕 |
| q | 退出 less 程序 |
less 属于”页面调度器”类程序,这些程序允许以逐页方式轻松浏览长文本文档。 more 程序只能向前翻页,而 less 程序允许前后翻页,此外还有很多其它的特性。
表 4-4: Linux 系统中的目录

| 目录 | 评论 |
|---|---|
| / | 根目录,万物起源。 |
| /bin | 包含系统启动和运行所必须的二进制程序。 |
| /boot | 包含 Linux 内核、初始 RAM 磁盘映像(用于启动时所需的驱动)和 启动加载程序。 有趣的文件: - /boot/grub/grub.conf or menu.lst, 被用来配置启动加载程序。 - /boot/vmlinuz,Linux 内核。 |
| /dev | 这是一个包含设备结点的特殊目录。“一切都是文件”,也适用于设备。 在这个目录里,内核维护着所有设备的列表。 |
| /etc | 这个目录包含所有系统层面的配置文件。它也包含一系列的 shell 脚本, 在系统启动时,这些脚本会开启每个系统服务。这个目录中的任何文件应该是可读的文本文件。 有趣的文件:虽然/etc 目录中的任何文件都有趣,但这里只列出了一些我一直喜欢的文件: - /etc/crontab, 定义自动运行的任务。 - /etc/fstab,包含存储设备的列表,以及与他们相关的挂载点。 - /etc/passwd,包含用户帐号列表。 |
| /home | 在通常的配置环境下,系统会在/home 下,给每个用户分配一个目录。普通用户只能 在自己的目录下写文件。这个限制保护系统免受错误的用户活动破坏。 |
| /lib | 包含核心系统程序所使用的共享库文件。这些文件与 Windows 中的动态链接库相似。 |
| /lost+found | 每个使用 Linux 文件系统的格式化分区或设备,例如 ext3文件系统, 都会有这个目录。当部分恢复一个损坏的文件系统时,会用到这个目录。这个目录应该是空的,除非文件系统 真正的损坏了。 |
| /media | 在现在的 Linux 系统中,/media 目录会包含可移动介质的挂载点, 例如 USB 驱动器,CD-ROMs 等等。这些介质连接到计算机之后,会自动地挂载到这个目录结点下。 |
| /mnt | 在早些的 Linux 系统中,/mnt 目录包含可移动介质的挂载点。 |
| /opt | 这个/opt 目录被用来安装“可选的”软件。这个主要用来存储可能 安装在系统中的商业软件产品。 |
| /proc | 这个/proc 目录很特殊。从存储在硬盘上的文件的意义上说,它不是真正的文件系统。 相反,它是一个由 Linux 内核维护的虚拟文件系统。它所包含的文件是内核的窥视孔。这些文件是可读的, 它们会告诉你内核是怎样监管计算机的。 |
| /root | root 帐户的家目录。 |
| /sbin | 这个目录包含“系统”二进制文件。它们是完成重大系统任务的程序,通常为超级用户保留。 |
| /tmp | 这个/tmp 目录,是用来存储由各种程序创建的临时文件的地方。一些配置导致系统每次 重新启动时,都会清空这个目录。 |
| /usr | 在 Linux 系统中,/usr 目录可能是最大的一个。它包含普通用户所需要的所有程序和文件。 |
| /usr/bin | /usr/bin 目录包含系统安装的可执行程序。通常,这个目录会包含许多程序。 |
| /usr/lib | 包含由/usr/bin 目录中的程序所用的共享库。 |
| /usr/local | 这个/usr/local 目录,是非系统发行版自带程序的安装目录。 通常,由源码编译的程序会安装在/usr/local/bin 目录下。新安装的 Linux 系统中会存在这个目录, 并且在管理员安装程序之前,这个目录是空的。 |
| /usr/sbin | 包含许多系统管理程序。 |
| /usr/share | /usr/share 目录包含许多由/usr/bin 目录中的程序使用的共享数据。 其中包括像默认的配置文件、图标、桌面背景、音频文件等等。 |
| /usr/share/doc | 大多数安装在系统中的软件包会包含一些文档。在/usr/share/doc 目录下, 我们可以找到按照软件包分类的文档。 |
| /var | 除了/tmp 和/home 目录之外,相对来说,目前我们看到的目录是静态的,这是说, 它们的内容不会改变。/var 目录存放的是动态文件。各种数据库,假脱机文件, 用户邮件等等,都位于在这里。 |
| /var/log | 这个/var/log 目录包含日志文件、各种系统活动的记录。这些文件非常重要,并且 应该时时监测它们。其中最重要的一个文件是/var/log/messages。注意,为了系统安全,在一些系统中, 你必须是超级用户才能查看这些日志文件。 |
四、操作文件和目录
cp— Copy files and directories 复制文件和目录mv— Move/rename files and directories 移动/重命名文件和目录mkdir— Create directories 创建目录rm— Remove files and directories 删除文件和目录ln— Create hard and symbolic links 创建硬链接和符号链接
例如,怎样拷贝一个目录下所有的HTML文件 ——这些文件在目标目录不存在或者版本比目标目录的文件更新——到目标目录呢? 要完成这个任务,使用文件管理器相当难,使用命令行相当容易:
cp -u *.html destination
通配符(类似正则)
表5-1: 通配符
| 通配符 | 意义 |
|---|---|
| * | 匹配任意多个字符(包括零个或一个) |
| ? | 匹配任意一个字符(不包括零个) |
| [characters] | 匹配任意一个属于字符集中的字符 |
| [!characters] | 匹配任意一个不是字符集中的字符 |
| [[:class:]] | 匹配任意一个属于指定字符类中的字符 |
表5-2: 普遍使用的字符类
| 字符类 | 意义 |
|---|---|
| [:alnum:] | 匹配任意一个字母或数字 |
| [:alpha:] | 匹配任意一个字母 |
| [:digit:] | 匹配任意一个数字 |
| [:lower:] | 匹配任意一个小写字母 |
| [:upper:] | 匹配任意一个大写字母 |
表5-3: 通配符范例
| 模式 | 匹配对象 |
|---|---|
| * | 所有文件 |
| g* | 文件名以“g”开头的文件 |
| b*.txt | 以”b”开头,中间有零个或任意多个字符,并以”.txt”结尾的文件 |
| Data??? | 以“Data”开头,其后紧接着3个字符的文件 |
| [abc]* | 文件名以”a”,”b”,或”c”开头的文件 |
| BACKUP.[0-9][0-9][0-9] | 以”BACKUP.”开头,并紧接着3个数字的文件 |
| [[:upper:]]* | 以大写字母开头的文件 |
| [![:digit:]]* | 不以数字开头的文件 |
| *[[:lower:]123] | 文件名以小写字母结尾,或以 “1”,“2”,或 “3” 结尾的文件 |
mkdir - 创建目录
mkdir 命令是用来创建目录的。它这样工作:
mkdir directory...
注意表示法:** 在描述一个命令时(如上所示),当有三个圆点跟在一个命令的参数后面, 这意味着那个参数可以重复,就像这样:
mkdir dir1
会创建一个名为”dir1”的目录,而
mkdir dir1 dir2 dir3
cp - 复制文件和目录
cp 命令,复制文件或者目录。它有两种使用方法:
cp item1 item2
复制单个文件或目录”item1”到文件或目录”item2”,和:
cp item... directory
有用的选项和实例
表5-4: cp 选项
| 选项 | 意义 |
|---|---|
| -a, —archive | 复制文件和目录,以及它们的属性,包括拥有者和所有权。 通常,副本具有用户所操作文件的默认属性。 |
| -i, —interactive | 在重写已存在文件之前,提示用户确认。如果这个选项不指定, cp 命令会默认重写文件。 |
| -r, —recursive | 递归地复制目录及目录中的内容。当复制目录时, 需要这个选项(或者-a 选项)。 |
| -u, —update | 当把文件从一个目录复制到另一个目录时,仅复制 目标目录中不存在的文件,或者是文件内容新于目标目录中已经存在的文件。 |
| -v, —verbose | 显示翔实的命令操作信息 |
表5-5: cp 实例
| 命令 | 运行结果 |
|---|---|
| cp file1 file2 | 复制文件 file1 内容到文件 file2。如果 file2 已经存在, file2 的内容会被 file1 的内容重写。如果 file2 不存在,则会创建 file2。 |
| cp -i file1 file2 | 这条命令和上面的命令一样,除了如果文件 file2 存在的话,在文件 file2 被重写之前, 会提示用户确认信息。 |
| cp file1 file2 dir1 | 复制文件 file1 和文件 file2 到目录 dir1。目录 dir1 必须存在。 |
| cp dir1/* dir2 | 使用一个通配符,在目录 dir1 中的所有文件都被复制到目录 dir2 中。 dir2 必须已经存在。 |
| cp -r dir1 dir2 | 复制目录 dir1 中的内容到目录 dir2。如果目录 dir2 不存在, 创建目录 dir2,操作完成后,目录 dir2 中的内容和 dir1 中的一样。 如果目录 dir2 存在,则目录 dir1 (和目录中的内容)将会被复制到 dir2 中。 |
mv - 移动和重命名文件
mv 命令可以执行文件移动和文件命名任务,这依赖于你怎样使用它。任何一种 情况下,完成操作之后,原来的文件名不再存在。mv 使用方法与 cp 很相像:
mv item1 item2
把文件或目录 “item1” 移动或重命名为 “item2”, 或者:
mv item... directory
把一个或多个条目从一个目录移动到另一个目录中。
表5-6: mv 选项
| 选项 | 意义 |
|---|---|
| -i —interactive | 在重写一个已经存在的文件之前,提示用户确认信息。 如果不指定这个选项,mv 命令会默认重写文件内容。 |
| -u —update | 当把文件从一个目录移动另一个目录时,只是移动不存在的文件, 或者文件内容新于目标目录相对应文件的内容。 |
| -v —verbose | 当操作 mv 命令时,显示翔实的操作信息。 |
表5-7: mv 实例
| mv file1 file2 | 移动 file1 到 file2。如果 file2 存在,它的内容会被 file1 的内容重写。 如果 file2 不存在,则创建 file2。 这两种情况下,file1 都不再存在。 |
|---|---|
| mv -i file1 file2 | 除了如果 file2 存在的话,在 file2 被重写之前,用户会得到 提示信息外,这个和上面的选项一样。 |
| mv file1 file2 dir1 | 移动 file1 和 file2 到目录 dir1 中。dir1 必须已经存在。 |
| mv dir1 dir2 | 如果目录 dir2 不存在,创建目录 dir2,并且移动目录 dir1 的内容到 目录 dir2 中,同时删除目录 dir1。如果目录 dir2 存在,移动目录 dir1(及它的内容)到目录 dir2。 |
rm - 删除文件和目录
表5-8: rm 选项
| 选项 | 意义 |
|---|---|
| -i, —interactive | 在删除已存在的文件前,提示用户确认信息。 如果不指定这个选项,rm 会默默地删除文件 |
| -r, —recursive | 递归地删除文件,这意味着,如果要删除一个目录,而此目录 又包含子目录,那么子目录也会被删除。要删除一个目录,必须指定这个选项。 |
| -f, —force | 忽视不存在的文件,不显示提示信息。这选项覆盖了“—interactive”选项。 |
| -v, —verbose | 在执行 rm 命令时,显示翔实的操作信息。 |
表5-9: rm 实例
| 命令 | 运行结果 |
|---|---|
| rm file1 | 默默地删除文件 |
| rm -i file1 | 除了在删除文件之前,提示用户确认信息之外,和上面的命令作用一样。 |
| rm -r file1 dir1 | 删除文件 file1, 目录 dir1,及 dir1 中的内容。 |
| rm -rf file1 dir1 | 同上,除了如果文件 file1,或目录 dir1 不存在的话,rm 仍会继续执行。 |
小贴士。 当你使用带有通配符的rm命令时(除了仔细检查输入的内容外), 先用 ls 命令来测试通配符。这会让你看到将要被删除的文件是什么。然后按下上箭头按键,重新调用 刚刚执行的命令,用 rm 替换 ls。
[root@iZ8vb3yphb2x30z813n1xpZ ~]# ls -l *.txt
-rw-r--r-- 1 root root 43 6月 13 18:36 temp.txt
ln — 创建链接
ln 命令既可创建硬链接,也可以创建符号链接。可以用其中一种方法来使用它:
ln file link
创建硬链接,和:
ln -s item link
创建符号链接,”item” 可以是一个文件或是一个目录。
硬链接
与更加现代的符号链接相比,硬链接是最初 Unix 创建链接的方式。每个文件默认会有一个硬链接, 这个硬链接给予文件名字。我们每创建一个硬链接,就为一个文件创建了一个额外的目录项。 硬链接有两个重要局限性:
- 一个硬链接不能关联它所在文件系统之外的文件。这是说一个链接不能关联 与链接本身不在同一个磁盘分区上的文件。
- 一个硬链接不能关联一个目录。
一个硬链接和文件本身没有什么区别。不像符号链接,当你列出一个包含硬链接的目录 内容时,你会看到没有特殊的链接指示说明。当一个硬链接被删除时,这个链接 被删除,但是文件本身的内容仍然存在(这是说,它所占的磁盘空间不会被重新分配), 直到所有关联这个文件的链接都删除掉。知道硬链接很重要,因为你可能有时 会遇到它们,但现在实际中更喜欢使用符号链接,下一步我们会讨论符号链接。
符号链接
创建符号链接是为了克服硬链接的局限性。符号链接生效,是通过创建一个 特殊类型的文件,这个文件包含一个关联文件或目录的文本指针。在这一方面, 它们和 Windows 的快捷方式差不多,当然,符号链接早于 Windows 的快捷方式 很多年;-)
一个符号链接指向一个文件,而且这个符号链接本身与其它的符号链接几乎没有区别。 例如,如果你往一个符号链接里面写入东西,那么相关联的文件也被写入。然而, 当你删除一个符号链接时,只有这个链接被删除,而不是文件自身。如果先于符号链接 删除文件,这个链接仍然存在,但是不指向任何东西。在这种情况下,这个链接被称为 坏链接。在许多实现中,ls 命令会以不同的颜色展示坏链接,比如说红色,来显示它们 的存在。
五、使用命令
type– Indicate how a command name is interpreted 说明怎样解释一个命令名which– Display which executable program will be executed 显示会执行哪个可执行程序man– Display a command’s manual page 显示命令手册页apropos– Display a list of appropriate commands 显示一系列适合的命令info– Display a command’s info entry 显示命令 infowhatis– Display a very brief description of a command 显示一个命令的简洁描述alias– Create an alias for a command 创建命令别名六、重定向
cat- 连接文件sort- 排序文本行uniq- 报道或省略重复行grep- 打印匹配行wc- 打印文件中换行符,字,和字节个数head- 输出文件第一部分tail- 输出文件最后一部分tee- 从标准输入读取数据,并同时写到标准输出和文件标准输入、输出和错误
到目前为止,我们用到的许多程序都会产生某种输出。这种输出,经常由两种类型组成。 第一,程序运行结果;这是说,程序要完成的功能。第二,我们得到状态和错误信息, 这些告诉我们程序进展。如果我们观察一个命令,例如 ls,会看到它的运行结果和错误信息 显示在屏幕上。
与 Unix 主题“任何东西都是一个文件”保持一致,像 ls这样的程序实际上把他们的运行结果 输送到一个叫做标准输出的特殊文件(经常用 stdout 表示),而它们的状态信息则送到另一个 叫做标准错误的文件(stderr)。默认情况下,标准输出和标准错误都连接到屏幕,而不是 保存到磁盘文件。除此之外,许多程序从一个叫做标准输入(stdin)的设备得到输入,默认情况下, 标准输入连接到键盘。
I/O 重定向允许我们更改输出地点和输入来源。一般来说,输入来自键盘,输出送到屏幕, 但是通过 I/O 重定向,我们可以做出改变。标准输出重定向
I/O 重定向允许我们来重定义标准输出的地点。我们使用 “>” 重定向符后接文件名将标准输出重定向到除屏幕 以外的另一个文件。为什么我们要这样做呢?因为有时候把一个命令的运行结果存储到 一个文件很有用处。例如,我们可以告诉 shell 把 ls 命令的运行结果输送到文件 ls-output.txt 中去, 由文件代替屏幕。
这里,我们创建了一个长长的目录/usr/bin 列表,并且输送程序运行结果到文件 ls-output.txt 中。 我们检查一下重定向的命令输出结果:[me@linuxbox ~]$ ls -l /usr/bin > ls-output.txt
所以,怎样才能把重定向结果追加到文件内容后面,而不是从开头重写文件?为了这个目的, 我们使用”>>“重定向符,像这样:[me@linuxbox ~]$ ls -l ls-output.txt -rw-rw-r-- 1 me me 167878 2008-02-01 15:07 ls-output.txt[me@linuxbox ~]$ ls -l /usr/bin >> ls-output.txtcat - 连接文件
在大多数情况下,你可以认为 cat 命令相似于 DOS 中的 TYPE 命令。你可以使用 cat 来显示 文件而没有分页,例如:
如果 cat 没有给出任何参数,它会从标准输入读入数据,又因为标准输入默认情况下连接到键盘, 它正在等待我们输入数据!试试这个:[me@linuxbox ~]$ cat ls-output.txt
下一步,输入 Ctrl-d(按住 Ctrl 键同时按下”d”),来告诉 cat,在标准输入中, 它已经到达文件末尾。[me@linuxbox ~]$ cat The quick brown fox jumped over the lazy dog.
由于没有文件名参数,cat 复制标准输入到标准输出,所以我们看到文本行重复出现。 我们可以使用这种行为来创建简短的文本文件。比方说,我们想创建一个叫做”lazy_dog.txt” 的文件,这个文件包含例子中的文本。我们这样做:[me@linuxbox ~]$ cat The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog.[me@linuxbox ~]$ cat > lazy_dog.txt The quick brown fox jumped over the lazy dog.管道线
命令从标准输入读取数据并输送到标准输出的能力被一个称为管道线的 shell 特性所利用。 使用管道操作符”|”(竖杠),一个命令的标准输出可以通过管道送至另一个命令的标准输入:command1 | command2
为了全面地说明这个命令,我们需要一些命令。是否记得我们说过,我们已经知道有一个 命令接受标准输入?它是 less 命令。我们用 less 来一页一页地显示任何命令的输出,命令把 它的运行结果输送到标准输出:
[me@linuxbox ~]$ ls -l /usr/bin | less
过滤器
管道线经常用来对数据完成复杂的操作。有可能会把几个命令放在一起组成一个管道线。 通常,以这种方式使用的命令被称为过滤器。过滤器接受输入,以某种方式改变它,然后 输出它。第一个我们想试验的过滤器是 sort。想象一下,我们想把目录/bin 和/usr/bin 中 的可执行程序都联合在一起,再把它们排序,然后浏览执行结果:
[me@linuxbox ~]$ ls /bin /usr/bin | sort | less
uniq - 报道或忽略重复行
uniq 命令经常和 sort 命令结合在一起使用。uniq 从标准输入或单个文件名参数接受数据有序 列表(详情查看 uniq 手册页),默认情况下,从数据列表中删除任何重复行。所以,为了确信 我们的列表中不包含重复句子(这是说,出现在目录/bin 和/usr/bin 中重名的程序),我们添加 uniq 到我们的管道线中:
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | less

如果我们想看到 重复的数据列表,让 uniq 命令带上”-d”选项
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq -d | less
wc - 打印行数、字数和字节数
wc(字计数)命令是用来显示文件所包含的行数、字数和字节数。例如:
[me@linuxbox ~]$ wc ls-output.txt
7902 64566 503634 ls-output.txt
在这个例子中,wc 打印出来三个数字:包含在文件 ls-output.txt 中的行数,单词数和字节数, 正如我们先前的命令,如果 wc 不带命令行参数,它接受标准输入。”-l”选项限制命令输出只能 报道行数。添加 wc 到管道线来统计数据,是个很便利的方法。查看我们的有序列表中程序个数, 我们可以这样做:
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | wc -l
2728
grep - 打印匹配行
grep 是个很强大的程序,用来找到文件中的匹配文本。这样使用 grep 命令:
grep pattern [file...]
当 grep 遇到一个文件中的匹配”模式”,它会打印出包含这个类型的行。grep 能够匹配的模式可以 很复杂,但是现在我们把注意力集中在简单文本匹配上面。在后面的章节中,我们将会研究 高级模式,叫做正则表达式。
比如说,我们想在我们的程序列表中,找到文件名中包含单词”zip”的所有文件。这样一个搜索, 可能让我们了解系统中的一些程序与文件压缩有关系。这样做:
[me@linuxbox ~]$ ls /bin /usr/bin | sort | uniq | grep zip
bunzip2
bzip2
gunzip
...
grep 有一些方便的选项:”-i”使得 grep 在执行搜索时忽略大小写(通常,搜索是大小写 敏感的),
”-v”选项会告诉 grep 只打印不匹配的行。
head / tail - 打印文件开头部分/结尾部分
有时候你不需要一个命令的所有输出。可能你只想要前几行或者后几行的输出内容。 head 命令打印文件的前十行,而 tail 命令打印文件的后十行。默认情况下,两个命令 都打印十行文本,但是可以通过”-n”选项来调整命令打印的行数。
[me@linuxbox ~]$ head -n 5 ls-output.txt
total 343496
...
[me@linuxbox ~]$ tail -n 5 ls-output.txt
...
它们也能用在管道线中:
[me@linuxbox ~]$ ls /usr/bin | tail -n 5
znew
...
tail 有一个选项允许你实时地浏览文件。当观察日志文件的进展时,这很有用,因为 它们同时在被写入。在以下的例子里,我们要查看目录/var/log 里面的信息文件。在 一些 Linux 发行版中,要求有超级用户权限才能阅读这些文件,因为文件/var/log/messages 可能包含安全信息。
[me@linuxbox ~]$ tail -f /var/log/messages
Feb 8 13:40:05 twin4 dhclient: DHCPACK from 192.168.1.1
....
使用”-f”选项,tail 命令继续监测这个文件,当新的内容添加到文件后,它们会立即 出现在屏幕上。这会一直继续下去直到你输入 Ctrl-c。
tee - 从 Stdin 读取数据,并同时输出到 Stdout 和文件
为了和我们的管道隐喻保持一致,Linux 提供了一个叫做 tee 的命令,这个命令制造了 一个”tee”,安装到我们的管道上。tee 程序从标准输入读入数据,并且同时复制数据 到标准输出(允许数据继续随着管道线流动)和一个或多个文件。当在某个中间处理 阶段来捕捉一个管道线的内容时,这很有帮助。这里,我们重复执行一个先前的例子, 这次包含 tee 命令,在 grep 过滤管道线的内容之前,来捕捉整个目录列表到文件 ls.txt:
[me@linuxbox ~]$ ls /usr/bin | tee ls.txt | grep zip
bunzip2
bzip2
....
七、从 shell 眼中看世界
echo- Display a line of text 显示一行文本(字符)展开
每当你输入一个命令并按下 enter 键,bash 会在执行你的命令之前对输入 的字符完成几个步骤的处理。我们已经见过几个例子:例如一个简单的字符序列”*”, 对 shell 来说有着多么丰富的涵义。这背后的的过程叫做(字符)展开。通过展开, 你输入的字符,在 shell 对它起作用之前,会展开成为别的字符。为了说明这一点 ,让我们看一看 echo 命令。echo 是一个 shell 内建命令,可以完成非常简单的任务。 它将它的文本参数打印到标准输出中。[me@linuxbox ~]$ echo this is a test this is a test
那么刚才发生了什么事情呢? 为什么 echo 不打印”“呢?如果你回忆起我们所学过的 关于通配符的内容,这个”“字符意味着匹配文件名中的任意字符,但在原先的讨论 中我们并不知道 shell 是怎样实现这个功能的。简单的答案就是 shell 在 echo 命 令被执行前把”“展开成了另外的东西(在这里,就是在当前工作目录下的文件名字)。 当回车键被按下时,shell 在命令被执行前在命令行上自动展开任何符合条件的字符, 所以 echo 命令的实际参数并不是”“,而是它展开后的结果。知道了这个以后, 我们就能明白 echo 的行为符合预期。[me@linuxbox ~]$ echo * Desktop Documents ls-output.txt Music Pictures Public Templates Videos路径名展开
通配符所依赖的工作机制叫做路径名展开。如果我们试一下在之前的章节中使用的技巧, 我们会看到它们实际上是展开。给定一个家目录,它看起来像这样:[me@linuxbox ~]$ ls Desktop ls-output.txt Pictures Templates ....
我们能够执行以下的展开:
[me@linuxbox ~]$ echo D*
Desktop Documents
和:
[me@linuxbox ~]$ echo *s
Documents Pictures Templates Videos
甚至是:
[me@linuxbox ~]$ echo [[:upper:]]*
Desktop Documents Music Pictures Public Templates Videos
查看家目录之外的目录:
[me@linuxbox ~]$ echo /usr/*/share
/usr/kerberos/share /usr/local/share
波浪线展开
可能你从我们对 cd 命令的介绍中回想起来,波浪线字符(“~”)有特殊的含义。当它用在 一个单词的开头时,它会展开成指定用户的家目录名,如果没有指定用户名,则展开成当前用户的家目录:
[me@linuxbox ~]$ echo ~
/home/me
如果有用户”foo”这个帐号,那么:
[me@linuxbox ~]$ echo ~foo
/home/foo
算术表达式展开
shell 在展开中执行算数表达式。这允许我们把 shell 提示当作计算器来使用:
[me@linuxbox ~]$ echo $((2 * 2))
4
算术表达式展开使用这种格式:
$((expression))
表 8-1: 算术操作符
| 操作符 | 说明 |
|---|---|
| + | 加 |
| - | 减 |
| * | 乘 |
| / | 除(但是记住,因为展开只是支持整数除法,所以结果是整数。) |
| % | 取余,只是简单的意味着,“余数” |
| ** | 取幂 |
在算术表达式中空格并不重要,并且表达式可以嵌套。例如,5的平方乘以3:
[me@linuxbox ~]$ echo $(($((5**2)) * 3))
75
这是一个使用除法和取余操作符的例子。注意整数除法的结果:
[me@linuxbox ~]$ echo Five divided by two equals $((5/2))
Five divided by two equals 2
[me@linuxbox ~]$ echo with $((5%2)) left over.
with 1 left over.
花括号展开
可能最奇怪的展开是花括号展开。通过它,你可以从一个包含花括号的模式中 创建多个文本字符串。这是一个例子:
[me@linuxbox ~]$ echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back
花括号展开模式可能包含一个开头部分叫做报头,一个结尾部分叫做附言。花括号表达式本身可 能包含一个由逗号分开的字符串列表,或者一个整数区间,或者单个的字符的区间。这种模式不能 嵌入空白字符。这个例子中使用了一个整数区间:
[me@linuxbox ~]$ echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
倒序排列的字母区间:
[me@linuxbox ~]$ echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
花括号展开可以嵌套:
[me@linuxbox ~]$ echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
那么这对什么有好处呢?最常见的应用是,创建一系列的文件或目录列表。例如, 如果我们是摄影师,有大量的相片。我们想把这些相片按年月先后组织起来。首先, 我们要创建一系列以数值”年-月”形式命名的目录。通过这种方式,可以使目录名按照 年代顺序排列。我们可以手动键入整个目录列表,但是工作量太大了,并且易于出错。 反之,我们可以这样做:
[me@linuxbox ~]$ mkdir Pics
[me@linuxbox ~]$ cd Pics
[me@linuxbox Pics]$ mkdir {2007..2009}-0{1..9} {2007..2009}-{10..12}
[me@linuxbox Pics]$ ls
2007-01 2007-07 2008-01 2008-07 2009-01 2009-07
2007-02 2007-08 2008-02 2008-08 2009-02 2009-08
2007-03 2007-09 2008-03 2008-09 2009-03 2009-09
2007-04 2007-10 2008-04 2008-10 2009-04 2009-10
2007-05 2007-11 2008-05 2008-11 2009-05 2009-11
2007-06 2007-12 2008-06 2008-12 2009-06 2009-12
参数展开
在这一章我们将会简单介绍参数展开,但会在后续章节中进行详细讨论。这个特性在 shell 脚本中比直接在命令行中更有用。 它的许多功能和系统存储小块数据,并给每块数据命名的能力有关系。许多像这样的小块数据, 更恰当的称呼应该是变量,可供你方便地检查它们。例如,叫做”USER”的变量包含你的 用户名。可以这样做来调用参数,并查看 USER 中的内容,:
[me@linuxbox ~]$ echo $USER
me
命令替换
命令替换允许我们把一个命令的输出作为一个展开模式来使用:
[me@linuxbox ~]$ echo $(ls)
Desktop Documents ls-output.txt Music Pictures Public Templates
Videos
我最喜欢用的一行命令是像这样的:
[me@linuxbox ~]$ ls -l $(which cp)
-rwxr-xr-x 1 root root 71516 2007-12-05 08:58 /bin/cp
这里我们把 which cp 的执行结果作为一个参数传递给 ls 命令,因此可以在不知道 cp 命令 完整路径名的情况下得到它的文件属性列表。我们不只限制于简单命令。也可以使用整个管道线 (只展示部分输出):
[me@linuxbox ~]$ file $(ls /usr/bin/* | grep zip)
/usr/bin/bunzip2: symbolic link to `bzip2'
....
在这个例子中,管道线的输出结果成为 file 命令的参数列表。
引用
我们已经知道 shell 有许多方式可以完成展开,现在是时候学习怎样来控制展开了。 以下面例子来说明:
[me@linuxbox ~]$ echo this is a test
this is a test
或者:
[me@linuxbox ~]$ echo The total is $100.00
The total is 00.00
在第一个例子中,shell 利用单词分割删除掉 echo 命令的参数列表中多余的空格。在第二个例子中, 参数展开把 $1 的值替换为一个空字符串,因为 1 是没有定义的变量。shell 提供了一种 叫做引用的机制,来有选择地禁止不需要的展开。
双引号
我们将要看一下引用的第一种类型,双引号。如果你把文本放在双引号中, shell 使用的特殊字符,都失去它们的特殊含义,被当作普通字符来看待。 有几个例外: $,\ (反斜杠),和 `(倒引号)。这意味着单词分割、路径名展开、 波浪线展开和花括号展开都将失效,然而参数展开、算术展开和命令替换 仍然执行。使用双引号,我们可以处理包含空格的文件名。比方说我们是不幸的 名为 two words.txt 文件的受害者。如果我们试图在命令行中使用这个 文件,单词分割机制会导致这个文件名被看作两个独自的参数,而不是所期望 的单个参数:
[me@linuxbox ~]$ ls -l two words.txt
ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory
使用双引号,我们可以阻止单词分割,得到期望的结果;进一步,我们甚至可以修复 破损的文件名。
[me@linuxbox ~]$ ls -l "two words.txt"
-rw-rw-r-- 1 me me 18 2008-02-20 13:03 two words.txt
[me@linuxbox ~]$ mv "two words.txt" two_words.txt
你瞧!现在我们不必一直输入那些讨厌的双引号了。
记住,在双引号中,参数展开、算术表达式展开和命令替换仍然有效:
[me@linuxbox ~]$ echo "$USER $((2+2)) $(cal)"
me 4 February 2008
Su Mo Tu We Th Fr Sa
....
单引号
如果需要禁止所有的展开,我们要使用单引号。以下例子是无引用,双引号,和单引号的比较结果:
[me@linuxbox ~]$ echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/me/ls-output.txt a b foo 4 me
[me@linuxbox ~]$ echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 me
[me@linuxbox ~]$ echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
转义字符
有时候我们只想引用单个字符。我们可以在字符之前加上一个反斜杠,在这里叫做转义字符。 经常在双引号中使用转义字符,来有选择地阻止展开。
[me@linuxbox ~]$ echo "The balance for user $USER is: \$5.00"
The balance for user me is: $5.00
| 转义序列 | 含义 |
|---|---|
| \a | 响铃(”警告”-导致计算机嘟嘟响) |
| \b | 退格符 |
| \n | 新的一行。在类 Unix 系统中,产生换行。 |
| \r | 回车符 |
| \t | 制表符 |
八、键盘高级操作
clear- Clear the screen 清空屏幕history-Display the contents of the history list 显示历史列表内容自动补全
[me@linuxbox ~]$ ls l
现在按下 tab 键:
[me@linuxbox ~]$ ls ls-output.txt
按下 tab:
[me@linuxbox ~]$ ls D
没有补全,只是嘟嘟响。因为”D”不止匹配目录中的一个条目。为了自动补全执行成功, 你给它的”线索”不能模棱两可。如果我们继续输入:
[me@linuxbox ~]$ ls Do
然后按下 tab:
[me@linuxbox ~]$ ls Documents
The completion is successful.
自动补全成功了。
搜索历史命令
在任何时候,我们都可以浏览历史列表的内容,通过:
[me@linuxbox ~]$ history | less
在默认情况下,bash 会存储你所输入的最后 500 个命令。在随后的章节里,我们会知道 怎样调整这个数值。比方说我们想在自己曾经用过的命令中,找出和/usr/bin这一目录相关的。那么我们就可以这样做:
[me@linuxbox ~]$ history | grep /usr/bin
比方说在我们的搜索结果之中,我们得到一行,包含了有趣的命令,像这样;
88 ls -l /usr/bin > ls-output.txt
数字 “88” 是这个命令在历史列表中的行号。我们可以使用另一种叫做 历史命令展开的方式,来调用“88”所代表的这一行命令:
[me@linuxbox ~]$ !88
九、权限
id– Display user identity 显示用户身份号chmod– Change a file’s mode 更改文件模式umask– Set the default file permissions 设置默认的文件权限su– Run a shell as another user 以另一个用户的身份来运行 shellsudo– Execute a command as another user 以另一个用户的身份来执行命令chown– Change a file’s owner 更改文件所有者chgrp– Change a file’s group ownership 更改文件组所有权passwd– Change a user’s password 更改用户密码
在 Unix 安全模型中,一个用户可能拥有文件和目录。当一个用户拥有一个文件或目录时, 用户对这个文件或目录的访问权限拥有控制权。用户反过来又属于一个由一个或多个 用户组成的用户组,用户组成员由文件和目录的所有者授予对文件和目录的访问权限。除了 对一个用户组授予权限之外,文件所有者可能会给每个人一些权限,在 Unix 术语中,每个人 是指整个世界。可以用 id 命令,来找到关于你自己身份的信息:
让我们看一下输出结果。当用户创建帐户之后,系统会给用户分配一个号码,叫做用户 ID 或者 uid,然后,为了符合人类的习惯,这个 ID 映射到一个用户名。系统又会给这个用户 分配一个原始的组 ID(即 gid)。一个用户可以属于额外的组(除gid外,有更多的组)。上面的例子来自于 Fedora 系统, 比方说 Ubuntu 的输出结果可能看起来有点儿不同:
[me@linuxbox ~]$ id
uid=1000(me) gid=1000(me)
groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(v
ideo),46(plugdev),108(lpadmin),114(admin),1000(me)
正如我们能看到的,两个系统中用户的 uid 和 gid 号码是不同的。原因很简单,因为 Fedora 系统 从500开始进行普通用户帐户的编号,而 Ubuntu 从1000开始。我们也能看到 Ubuntu 的用户属于 更多的用户组。这和 Ubuntu 管理系统设备和服务权限的方式有关系。
那么这些信息来源于哪里呢?像 Linux 系统中的许多东西一样,来自一系列的文本文件。用户帐户 定义在/etc/passwd 文件里面,用户组定义在/etc/group 文件里面。当用户帐户和用户组创建以后, 这些文件随着文件/etc/shadow 的变动而修改,文件/etc/shadow 包含了关于用户密码的信息。 对于每个用户帐号,文件/etc/passwd 定义了用户(登录)名、uid、gid、帐号的真实姓名、家目录 和登录 shell。如果你查看一下文件/etc/passwd 和文件/etc/group 的内容,你会注意到除了普通 用户帐号之外,还有超级用户(uid 0)帐号,和各种各样的系统用户。
读取、写入和执行
对于文件和目录的访问权力是根据读访问、写访问和执行访问来定义的。如果我们看一下 ls 命令的输出结果,我们能得到一些线索,这是怎样实现的:
[me@linuxbox ~]$ > foo.txt
[me@linuxbox ~]$ ls -l foo.txt
-rw-rw-r-- 1 me me 0 2008-03-06 14:52 foo.txt
列表的前十个字符是文件的属性。这十个字符的第一个字符表明文件类型。下表是你可能经常看到 的文件类型(还有其它的,不常见类型):
表10-1: 文件类型
| 属性 | 文件类型 |
|---|---|
| - | 一个普通文件 |
| d | 一个目录 |
| l | 一个符号链接。注意对于符号链接文件,剩余的文件属性总是”rwxrwxrwx”,而且都是 虚拟值。真正的文件属性是指符号链接所指向的文件的属性。 |
| c | 一个字符设备文件。这种文件类型是指按照字节流来处理数据的设备。 比如说终端机或者调制解调器 |
| b | 一个块设备文件。这种文件类型是指按照数据块来处理数据的设备,例如一个硬盘或者 CD-ROM 盘。 |

剩下的九个字符叫做文件模式,代表着文件所有者、文件组所有者和其他人的读、写和执行权限。
图 1: 权限属性
当设置文件模式后,r、w和x 模式属性对文件和目录会产生以下影响:
表 10-2: 权限属性
| 属性 | 文件 | 目录 |
|---|---|---|
| r | 允许打开并读取文件内容。 | 允许列出目录中的内容,前提是目录必须设置了可执行属性(x)。 |
| w | 允许写入文件内容或截断文件。但是不允许对文件进行重命名或删除,重命名或删除是由目录的属性决定的。 | 允许在目录下新建、删除或重命名文件,前提是目录必须设置了可执行属性(x)。 |
| x | 允许将文件作为程序来执行,使用脚本语言编写的程序必须设置为可读才能被执行。 | 允许进入目录,例如:cd directory 。 |
表 10-3: 权限属性示例
| 文件属性 | 含义 |
|---|---|
| -rwx——— | 一个普通文件,对文件所有者来说可读、可写、可执行。其他人无法访问。 |
| -rw———- | 一个普通文件,对文件所有者来说可读可写。其他人无法访问。 |
| -rw-r—r— | 一个普通文件,对文件所有者来说可读可写,文件所有者的组成员可以读该文件,其他所有人都可以读该文件。 |
| -rwxr-xr-x | 一个普通文件,对文件所有者来说可读、可写、可执行。也可以被其他的所有人读取和执行。 |
| -rw-rw—— | 一个普通文件,对文件所有者以及文件所有者的组成员来说可读可写。 |
| lrwxrwxrwx | 一个符号链接,符号链接的权限都是虚拟的,真实的权限应该以符号链接指向的文件为准。 |
| drwxrwx—- | 一个目录,文件所有者以及文件所有者的组成员可以访问该目录,并且可以在该目录下新建、重命名、删除文件。 |
| drwxr-x—- | 一个目录,文件所有者可以访问该目录,并且可以在该目录下新建、重命名、删除文件,文件所有者的组成员可以访问该目录,但是不能新建、重命名、删除文件。 |
十、进程
ps– Report a snapshot of current processes 报告当前进程快照top– Display tasks 显示任务jobs– List active jobs 列出活跃的任务bg– Place a job in the background 把一个任务放到后台执行fg– Place a job in the foreground 把一个任务放到前台执行kill– Send a signal to a process 给一个进程发送信号killall– Kill processes by name 杀死指定名字的进程shutdown– Shutdown or reboot the system 关机或重启系统查看进程
查看进程,最常使用地命令(有几个命令)是 ps(process status)。ps 程序有许多选项,它最简单地使用形式是这样的:
TTY 是 “Teletype”(直译电传打字机) 的简写,是指进程的控制终端。TTY足足显示了 Unix 的年代久远。TIME 字段表示 进程所消耗的 CPU 时间数量。正如我们所看到的,这两个进程使计算机工作起来很轻松。[me@linuxbox ~]$ ps PID TTY TIME CMD 5198 pts/1 00:00:00 bash 10129 pts/1 00:00:00 ps
如果给 ps 命令加上选项,我们可以得到更多关于系统运行状态的信息:
加上 “x” 选项(注意没有开头的 “-“ 字符),告诉 ps 命令,展示所有进程,不管它们由什么 终端(如果有的话)控制。在 TTY 一栏中出现的 “?” ,表示没有控制终端。使用这个 “x” 选项,可以 看到我们所拥有的每个进程的信息。[me@linuxbox ~]$ ps x PID TTY STAT TIME COMMAND 2799 ? Ssl 0:00 /usr/libexec/bonobo-activation-server –ac 2820 ? Sl 0:01 /usr/libexec/evolution-data-server-1.10 -- and many more...
表11-1: 进程状态
| 状态 | 含义 |
|---|---|
| R | 运行中。这意味着,进程正在运行或准备运行。 |
| S | 正在睡眠。进程没有运行,而是,正在等待一个事件, 比如说,一个按键或者网络分组。 |
| D | 不可中断睡眠。进程正在等待 I/O,比方说,一个磁盘驱动器的 I/O。 |
| T | 已停止. 已经指示进程停止运行。稍后介绍更多。 |
| Z | 一个死进程或“僵尸”进程。这是一个已经终止的子进程,但是它的父进程还没有清空它。 (父进程没有把子进程从进程表中删除) |
| < | 一个高优先级进程。这可能会授予一个进程更多重要的资源,给它更多的 CPU 时间。 进程的这种属性叫做 niceness。具有高优先级的进程据说是不好的(less nice), 因为它占用了比较多的 CPU 时间,这样就给其它进程留下很少时间。 |
| N | 低优先级进程。 一个低优先级进程(一个“nice”进程)只有当其它高优先级进程被服务了之后,才会得到处理器时间。 |
另一个流行的选项组合是 “aux”(不带开头的”-“字符)。这会给我们更多信息:
[me@linuxbox ~]$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 2136 644 ? Ss Mar05 0:31 init
root 2 0.0 0.0 0 0 ? S< Mar05 0:00 [kt]
and many more...
这个选项组合,能够显示属于每个用户的进程信息。使用这个选项,可以唤醒 “BSD 风格” 的输出结果。 Linux 版本的 ps 命令,可以模拟几个不同 Unix 版本中的 ps 程序的行为。通过这些选项,我们得到 这些额外的列。
表11-2: BSD 风格的 ps 命令列标题
| 标题 | 含义 |
|---|---|
| USER | 用户 ID. 进程的所有者。 |
| %CPU | 以百分比表示的 CPU 使用率 |
| %MEM | 以百分比表示的内存使用率 |
| VSZ | 虚拟内存大小 |
| RSS | 进程占用的物理内存的大小,以千字节为单位。 |
| START | 进程启动的时间。若它的值超过24小时,则用天表示。 |
用 top 命令动态查看进程
虽然 ps 命令能够展示许多计算机运行状态的信息,但是它只是提供 ps 命令执行时刻的机器状态快照。 为了看到更多动态的信息,我们使用 top 命令:
[me@linuxbox ~]$ top
top 程序以进程活动顺序显示连续更新的系统进程列表。(默认情况下,每三秒钟更新一次),”top”这个名字 来源于 top 程序是用来查看系统中“顶端”进程的。top 显示结果由两部分组成: 最上面是系统概要,下面是进程列表,以 CPU 的使用率排序。
top - 14:59:20 up 6:30, 2 users, load average: 0.07, 0.02, 0.00
Tasks: 109 total, 1 running, 106 sleeping, 0 stopped, 2 zombie
Cpu(s): 0.7%us, 1.0%sy, 0.0%ni, 98.3%id, 0.0%wa, 0.0%hi, 0.0%si
Mem: 319496k total, 314860k used, 4636k free, 19392k buff
Swap: 875500k total, 149128k used, 726372k free, 114676k cach
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6244 me 39 19 31752 3124 2188 S 6.3 1.0 16:24.42 trackerd
....
表11-3: top 命令信息字段
| 行号 | 字段 | 意义 |
|---|---|---|
| 1 | top | 程序名。 |
| 14:59:20 | 当前时间。 | |
| up 6:30 | 这是正常运行时间。它是计算机从上次启动到现在所运行的时间。 在这个例子里,系统已经运行了六个半小时。 | |
| 2 users | 有两个用户登录系统。 | |
| load average: | 加载平均值是指,等待运行的进程数目,也就是说,处于可以运行状态并共享 CPU 的进程个数。 这里展示了三个数值,每个数值对应不同的时间段。第一个是最后60秒的平均值, 下一个是前5分钟的平均值,最后一个是前15分钟的平均值。若平均值低于1.0,则指示计算机 工作不忙碌。 | |
| 2 | Tasks: | 总结了进程数目和这些进程的各种状态。 |
| 3 | Cpu(s): | 这一行描述了 CPU 正在进行的活动的特性。 |
| 0.7%us | 0.7% 的 CPU 被用于用户进程。这意味着进程在内核之外。 | |
| 1.0%sy | 1.0%的 CPU 时间被用于系统(内核)进程。 | |
| 0.0%ni | 0.0%的 CPU 时间被用于”nice”(低优先级)进程。 | |
| 98.3%id | 98.3%的 CPU 时间是空闲的。 | |
| 0.0%wa | 0.0%的 CPU 时间来等待 I/O。 | |
| 4 | Mem: | 展示物理内存的使用情况。 |
| 5 | Swap: | 展示交换分区(虚拟内存)的使用情况。 |
中断一个进程
把一个进程放置到后台(执行)
假如说我们想让 shell 提示符返回,却不终止 xlogo 程序。我们可以把 这个程序放到后台(background)执行。把终端想象是一个有前台(包含在表层可见的事物,像 shell 提示符) 和后台(包含表层之下的隐藏的事物)(的设备)。为了启动一个程序并让它立即在后台 运行,我们在程序命令之后,加上”&”字符:
[me@linuxbox ~]$ xlogo &
[1] 28236
[me@linuxbox ~]$
shell 的任务控制功能给出了一种列出从我们终端中启动了的任务的方法。执行 jobs 命令,我们可以看到这个输出列表:
[me@linuxbox ~]$ jobs
[1]+ Running xlogo &
进程返回到前台
一个在后台运行的进程对一切来自键盘的输入都免疫,也不能用 Ctrl-c 来中断它。 为了让一个进程返回前台 (foreground),这样使用 fg 命令:
[me@linuxbox ~]$ jobs
[1]+ Running xlogo &
[me@linuxbox ~]$ fg %1
xlogo
停止一个进程
有时候,我们想要停止一个进程,而不是终止它。我们这么做通常是为了允许前台进程被移动到后台。 输入 Ctrl-z,可以停止一个前台进程。让我们试一下。在命令提示符下,执行 xlogo 命令, 然后输入 Ctrl-z:
[me@linuxbox ~]$ xlogo
[1]+ Stopped xlogo
[me@linuxbox ~]$
Signals
kill 命令被用来“杀死”程序。这样我们就可以终止需要杀死的程序。这里有一个例子:
[me@linuxbox ~]$ xlogo &
[1] 28401
[me@linuxbox ~]$ kill 28401
[1]+ Terminated xlogo
首先,我们在后台启动 xlogo 程序。shell 打印出这个后台进程的 jobspec 和 PID。下一步,我们使用 kill 命令,并且指定我们想要终止的进程 PID。也可以用 jobspec(例如,“%1”)来代替 PID。
虽然这个命令看上去很直白, 但是它的含义不止于此。这个 kill 命令不是真的“杀死”程序,而是给程序 发送信号。信号是操作系统与程序之间进行通信时所采用的几种方式中的一种。 在使用 Ctrl-c 和 Ctrl-z 的过程中我们已经看到信号的实际用法。当终端接受了其中一个按键组合后,它会给在前端运行 的程序发送一个信号。在使用 Ctrl-c 的情况下,会发送一个叫做 INT(Interrupt,中断)的信号;当使用 Ctrl-z 时,则发送一个叫做 TSTP(Terminal Stop,终端停止)的信号。程序,相应地,监听信号的到来,当程序 接到信号之后,则做出响应。一个程序能够监听和响应信号这件事允许一个程序做些事情, 比如,当程序接到一个终止信号时,它可以保存所做的工作。
通过 kill 命令给进程发送信号
kill 命令被用来给程序发送信号。它最常见的语法形式看起来像这样:
kill [-signal] PID...
如果在命令行中没有指定信号,那么默认情况下,发送 TERM(Terminate,终止)信号。kill 命令被经常 用来发送以下命令:
表 11-4: 常用信号
| 编号 | 名字 | 含义 |
|---|---|---|
| 1 | HUP | 挂起(Hangup)。这是美好往昔的残留部分,那时候终端机通过电话线和调制解调器连接到 远端的计算机。这个信号被用来告诉程序,控制的终端机已经“挂断”。 通过关闭一个终端会话,可以展示这个信号的作用。在当前终端运行的前台程序将会收到这个信号并终止。许多守护进程也使用这个信号,来重新初始化。这意味着,当一个守护进程收到这个信号后, 这个进程会重新启动,并且重新读取它的配置文件。Apache 网络服务器守护进程就是一个例子。 |
| 2 | INT | 中断。实现和 Ctrl-c 一样的功能,由终端发送。通常,它会终止一个程序。 |
| 9 | KILL | 杀死。这个信号很特别。尽管程序可能会选择不同的方式来处理发送给它的 信号,其中也包含忽略信号,但是 KILL 信号从不被发送到目标程序。而是内核立即终止 这个进程。当一个进程以这种方式终止的时候,它没有机会去做些“清理”工作,或者是保存工作。 因为这个原因,把 KILL 信号看作最后一招,当其它终止信号失败后,再使用它。 |
| 15 | TERM | 终止。这是 kill 命令发送的默认信号。如果程序仍然“活着”,可以接受信号,那么 这个它会终止。 |
| 18 | CONT | 继续。在一个停止信号后,这个信号会恢复进程的运行。 |
| 19 | STOP | 停止。这个信号导致进程停止运行,而不是终止。像 KILL 信号,它不被 发送到目标进程,因此它不能被忽略。 |
让我们试一下 kill 命令:
[me@linuxbox ~]$ xlogo &
[1] 13546
[me@linuxbox ~]$ kill -1 13546
[1]+ Hangup xlogo
在这个例子里,我们在后台启动 xlogo 程序,然后通过 kill 命令,发送给它一个 HUP 信号。 这个 xlogo 程序终止运行,并且 shell 指示这个后台进程已经接受了一个挂起信号。在看到这条 信息之前,你可能需要多按几次 enter 键。注意,信号既可以用号码,也可以用名字来指定, 包括在前面加上字母 “SIG” 的名字。
[me@linuxbox ~]$ xlogo 1] 13601
[me@linuxbox ~]$ kill -INT 13601
[1]+ Interrupt xlogo
[me@linuxbox ~]$ xlogo &
[1] 13608
[me@linuxbox ~]$ kill -SIGINT 13608
[1]+ Interrupt xlogo
重复上面的例子,试着使用其它的信号。记住,你也可以用 jobspecs 来代替 PID。
进程,和文件一样,拥有所有者,所以为了能够通过 kill 命令来给进程发送信号, 你必须是进程的所有者(或者是超级用户)。
表 11-5: 其它常用信号
| 编号 | 名字 | 含义 |
|---|---|---|
| 3 | QUIT | 退出 |
| 11 | SEGV | 段错误(Segmentation Violation)。如果一个程序非法使用内存,就会发送这个信号。也就是说, 程序试图写入内存,而这个内存空间是不允许此程序写入的。 |
| 20 | TSTP | 终端停止(Terminal Stop)。当按下 Ctrl-z 组合键后,终端发送这个信号。不像 STOP 信号, TSTP 信号由目标进程接收,且可能被忽略。 |
| 28 | WINCH | 改变窗口大小(Window Change)。当改变窗口大小时,系统会发送这个信号。 一些程序,像 top 和 less 程序会响应这个信号,按照新窗口的尺寸,刷新显示的内容。 |
通过下面的命令可以得到一个完整的信号列表:
[me@linuxbox ~]$ kill -l
通过 killall 命令给多个进程发送信号
也有可能通过 killall 命令,给匹配特定程序或用户名的多个进程发送信号。下面是 killall 命令的语法形式:
killall [-u user] [-signal] name...
为了说明情况,我们将启动一对 xlogo 程序的实例,然后再终止它们:
[me@linuxbox ~]$ xlogo &
[1] 18801
[me@linuxbox ~]$ xlogo &
[2] 18802
[me@linuxbox ~]$ killall xlogo
[1]- Terminated xlogo
[2]+ Terminated xlogo
记住,和 kill 命令一样,你必须拥有超级用户权限才能给不属于你的进程发送信号。
更多和进程相关的命令
因为监测进程是一个很重要的系统管理任务,所以有许多命令与它相关。玩玩下面几个命令:
表11-6: 其它与进程相关的命令
| 命令名 | 命令描述 |
|---|---|
| pstree | 输出一个树型结构的进程列表(processtree),这个列表展示了进程间父/子关系。 |
| vmstat | 输出一个系统资源使用快照,包括内存,交换分区和磁盘 I/O。 为了看到连续的显示结果,则在命令名后加上更新操作延时的时间(以秒为单位)。例如,“vmstat 5”。 ,按下 Ctrl-c 组合键, 终止输出。 |
| xload | 一个图形界面程序,可以画出系统负载随时间变化的图形。 |
| tload | terminal load与 xload 程序相似,但是在终端中画出图形。使用 Ctrl-c,来终止输出。 |
