Linux入门教程
以下内容引用自yzh的PA实验课程网站,并有少量修改和补充。
探索命令行
Linux命令行中的命令使用格式都是相同的:
命令名称 参数1 参数2 参数3 ...参数之间用任意数量的空白字符分开。关于命令行,可以先阅读一些基本常识。然后我们介绍最常用的一些命令:
ls用于列出当前目录(即"文件夹")下的所有文件(或目录)。目录会用蓝色显示。ls -l可以显示详细信息。pwd能够列出当前所在的目录。cd DIR可以切换到DIR目录。在Linux中,每个目录中都至少包含两个目录:.指向该目录自身,..指向它的上级目录。文件系统的根是/。touch NEWFILE可以创建一个内容为空的新文件NEWFILE,若NEWFILE已存在,其内容不会丢失。cp SOURCE DEST可以将SOURCE文件复制为DEST文件; 如果DEST是一个目录,则将SOURCE文件复制到该目录下。mv SOURCE DEST可以将SOURCE文件重命名为DEST文件; 如果DEST是一个目录,则将SOURCE文件移动到该目录下。mkdir DIR能够创建一个DIR目录。rm FILE能够删除FILE文件; 如果使用-r选项则可以递归删除一个目录。删除后的文件无法恢复,使用时请谨慎!man可以查看命令的帮助。例如man ls可以查看ls命令的使用方法。灵活应用man和互联网搜索,可以快速学习新的命令。
man的功能不仅限于此。man后可以跟两个参数,可以查看不同类型的帮助(请在互联网上搜索)。例如当你不知道C标准库函数freopen如何使用时,可以键入命令。
思考: 上述各个命令除了cd之外都能找到它们的manpage,这是为什么? 如果你思考后仍然感到困惑,试着到互联网上寻找答案。
下面给出一些常用命令使用的例子,你可以键入每条命令之后使用ls查看命令执行的结果:
提示: 仅仅了解这些最基础的命令行知识是不够的。通常,我们可以抱着如下的信条: 只要我们能想到的,就一定有方便的办法能够办到。因此当你想要完成某件事却又不知道应该做什么的时候,请向Google求助。如果你想以Linux作为未来的事业,那就可以去图书馆或互联网上找一些相关的书籍来阅读。
统计代码行数
第一个例子是统计一个目录中(包含子目录)中的代码行数。如果想知道当前目录下究竟有多少行的代码,就可以在命令行中键入如下命令:
如果用man find查看find操作的功能,可以看到find是搜索目录中的文件。Linux中一个点。始终表示Shell当前所在的目录,因此find .实际能够列出当前目录下的所有文件。如果在文件很多的地方键入find .,将会看到过多的文件,此时可以按CTRL + c退出。
同样,用man查看grep的功能——"print lines matching a pattern"。grep实现了输入的过滤,我们的grep有一个参数,它能够匹配以.c或.h结束的文件。正则表达式是处理字符串非常强大的工具之一,每一个程序员都应该掌握其相关的知识。有兴趣的同学可以首先阅读一个基础的教程。 上述的grep命令能够提取所有.c和.h结尾的文件。
刚才的find和grep命令,都从标准输入中读取数据,并输出到标准输出。关于什么是标准输入输出,请参考这里。连接起这两个命令的关键就是管道符号|。这一符号的左右都是Shell命令,A | B的含义是创建两个进程A和B,并将A进程的标准输出连接到B进程的标准输入。这样,将find和grep连接起来就能够筛选出当前目录(.)下所有以.c或.h结尾的文件。
我们最后的任务是统计这些文件所占用的总行数,此时可以用man查看wc命令。wc命令的-l选项能够计算代码的行数。xargs命令十分特殊,它能够将标准输入转换为参数,传送给第一个参数所指定的程序。所以,代码中的xargs wc -l就等价于执行wc -l aaa.c bbb.c include/ccc.h ...,最终完成代码行数统计。
思考: 如果要统计python项目的代码量,应该如何修改上述命名?
统计磁盘使用情况
以下命令统计/usr/share目录下各个目录所占用的磁盘空间:
du是磁盘空间分析工具,du -sc将目录的大小顺次输出到标准输出,继而通过管道传送给sort。sort是数据排序工具,其中的选项-n表示按照数值进行排序,而-r则表示从大到小输出。sort可以将这些参数连写在一起。
然而我们发现,/usr/share中的目录过多,无法在一个屏幕内显示。此时,我们可以再使用一个命令: more或less。
此时将会看到输出的前几行结果。more工具使用空格翻页,并可以用q键在中途退出。less工具则更为强大,不仅可以向下翻页,还可以向上翻页,同样使用q键退出。
在Linux下编写Hello World程序
Linux中用户的主目录是/home/用户名称,如果你的用户名是user,你的主目录就是/home/user。用户的home目录可以用波浪符号~替代,例如临时文件目录/home/user/Templates可以简写为~/Templates。现在我们就可以进入主目录并编辑文件了。如果Templates目录不存在,可以通过mkdir命令创建它:
创建成功后,键入
可以完成目录的切换。注意在输入目录名时,tab键可以提供联想。
你感到键入困难吗? 你可能会经常要在终端里输入类似于
cd AVeryVeryLongFileName的命令,你一定觉得非常烦躁。回顾上面所说的原则之一: 如果你感到有什么地方不对,就一定有什么好办法来解决。试试tab键吧。 Shell中有很多这样的小技巧,你也可以使用其他的Shell例如zsh,提供更丰富好用的功能。总之,尝试和改变是最重要的。
进入了正确的目录后,输入相应的命令就能够开始编辑文件。例如输入
就能开启一个文件编辑。例如可以键入如下代码(对于首次使用vi或vim的同学,键入代码可能会花去一些时间,在编辑的同时要大量查看网络上的资料):
保存后就能够看到hello.c的内容了。终端中可以用cat hello.c查看代码的内容。如果要将它编译,可以使用gcc命令:
gcc的-o选项指定了输出文件的名称,如果将-o hello改为-o hi,将会生成名为hi的可执行文件。如果不使用-o选项,则会默认生成名为a.out的文件,它的含义是assembler output。在命令行输入
就能够运行改程序。命令中的./是不能少的,点代表了当前目录,而./hello则表示当前目录下的hello文件。与Windows不同,Linux系统默认情况下并不查找当前目录,这是因为Linux下有大量的标准工具(如test等),很容易与用户自己编写的程序重名,不搜索当前目录消除了命令访问的歧义。
使用重定向
有时我们希望将程序的输出信息保存到文件中,方便以后查看。例如你编译了一个程序myprog,你可以使用以下命令对myprog进行反汇编,并将反汇编的结果保存到output文件中:
>是标准输出重定向符号,可以将前一命令的输出重定向到文件output中。这样,你就可以使用文本编辑工具查看output了。
但你会发现,使用了输出重定向之后,屏幕上就不会显示myprog输出的任何信息。如果你希望输出到文件的同时也输出到屏幕上,你可以使用tee命令:
使用输出重定向还能很方便地实现一些常用的功能,例如
如果myprog需要从键盘上读入大量数据(例如一个图的拓扑结构),当你需要反复对myprog进行测试的时候,你需要多次键入大量相同的数据。为了避免这种无意义的重复键入,你可以使用以下命令:
<是标准输入重定向符号,可以将前一命令的输入重定向到文件data中。这样,你只需要将myprog读入的数据一次性输入到文件data中,myprog就会从文件data中读入数据,节省了大量的时间。
下面给出了一个综合使用重定向的例子:
这个命令在运行myprog的同时,指定其从文件data中读入数据,并将其输出信息打印到屏幕和文件output中。time工具记录了这一过程所消耗的时间,最后你会在屏幕上看到myprog运行所需要的时间。如果你只关心myprog的运行时间,你可以使用以下命令将myprog的输出过滤掉:
/dev/null是一个特殊的文件,任何试图输出到它的信息都会被丢弃,你能想到这是怎么实现的吗? 总之,上面的命令将myprog的输出过滤掉,保留了time的计时结果,方便又整洁。
使用Makefile管理工程
大规模的工程中通常含有几十甚至成百上千个源文件(Linux内核源码有25000+的源文件),分别键入命令对它们进行编译是十分低效的。Linux提供了一个高效管理工程文件的工具: GNU Make。我们首先从一个简单的例子开始,考虑上文提到的Hello World的例子,在hello.c所在目录下新建一个文件Makefile,输入以下内容并保存:
返回命令行,键入make,你会发现make程序调用了gcc进行编译。Makefile文件由若干规则组成,规则的格式一般如下:
我们来解释一下上文中的hello规则。这条规则告诉make程序,需要生成的目标文件是hello,它依赖于文件hello.c,通过执行命令gcc hello.c -o hello来生成hello文件。
如果你连续多次执行make,你会得到"文件已经是最新版本"的提示信息,这是make程序智能管理的功能。如果目标文件已经存在,并且它比所有依赖文件都要"新",用于生成目标的命令就不会被执行。你能想到make程序是如何进行"新"和"旧"的判断的吗?
上面例子中的clean规则比较特殊,它并不是用来生成一个名为clean的文件,而是用于清除编译结果,并且它不依赖于其它任何文件。make程序总是希望通过执行命令来生成目标,但我们给出的命令rm hello并不是用来生成clean文件,因此这样的命令总是会被执行。你需要键入make clean命令来告诉make程序执行clean规则,这是因为make默认执行在Makefile中文本序排在最前面的规则。但如果很不幸地,目录下已经存在了一个名为clean的文件,执行make clean会得到"文件已经是最新版本"的提示。解决这个问题的方法是在Makefile中加入一行PHONY: clean,用于指示"clean是一个伪目标"。这样以后,make程序就不会判断目标文件的新旧,伪目标相应的命令序列总是会被执行。
对于一个规模稍大一点的工程,Makefile文件还会使用变量,函数,调用Shell命令,隐含规则等功能。如果你希望学习如何更好地编写一个Makefile,请到互联网上搜索相关资料。
Last updated