有一种说法,现代计算机不是靠电力驱动,而是靠“鼠标”。多少应用程序的界面都是需要移动和点击鼠标来执行的。计算机本来的用意是把人类从反复单调的工作中解放出来,但摆在我们身边的残酷现实是我们每个人每天不得不反复单调地移动和点击鼠标,以确保养家糊口的工作能够顺利正确地完成。 别叹气,存在另一个世界,那就是命令行,让你暂时远离鼠标。对那些苦哈哈的程序猿来讲,这也许是另一种情调的工作方式。我们突然之间拥有了另一种意想不到的收获,例如我想看看用户目录下的文件大小,然后按升序排列产生个报表。如果用C/C++完成这项工作,至少得用好几十行代码,但是用一句命令行就能完成上面的功能。 du -s * | sort -nr > $HOME/space_report.txt 命令行有它的存在价值吧。还有把 Linux 桌面操作录制成一段视频,想起来就是一件复杂的任务,在Linux上用一句命令就能轻松搞定。 ffmpeg -f x11grab -s wxga -r 25 -i :0.0 -sameq /tmp/out.mpg 卖个关子,这个命令会在第18章作详细解释。 估计你可能会迫不及待地想要实验一下刚才所提到的命令,但是苦于现在都流行的图形界面,我们推荐的CentOS默认也进入了图形界面,看来要想做点实验还是有点难度的。不过不用着急,Linux的老手们一定是要命令行的,所以想通过键盘输入命令,一个合格的Linux发行版一定会做得十分方便,只是要先搞清楚一些概念。 1.4.1 开始执行命令 用户和系统不是直接打交道的,它们中间有个名字叫shell的联系人。我们从键盘中输入命令给shell,shell再把它交给操作系统去执行。 从哪里开始输入命令呢?当然你可以在字符界面输入命令(暂时先放放,稍后再看)。Linux系统还提供一个叫终端模拟器的程序。这个程序打开一个窗口,让我们与shell交流。Linux系统上的各种软件向来是百花齐放,模拟器终端也不例外,例如gnome-terminal、konsole、xterm、rxvt、kvt、nxterm和eterm等,而大多数Linux发行版会同时支持几种。 使用过Windows操作系统的人,在登录Linux桌面系统后,应该也能轻松地从菜单中选择启动终端的图标,点击就可以进入终端模拟器。当然你也可以在文件浏览器中找到叫“konsole”(KDE桌面)或“gnome-terminal”(GNOME桌面)的程序双击执行以打开终端窗口。更有意思的是你可以打开任意多个窗口,每个窗口给你一个shell会话。你从中选择了一个窗口开始尝试输入这个命令: $ cp /etc/resolv.conf /etc/resolv.conf.bak cp: cannot create regular file '/etc/resolv.conf.bak': Permission denied 太欺负人了吧,这么简单的命令都不让偶用。 你注意到没有,shell命令提示符是$,这意味着什么?这意味着你是普通用户,不是超级用户,你没有管理员权限。如果你是拥有管理员权限的root用户,提示符就变成#,你就可以在系统上做增加、删除和修改文件的操作。 1.4.2 文本和图形的切换 方才我们介绍的方法是目前最常用的在桌面环境下执行命令的方法,但是也有很多有“洁癖”的人喜欢使用纯粹的文本终端,这就需要进行图形和文本切换了,或者干脆就关闭图形界面。我们先搞定前者,后者会在后面的章节做十分详细的介绍。 要在文本和图形界面之间来回切换非常简单,只需要使用快捷键<Ctrl><Alt><F1>~ <F6>来回切换就行,具体什么效果大家可以自己实验,这个地方不同的Linux发行版会有不同的设定,所以本书就不好做定论。一般<Crtl><Alt><F1>代表图形界面,而剩下的5组快捷键对应5个不同的文本终端,我们推荐的CentOS就是这种设定。还有的设定是<Ctrl><Alt><F7>是图形界面,其他6组快捷键是6个不同的文本终端。 一般不建议使用这种方法来操作Linux,除非你有强烈的“洁癖”或遇到有“洁癖”的系统管理员。因为这种方法你能够使用到的独立文本终端最多只有6个。而前面介绍的在图形界面中使用终端模拟器的方法,则没有文本终端数量的限制。对于一个Linux老手来讲,文本终端永远都是多多益善的。很快你们就会有这种感觉了。 1.4.3 基础命令的操作 提及Linux基本命令,先给你讲述一个浪漫的故事。 曾经有个男孩很喜欢一个女孩,可是不敢表白。他想了一个办法,在Linux终端上输入: $ echo“这周六下午2:30,能在如嘉咖啡馆一起喝咖啡吗?”> love.txt 然后回车。接着他找来那张他喜欢的鼓浪屿图片(pic.png),使用命令: $ cat pic.png love.txt > pic1.png 重新做了一个图片文件。他鼓起勇气给那个女孩写了封邮件,邮件内容只是:请查阅附件。 女孩收到邮件,用图片浏览器打开后,看到的只是一张美丽的风景图片,有点纳闷。但是聪明的她,立刻猜到了那个男孩的用意。她用tail pic1.png,很快发现了秘密。 $ tail pic1.png PNG ▒ IHDRm�▒tEXtSoftwareAdobe ImageReadyq�<IDATxڼA0 [图片编码内容,一般人无法直接读懂……] )'EDDD���q��q^�cDDD�/�GDDDDm�y�w/�}!"""“这周六下午2:30,能在如嘉咖啡馆一起喝咖啡吗?” 太妙了,原来学好Linux通过Linux基础命令还可以交女朋友。(用这法注定孤独一生)加大马力,我们来认识更多的命令吧。不过我们会遇到一个问题,Linux命令太多了,数量至少有200多个,怎么记呀。其实谁也记不住这么多命令,剥茧抽丝抓重点,把重要的和经常使用的搞定了就行。按照它们在系统中所起的作用,我简单地做了一下分类说明,更为详细的下章还有。见表1-1的内容。 表 1-1 命 令 说 明 目录和文件处理 mkdir 建立目录 用法:mkdir [OPTION] DIRECTORY... 例:$ mkdir fangru ls 列出目录下的内容 用法:ls [OPTION]...[FILE]... 例:$ ls al fangru cd 更换工作目录 用法:cd [DIRECTORY] 例:$ cd fangru pwd 显示当前工作目录 用法:pwd (续) 命 令 说 明 cp 拷贝文件及其目录 用法:cp [OPTION]… SOURCE DEST 例:$ cp jie.txt jie.bak mv 移动(重命名)文件 用法:mv [OPTION]…SOURCE DEST 例:$ mv jieold jienew rm 删除文件或目录 用法:rm [OPTION]…FILE… 例:$ rm rf jie_dir 文本处理 cat 连结文件打印到标准输出 用法:cat [OPTION] [FILE]… 例:$cat pic.png love.txt > pic1.png 还记得那个命令行的故事吧?这个命令也常被用来查看小文件的内容 More 查看文件内容,当画面在显示满一页的时候暂停,按空格继续或按Q结束 用法:more [OPTIONS] FILE 例:$ more /etc/group less 与more类似,但是less允许利用光标键上下卷动文本内容进行浏览 用法: less [OPTIONS] FILE head 查看文件头部内容 用法:head [OPTION]… [FILE] … 例:$ head /etc/group tail 查看文件尾部内容 用法:tail [OPTION] … [FILE] … 例:tail /etc/group 比较常用的一个命令选项是-f,它可以用于跟随文件的增长,显示文件的最新内容。对于在线监控软件日志非常有帮助 Echo 显示一行文本 用法:echo [OPTION] [string] 例:echo $HOME (续) 命 令 说 明 系统管理 ps 强悍的进程查看命令 用法:ps [OPTION] 例:ps –aef kill 删除执行中的程序或工作 用法:kill [OPTION] 例:kill 9 3154 jobs 通过jobs命令查到后台正在执行的命令的序号(非进程号pid) 用法:jobs bg 指定号码(非进程号)的命令进程放到后台运行 用法:输入'ctrl+z' 然后输入 'bg<job id>' 例:bg <job id> fg 指定号码(非进程号)的命令进程放到前台运行 用法:fg <jobid> 文件系统 du 查看目录或文件所占用磁盘空间的大小 用法:du [OPTION]……[FILE]…… 例:du df 检查文件系统的磁盘空间占用情况。 用法:df [OPTION]……[FILE]…… 例:df 1.4.4 快捷键 有位童鞋正在Linux系统上开发一个中文相似度匹配的项目,工作相当努力,已经达到了废寝忘食的地步,但是使用的TF-IDF 算法的计算速度还是不尽人意。这时候,他决定先停一停,换换思路,玩玩俄罗斯方块放松一下。突然老板走过来,他下意识地使用<Ctrl><Alt><d>快速隐藏桌面。还好有惊无险,没有被老板发觉在玩游戏,否则又需要一大堆的解释。老板拍了拍他的肩膀走了过去,随后他用<Ctrl><Alt><d>又恢复了原有功能的显示。 举这个好玩的例子可不是让你照着做,而是为了告诉你Linux系统提供了很多快捷键提高命令行使用的工作效率,减少键盘的敲打以及拼写错误。说几个比较实用的快捷键,见表1-2所示,其他的你自己去挖掘。 表 1-2 常用快捷键 说 明 <Tab> 在文本终端下,使用TAB自动完成命令的输入,或者显示所有的可选项。超好用! <Shift><PgUp> 滚动文本终端输出。终端屏幕上一屏又一屏的提示信息,就可以用它向上翻滚查看这些信息 <Shift><PgDn> 回滚文本终端输出 <Ctrl><Alt><Delete> 文本终端下关机和重新启动 <Ctrl><Alt><Backspace> 关闭或重启X Window <Ctrl>a 到正在输入的命令行的首部 <Ctrl>e 到正在输入的命令行的尾部 <Ctrl>c 终止当前进程 <Ctrl>s 停止终端传输 <Ctrl>p 上一条执行的命令 <Ctrl>n 下一条执行的命令,前提是执行过<Ctrl>p <Ctrl>f 在当前命令输入中右移光标一个字符 <Ctrl>b 在当前命令输入中左移光标一个字符 <Alt>f 在当前命令输入中右移光标一个词 <Alt>b 在当前命令输入中左移光标一个词 <Ctrl>k 删除光标后的所有字符 <Ctrl>d 删除光标当前的字符 <Alt><Tab> 切换不同的程序窗口 <Alt><F1> 访问“开始”菜单 <Alt><鼠标左键> 拖曳并移动一个窗口 <Alt><PrintScreen> 把当前屏幕的快照存到剪贴板 <Ctrl><Alt><d> 哈哈,老板键。切换隐藏/显示桌面运行程序 使用快捷键太爽了!默认情况下,按TAB在bash中是可以自动补齐,但仅能自动补齐命令名和文件名。可是我们追求的目标是“更快、更高、更强”,那就安装bash-completion做个增强版的自动补齐吧。使用TAB键自动补齐几乎任何内容,包括参数、文件、目录甚至包名称等。安装方法很简单,下载到的包中包含一个bash-completion文件,将其放在/etc下。在/etc/bash.bashrc文件里加入可执行命令(这个操作需要root权限)。 # Run bash completion code if [ -r /etc/bash_completion ]; then # Source completion code. . /etc/bash_completion fi 1. 更快…… 举个例子。淘宝的预发环境中的Linux机器不允许直接登录。需要申请跳板机,通过跳板机才能登录预发机。在跳板机上,我们经常使用ssh 10.232.15.201操作命令,好麻烦呀。在/etc/hosts中我们加入一行“10.232.15.201 prerelease”。 然后我们使用complete -F _known_hosts ssh告诉ssh需要的主机名。一旦设置好了,我就可以通过敲[TAB]键完成主机名的输入:ssh p[TAB]。 另外你还可以定制私有命令的补齐功能,不过你需要自己编写shell脚本实现,然后把这个脚本放在/etc/bash_completion.d/下。在随后的章节,我们会学习shell脚本的编程。在学完之后,希望你会通过编写脚本产生自己的补齐功能。 2. 更高…… 有的命令太长,那就把命令缩短。命令别名(alias)就起到这个作用。例如在SUSE版本中有个命令别名的文件(/etc/profile.d/alias.bash)。它里面定义了许多命令别名,例如alias ..='cd ..', 那么在终端上输入“..”就相当于输入了“cd ..”直接回到上级目录,方便不? 3. 更强…… 在shell终端上还可以一下子运行多个命令,只需要用分号“;”把各个命令串起来就行: [命令1];[命令2];[命令3] 不管执行的命令结果如何,就是勇往直前地冲呀杀呀,把这些命令最终执行掉。但是有时候,这些命令之间是有关联的,就需要改改这种傻愣愣的工作方式。我们可以用“&&”把命令连接起来,只有前一个命令执行成功才执行下一个命令: [命令1]&&[命令2]&&[命令3] 如果需要等前一个命令执行失败才执行下一个命令,则要使用“||”把命令连接起来: [命令1]||[命令2]||[命令3] 哎,使用命令行的技巧还真不少,我们可以考虑出版一本专门讲述Linux命令行的参考书了:) 1.4.5 错误信息 $ %boast bash: fg: %boast: No such job. 当命令执行成功的时候终端屏幕上不显示任何信息,但是当发生错误的时候它经常会以一定的形式汇报错误。上面我开了一个关于Linux错误信息提示的玩笑。boast是吹牛的意思。我在终端上敲入“%boast”后,终端返回错误提示“No such job”,意思是没有这样的工作。不同的命令返回的错误信息格式有所不同,但是经常有如下格式: 命令名: 执行内容: 错误信息 例如: $ rm jie 给出的错误返回是: rm: cannot remove 'jie': No such file or directory. 那究竟发生了什么情况?当rm命令要删除jie这个文件,jie这个文件不存在,产生了代号为2的错误。这个错误代号的意思就是找不到相应的文件或目录。错误代码就被自动翻译成No such file or directory。由于错误代码有限(大约有一百多种),有可能许多不同问题对应于同一个错误代码,所以理解要执行的命令和错误信息的关系很重要。得到错误信息,让我欢喜让我忧,喜的是知道发生什么样的错误,忧的是对错误信息有可能百思不得其解,不知道如何去解决,这时候就得凭经验了。 errno.h包含一个完整的基本错误代码列表。除此之外,其他一些头文件(.h)也定义了自己的一些错误代码。代码1列出了系统定义的所有错误代码及错误描述。 代码1: #include<string.h> #include <errno.h> #include <stdio.h> int main(intargc, char ** argv) { int i = 0; for(i = 0; i< 256; i++) printf("errno.%02d is: %sn", i, strerror(i)); return 0; } 编译此程序用命令: gcc -Wall strerror.c 执行程序: ./a.out 这个程序的输出有点长,所以就不去浪费纸张了,你自己在电脑上看吧。 1.4.6 联机帮助——man很靠谱 遇到问题寻找帮助能加快解决问题的速度。在Linux系统上,有以下几个途径可以获得帮助: 1. 遇到问题,男人(man,其实是“手册”的简称)的帮助很靠谱。需要某个命令或者配置文件的帮助,就在终端输入: man 命令名 或 man 配置文件 屏幕就会显示对应命令系统的帮助手册。输入“q”退出帮助浏览器。 2. info 和 man 功能相似,但是包含更多的最新信息。 3. 使用“命令名 –help”得到一个简略容易消化的命令帮助。 4. 程序自带README文件或者其他帮助信息文件,例如在/usr/share/doc下的一些手册。 如何在man页中查找信息呢?浏览man页默认的工具是less。less的使用方法很简单。翻页用Space,查找用反斜杠“/”紧跟着正则表达式,用n查找下一个匹配项,用Shift+n查找前一个匹配项。如果这页里没有你感兴趣的,按Space翻到下页。更多的操作还是man一下less文档吧。 很多命令的man帮助页中涉及shell命令、系统调用和编程接口等多方面,而这些内容很可能会拥有相同的名字。例如“printf”,它既是shell命令,又是库函数。为了能够精确找到你需要的帮助信息,人们为它们进行了分类编号。比如3代表库函数,我们要使用这样的命令才能找到库函数printf的帮助信息: $ man 3 printf 否则的话,你得到的帮助信息是shell命令printf的帮助信息。可是man对帮助信息做了哪些分类,分别都用什么编号来代表的呢?这个问题我们不用管,第3章再说。当前为了解决这种分类问题我们有一个折中的办法,就是使用“-a”命令选项,它会把所有跟你给定的命令名有关的帮助信息都列出来。例如: $ man -a printf 慢慢看吧,如果觉得当前的信息不是你需要的,按“q”之后会显示另外一个分类的信息,直到找到自己需要的为止。当然,有些时候你可能一无所获,最大的可能就是你记错了关键字。 还有,帮助信息中的“SEE ALSO”经常是被遗忘的角落,但是我经常会在这里发现其他有用的命令或库函数,千万不要放过它。 1.4.7 致命的Linux命令 别以为我是在开玩笑。有些Linux命令轻则造成数据丢失,重则导致系统瘫痪。你看这位同学漫不经心,以root身份敲入了rm -rf /,强制删除 / 目录下的所有文件,这代价可是很惨痛的(相当于系统自杀)。 还有一个很好玩的例子,我用旺旺聊天的形式给你讲述: 小雪2012-08-25 15:28:10: 在你Linux系统上输入这串东西:(){ :|:& }; 灰猫2012-08-25 15:28:34: 长得这么怪? 小雪2012-08-25 15:28:41: 试试看看是什么结果。谢了。 灰猫2012-08-25 15:28:44: 不好了。终端一直出现下面的提示: -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable -bash: fork: retry: Resource temporarily unavailable 很惨啊。 小雪2012-08-25 15:29:02: 哈哈,真的很惨。 灰猫2012-08-25 15:29:21: Ctrl+C都是不管用的。 小雪2012-08-25 15:29:21: 即便退出这个终端也是没有用的。 灰猫2012-08-25 15:29:31: 最后全都是这个。-bash: pipe error: Cannot allocate memory -bash: pipe error: Cannot allocate memory root用户搞不定,因为killall的速度受到了影响,只能重启机器了。 小雪2012-08-25 15:30:15:这就是著名fork炸弹。看来危害不小。 灰猫2012-08-25 15:30:34:别幸灾乐祸了。能告诉我什么原理吗? 小雪2012-08-25 15:31:43: 把:(){ :|:& };写成下面格式你就看懂了 :() { :|:& }; 灰猫2012-08-25 15:32:13: 明白了。“:”函数里面定义操作是后台执行“:”函数重定向到“:”函数,“:”函数的递归调用。 小雪2012-08-25 15:32:15: 是滴。系统执行海量的进程直到死亡。 灰猫2012-08-25 15:32:43: 这样的代码不好分析,主要是因为不清楚“:”是可以做为函数名的。 小雪2012-08-25 15:33:12: Quite right。另外为了防止这个问题的出现,要限制赋予root权限的用户数量以及单用户的进程数。 灰猫2012-08-25 15:34:12: 哈哈。是的,拥有root权限的用户操作不慎很容易给系统造成破坏。 故事还没有结束。如何限制用户的进程数呢?我们可以在/etc/security/limits.conf文件末尾加入一行: * hard nproc 200 限制用户的进程数为200,但root用户不会受这个限制。 这个命令行还涉及shell脚本编程,我们将在后面的章节来学习。