第二周(9.14-9.20):

学习计时:共17小时

实验楼:6小时  读书:1小时  代码:3小时  作业:0小时  博客:7小时

一、学习目标

1. 能够独立安装Linux操作系统  

2. 能够熟练使用Linux系统的基本命令  

3. 熟练使用Linux中用户管理命令/系统相关命令/文件目录相关命令/打包压缩相关命令/比较合并相关命令/网络相关命令等

4. 熟练应用“搜索”进行举一反三的学习

二、学习资源

1. 课程资料:https://www.shiyanlou.com/courses/413   实验一

2. Linux 基础入门:https://www.shiyanlou.com/courses/1(重点,第一次课考核内容全部从这里面出)

3.  Linux命令:en   cn

三、学习方法

1.  进度很重要:必须跟上每周的进度,阅读,练习,问答,项目。我会认真对待每一位同学,请你不要因为困难半途而废。

2. 问答很重要:遇到知识难点请多多提问,这是你的权利更是您对自己负责的义务。问答到博客园讨论小组:http://group.cnblogs.com/103791/

3. 实践很重要:解决书中习题,实践书中实例,完成每周项目,才算真的消化了这本好书。通过实验楼环境或自己安装的虚拟机在实践中进行学习

4. 实验报告很重要:详细记录你完成项目任务的思路,获得老师点评和帮助自己复习。学习完成后在博客园中(http://www.cnblogs.com/)把学习过程通过博客发表,博客标题“信息安全系统设计基础第一周学习总结”

四、学习任务

(提示:请将要求学生完成的任务、测验或思考题列在此处)

1. 重点学习 cheat/find/locate/grep/man/whereis/which/apt-get

   查找帮助文档、各种示例多多练习,这几个命令会贯穿我们整个学习的学习,掌握这几个命令就可以很好学习其他命令了。

2. 这学期需要掌握的命令有ac,apt-get,bzip2,cat,chgrp,chmod,chown,clear,compress,cp,dd,df,diff,du,dump,evn,find,finger,free,grep,gzip,head,kill,less,ln,locate,l,gout,ls,man,mkdir,more,mount,mt,mv,netstat,nslookup,od,passwd,patch,ps,pstop,pwd,rm,shell,sort,ssh,stty,tail,tar,telnet,touch,tree,uname,unzip,vi,vim,whereis,which,who,write等

3. 测试示例:

  • 请在虚拟机中安装DDD软件(其他软件)
  • 请演示怎么判断DDD软件能不能安装
  • 请查找系统中50M以上的文件
  • 请查找系统中两天前修改过的且小于5M的文件
  • 请问如何查找操作系统的信息
  • 请查找当前目录下所有*.c文件中哪个文件中包含main函数
  • 请建立一个目录,里面建立两个子文目录,如何一条命令删除三个目录?
  • 如何把一个目录及子目录拷贝到自己的主目录中
  • ...

、后续学习预告(可选):

Linux下C语言编程基础:

VIM进行编辑

GCC进行编译

GDB进行调试

Make进行自动化

、学习过程

(提示:此处由学生填写,学习过程,学习笔记,代码编译,运行结果,思考等)

1. 重要知识点总结梳理:(参考资料:实验楼Linux基础入门)

1Linux终端与图形界面切换

Linux 默认提供了 6 个纯命令行界面的 “terminal”来让用户登录,在物理机系统上你可以通过使用[Ctrl]+[Alt]+[F1][F6]进行切换。

切换到其中一个终端后想要切换回图形界面:[Ctrl]+[Alt]+[F7]

2)命令解析器

核:UNIX/Linux 内核

壳Shell:是指“提供给使用者使用界面”的软件(命令解析器),隐藏了操作系统底层的细节。普通意义上的Shell 就是可以接受用户输入命令的程序。

3)快捷键

Tab使用Tab键来进行补全,补全命令,补全目录,补全命令参数。当忘记某个命令的全称时可以只输入它的开头的一部分然后按下Tab键就可以得到提示或者帮助完成。
例:输入cd之后按Tab键,会出现:
之后按Tab在补全选项中切换:
  或 
[Ctrl+c]强行终止当前程序。
例:tail命令,回显输入  无法跳出;
此时按Ctrl+C就可以跳出来。
例2:find /命令之后,使用Ctrl+C:

Ctrl+d    键盘输入结束或退出终端

Ctrl+s    暂定当前程序,暂停后按下任意键恢复运行

Ctrl+z    将当前程序放到后台运行,恢复到前台为命令fg

Ctrl+a   将光标移至输入行头,相当于Home键

Ctrl+e       将光标移至输入行末,相当于End键

Ctrl+k       删除从光标所在位置到行末

Alt+Backspace  向前删除一个单词

Shift+PgUp     将终端显示向上滚动

Shift+PgDn     将终端显示向下滚动

方向键上   显示输入命令的历史记录

4)通配符

通配符是一种特殊语句,主要有星号(*)和问号(?),用来对对字符串进行模糊匹配(比如文件名,参数名)。当查找文件夹时,可以使用它来代替一个或多个真正字符;当不知道真正字符或者懒得输入完整名字时,常常使用通配符代替一个或多个真正的字符。
例:
创建多个文件:

Shell 常用通配符:

*     匹配 0 或多个字符

?      匹配任意一个字符

[list]       匹配 list 中的任意单一字符

[!list]      匹配 除list 中的任意单一字符以外的字符

[c1-c2]    匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z]

{string1,string2,...}       匹配 sring1 或 string2 (或更多)其一字符串

{c2..c2}  匹配 c1-c2 中全部字符 如{1..10}

5)帮助

man man命令
man 中使用搜索:/<你要搜索的关键字>
n :切换到下一个关键字所在处
shift+n:上一个关键字所在处
Space(空格键):翻页
Enter(回车键):向下滚动一行
j,k(vim编辑器的移动键):进行向前向后滚动一行
h:显示使用帮助(因为man使用less作为阅读器,实为less工具的帮助)
q:退出
想要获得更详细的帮助,你还可以使用info命令,不过通常使用man就足够了。
如果你知道某个命令的作用,只是想快速查看一些它的某个具体参数的作用,那么你可以使用--help参数,大部分命令都会带有这个参数。
例:输入ls –help命令:

5)输出图形字符命令

1.banner

安装命令:sudo apt-get update;sudo apt-get install sysvbanner
然后输入显示命令banner hanyuqi:
输入命令:printerbanner –w 25 HYQ:

2.toilet

安装命令:sudo apt-get install toilet
显示命令:
可以添加颜色。我们可以运行下列命令看到颜色:toilet -f mono12 -F metal mylinuxbook12:

3.figlet

安装命令:sudo apt-get install figlet
显示命令:

6查看用户

 
whoami:要查看当前登录用户的用户名
who am i:第一列表示打开当前伪终端的用户的用户名,第二列的 pts/0 中 pts 表示伪终端,第三列则表示当前伪终端的启动时间。
who 命令其它常用参数:
-a    打印能打印的全部
-d    打印死掉的进程
-m   同am i,mom likes
-q    打印当前登录用户数及用户名
-u    打印当前登录用户登录信息
-r     打印运行等级
例:

7)创建用户

在 Linux 系统里, root 账户拥有整个系统至高无上的权利,比如新建/添加用户。
新建一个新用户hanyuqi:
创建好一个用户,可以使用你创建的用户登录了,使用如下命令切换登录用户
su –l hanyuqi:
退出当前用户:exit / Ctrl+d

8)用户组

在 Linux 里面每个用户都有一个归属(用户组),用户组简单地理解就是一组用户的集合,它们共享一些资源和权限,同时拥有私有资源。
如何知道自己属于哪些用户组呢?
方法一:groups 用户名
 
每次新建用户如果不指定用户组的话,默认会自动创建一个与用户名相同的用户组(差不多就相当于家长的意思,或者说是老总)。默认情况下在sudo用户组里的可以使用sudo命令获得root权限。
方法二:cat etc/group | sort
这里 cat 命令用于读取指定文件的内容并打印到终端输出,后面会详细讲它的使用。 | sort 表示将读取的文本进行一个字典排序再输出,然后你将看到如下一堆输出,你可以在最下面看到 shiyanlou 的用户组信息。
过滤信息(x指的是密码不可见):
 

9)将其它用户加入 sudo 用户组

使用 usermod 命令可以为用户添加用户组,同样使用该命令你必需有 root 权限,你可以直接使用 root 用户为其它用户添加用户组,或者用其它已经在 sudo 用户组的用户使用 sudo 命令获取权限来执行该命令
这里用 shiyanlou 用户执行 sudo 命令将hanyuqi添加到sudo用户组,让它也可以使用 sudo 命令获得 root 权限:
 

10)删除用户

sudo deluser hanyuqi –remove-home

11)查看文件权限

ls –l:

文件类型:Linux中一切皆文件
文件权限:一个目录要同时具有读权限和执行权限才可以打开,而一个目录要有写权限才允许在其中创建其它文件,这是因为目录文件实际保存着该目录里面的文件的列表等信息。
连接数:链接到该文件所在的 inode 结点的文件名数目。
文件大小:以 inode 结点大小为单位来表示的文件大小。ls 加上 -lh 参数来更直观的查看文件的大小

常用:

显示除了 '.'(当前目录),'..' 上一级目录之外的所有包含隐藏文件(Linux 下以 '.' 开头的文件为隐藏文件):

同时使用 '-A' 和 '-l' 参数:

 

查看某一个目录的完整属性,而不是显示目录里面的文件属性:

 

显示所有文件大小,并以普通人类能看懂的方式呈现:

 

其中小 s 为显示文件大小,大 S 为按文件大小排序,若需要知道如何按其它方式排序,请使用“man”命令查询。

12)变更文件所有者

切换登录用户hanyuqi,输入密码后新建一个文件,命名为“Lenovo”:
 
变更文件所有者:
 

13)修改文件权限

文件不想被其他用户读、写、执行

方法一:二进制数字表示

方法二:加减赋值操作

'g''o'还有'u',分别表示group,others,user,'+','-' 就分别表示增加和去掉相应的权限。

14)目录路径

进入上一级目录:cd ..

cd ~ # 或者 cd /home/<你的用户名>

使用 pwd 获取当前路径:

绝对路径:以根"/"目录为起点的完整路径,以你所要到的目录为终点,表现形式如: /usr/local/bin,表示根目录下的 usr 目录中的 local 目录中的 bin 目录。

相对路径:相对于你当前的目录的路径,相对路径是以当前目录 . 为起点,以你所要到的目录为终点,表现形式如: usr/local/bin (这里假设你当前目录为根目录)。你可能注意到,我们表示相对路径实际并没有加上表示当前目录的那个 . ,而是直接以目录名开头,因为这个 usr 目录为 / 目录下的子目录,是可以省略这个 . 的(以后会讲到一个类似不能省略的情况);如果是当前目录的上一级目录,则需要使用 .. ,比如你当前目录为“home”目录,根目录就应该表示为 ../../ ,表示上一级目录("home"目录)的上一级目录("/"目录)。

以"home"目录为起点,分别以绝对路径和相对路径的方式进入 /usr/local/bin 目录:

# 绝对路径  $ cd /usr/local/bin        # 相对路径  $ cd ../../usr/local/bin

 

提示:在进行目录切换的过程中请多使用 Tab 键自动补全,可避免输入错误,连续按两次Tab可以显示全部候选结果。

15)文件操作

使用 touch 命令创建空白文件,其主要是来更改已有文件的时间戳的(如最近访问时间,最近修改时间),但其在不加任何参数的情况下,只指定一个文件名,则可以创建一个为指定文件名的空白文件(不会覆盖已有同名文件),也可以同时指定该文件的时间戳。

创建名为mytest的空白文件:

新建目录:创建名为"mydir"的空目录:$ mkdir mydir

使用 -p 参数,同时创建父目录(如果不存在该父目录),如下我们同时创建一个多级目录(这在有时候安装软件,配置安装路径时非常有用):

 

复制文件:cp命令

复制目录:果直接使用cp命令,复制一个目录的话,会出现如下错误:

 

要成功复制目录需要加上-r或者-R参数,表示递归复制:$ cp -r father family

删除文件:$ rm test

强制删除:$ rm -f test

 

删除目录:$rm -r family

移动文件:mv 源目录文件 目的目录

文件重命名:mv 旧的文件名 新的文件名

批量重命名:

# 使用通配符批量创建 5 个文件

$ touch file{1..5}.txt

# 批量将这 5 个后缀为 .txt 的文本文件重命名为以 .c 为后缀的文件

$ rename 's/\.txt/\.c/' *.txt

# 批量将这 5 个文件,文件名改为大写

$ rename 'y/a-z/A-Z/' *.c

16)查看文件

使用cat,tac和nl命令查看文件:这两个命令都是用来打印文件内容到标准输出(终端),其中cat为正序显示,tac倒序显示。
使用more和less命令分页查看文件。
使用head和tail命令查看文件

17)召唤“眼睛”

xeyes

放在后台:$ nohup xeyes &

 

18)变量

使用declare命令创建一个变量名为 tmp 的变量:$ declare tmp
其实也可以不用 declare 预声明一个变量,直接即用即创建,这里只是告诉你 declare 的作用,这在创建其它指定类型的变量(如数组)时会用到。
使用=号赋值运算符为变量 tmp 赋值为 shiyanlou:$ tmp=shiyanlou
读取变量的值,使用echo命令和$符号($符号用于表示引用一个变量的值,初学者经常会忘记输入):$ echo $tmp
 
注意:关于变量名,并不是任何形式的变量名都是可用的,变量名只能是英文字母,数字或者下划线,且不能以数字作为开头。

19)环境变量

你可以更直观的使用vimdiff工具比较一下它们之间的差别:
$ temp=shiyanlou
$ export temp_env=shiyanlou
$ env|sort>env.txt
$ export|sort>export.txt
$ set|sort>set.txt
上述操作将命令输出通过管道|使用sort命令排序,再重定向到对象文本文件中。
$ vimdiff env.txt export.txt set.txt
 
使用vimdiff工具比较导出的几个文件的内容。
关于环境变量,可以简单的理解成在当前进程的子进程是否有效,有效则为环境变量,否则不是(有些人也将所有变量统称为环境变量,只是以全局环境变量和局部环境变量进行区分,我们只要理解它们的实质区别即可)。我们这里用export命令来体会一下,先在 Shell 中设置一个变量temp=shiyanlou,然后再新创建一个子 Shell 查看temp变量的值:
注意:为了与普通变量区分,通常我们习惯将环境变量名设为大写

20)命令的查找路径与顺序

变量修改

变量的修改有以下几种方式:

变量设置方式

说明

${变量名#匹配字串}

从头向后开始匹配,删除符合匹配字串的最短数据

${变量名##匹配字串}

从头向后开始匹配,删除符合匹配字串的最长数据

${变量名%匹配字串}

从尾向前开始匹配,删除符合匹配字串的最短数据

${变量名%%匹配字串}

从尾向前开始匹配,删除符合匹配字串的最长数据

${变量名/旧的字串/新的字串}

将符合旧字串的第一个字串替换为新的字串

${变量名//旧字串/新的字串}

将符合旧字串的全部字串替换为新的字串

比如要修改我们前面添加到 PATH 的环境变量。为了避免操作失误导致命令找不到,我们先将 PATH 赋值给一个新的自定义变量 path:

$ path=$PATH

$ echo $path

$ path=${path%/home/shiyanlou/mybin}

# 或使用通配符,*表示任意多个任意字符

$ path=${path%*/mybin}

变量删除

可以使用unset命令删除一个环境变量:$ unset temp

21)搜索文件

与搜索相关的命令常用的有如下几个whereis,which,find,locate

 

-mtime n: n 为数字,表示为在n天之前的”一天之内“修改过的文件

-mtime +n: 列出在n天之前(不包含n天本身)被修改过的文件

-mtime -n: 列出在n天之前(包含n天本身)被修改过的文件

newer file: file为一个已存在的文件,列出比file还要新的文件名

列出 home 目录中,当天(24 小时之内)有改动的文件:

$ find ~ -mtime 0

列出用户家目录下比Code文件夹新的文件:

$ find ~ -newer /home/shiyanlou/Code

 

22)“数字雨”

 

23)文件打包和解压缩

zip压缩打包程序

  • 使用zip打包文件夹:

$ zip -r -q -o shiyanlou.zip /home/shiyanlou

$ du -h shiyanlou.zip

$ file shiyanlou.zip

  • 创建加密zip包

使用-e参数可以创建加密压缩包:

$ zip -r -e -o shiyanlou_encryption.zip /home/shiyanlou

使用unzip命令解压缩zip文件

将shiyanlou.zip解压到当前目录:$ unzip shiyanlou.zip

使用安静模式,将文件解压到指定目录:

$ unzip -q shiyanlou.zip -d ziptest

 

24)文件系统操作与管理

1.查看磁盘和目录的容量

使用 df 命令查看磁盘的容量

$ df

在实验楼的环境中你将看到如下的输出内容:

但在实际的物理主机上会更像这样:

cowsay命令,可以让你在终端里以一种动物说话的形式打印出一段话。

# 安装
$ sudo apt-get install cowsay

# 默认是一只牛
$ cowsay hello shiyanlou

# 加上'-l'参数打印所有支持的动物(其实不只是动物)种类
$ cowsay -l

# 使用'-f'参数选择动物种类
$ cowsay -f elephant hello shiyanlou

# 此外它还可以结合我们之前的作业讲过的 fortune 命令一起使用
$ fortune | cowsay -f daemon

(25)顺序执行多条命令

通常情况下,我们每次只能在终端输入一条命令,按下回车执行,执行完成后,我们再输入第二条命令,然后再按回车执行…… 你可能会遇到如下使用场景:我需要使用apt-get安装一个软件,然后安装完成后立即运行安装的软件(或命令工具),又恰巧你的主机才更换的软件源还没有更新软件列表(比如之前我们的环境中,每次重新开始实验就得sudo apt-get update,现在已经没有这个问题了),那么你可能会有如下一系列操作:

$ sudo apt-get update
# 等待——————————然后输入下面的命令
$ sudo apt-get install some-tool
# 等待——————————然后输入下面的命令
$ some-tool

这时你可能就会想要是我可以一次性输入完,让它自己去一次执行各命令就好了,这就是我们这一小节要解决的问题。

简单的顺序执行你可以使用;来完成,比如上述操作你可以:

$ sudo apt-get update;sudo apt-get install some-tool;some-tool
# 让它自己运行

(26)有选择的执行命令

关于上面的操作,不知你有没有思考过一个问题,如果我们在让它自动顺序执行命令时,前面的命令执行不成功,而后面的命令又依赖与上一条命令的结果,那么就会造成花了时间,最终却得到一个错误的结果,而且有时候直观的看你还无法判断结果是否正确。那么我们需要能够有选择性的来执行命令,比如上一条命令执行成功才继续下一条,或者不成功又该做出其它什么处理,比如我们使用which来查找是否安装某个命令,如果找到就执行该命令,否则什么也不做(虽然这个操作没有什么实际意义,但可帮你更好的理解一些概念):

$ which cowsay>/dev/null && cowsay -f head-in ohch~

cut 命令,打印每一行的某一字段

打印/etc/passwd文件中以:为分隔符的第1个字段和第6个字段分别表示用户名和其家目录:

$ cut /etc/passwd -d ':' -f 1,6

打印/etc/passwd文件中每一行的前N个字符:

# 前五个(包含第五个)
$ cut /etc/passwd -c -5
# 前五个之后的(包含第五个)
$ cut /etc/passwd -c 5-
# 第五个
$ cut /etc/passwd -c 5
# 2到5之间的(包含第五个)
$ cut /etc/passwd -c 2-5

(27)sort 排序命令

这个命令前面我们也是用过多次,功能很简单就是将输入按照一定方式排序,然后再输出,它支持的排序有按字典排序,数字排序,按月份排序,随机排序,反转排序,指定特定字段进行排序等等。

默认为字典排序:

$ cat /etc/passswd | sort

反转排序:

$ cat /etc/passwd | sort -r

按特定字段排序:

$ cat /etc/passwd | sort -t':' -k 3

上面的-t参数用于指定字段的分隔符,这里是以":"作为分隔符;-k 字段号用于指定对哪一个字段进行排序。这里/etc/passwd文件的第三个字段为数字,默认情况下是一字典序排序的,如果要按照数字排序就要加上-n参数:

$ cat /etc/passwd | sort -t':' -k 3 -n

(28)文本处理命令

1.tr 命令

tr 命令可以用来删除一段文本信息中的某些文字。或者将其进行转换。

使用方式:tr [option]...SET1 [SET2]

常用的选项有:

选项说明
-d 删除和set1匹配的字符,注意不是全词匹配也不是按字符顺序匹配
-s 去除set1指定的在输入文本中连续并重复的字符

操作举例:

# 删除 "hello shiyanlou" 中所有的'o','l','h'
$ echo 'hello shiyanlou' | tr -d 'olh'
# 将"hello" 中的ll,去重为一个l
$ echo 'hello' | tr -s 'l'
# 将输入文本,全部转换为大写或小写输出
$ cat /etc/passwd | tr '[:lower:]' '[:upper:]'
# 上面的'[:lower:]' '[:upper:]'你也可以简单的写作'[a-z]' '[A-Z]',当然反过来将大写变小写也是可以的

更多 tr 的使用,你可以使用--help或者man tr获得。

2.col 命令

col 命令可以将Tab换成对等数量的空格建,或反转这个操作。

使用方式:

col [option]

常用的选项有:

选项说明
-x Tab转换为空格
-h 将空格转换为Tab(默认选项)

操作举例:

# 查看 /etc/protocols 中的不可见字符,可以看到很多 ^I ,这其实就是 Tab 转义成可见字符的符号
$ cat -A /etc/protocols
# 使用 col -x 将 /etc/protocols 中的 Tab 转换为空格,然后再使用 cat 查看,你发现 ^I 不见了
$ cat /etc/protocols | col -x | cat -A

3.join命令

学过数据库的用户对这个应该不会陌生,这个命令就是用于将两个文件中包含相同内容的那一行合并在一起。

使用方式:

join [option]... file1 file2

常用的选项有:

选项说明
-t 指定分隔符,默认为空格
-i 忽略大小写的差异
-1 指明第一个文件要用哪个字段来对比,,默认对比第一个字段
-2 指明第二个文件要用哪个字段来对比,,默认对比第一个字段

操作举例:

# 创建两个文件
$ echo '1 hello' > file1
$ echo '1 shiyanlou' > file2
$ join file1 file2
# 将/etc/passwd与/etc/shadow两个文件合并,指定以':'作为分隔符
$ sudo join -t':' /etc/passwd /etc/shadow
# 将/etc/passwd与/etc/group两个文件合并,指定以':'作为分隔符, 分别比对第4和第3个字段
$ sudo join -t':' -1 4 /etc/passwd -2 3 /etc/group

4.paste命令

paste这个命令与join 命令类似,它是在不对比数据的情况下,简单地将多个文件合并一起,以Tab隔开。

使用方式:

paste [option] file...

常用的选项有:

选项说明
-d 指定合并的分隔符,默认为Tab
-s 不合并到一行,每个文件为一行

操作举例:

$ echo hello > file1
$ echo shiyanlou > file2
$ echo www.shiyanlou.com > file3
$ paste -d ':' file1 file2 file3
$ paste -s file1 file2 file3

 

(29)数据流重定向

下面我们简单的回顾一下我们前面经常用到的两个重定向操作:

$ echo 'hello shiyanlou' > redirect 
$ echo 'www.shiyanlou.com' >> redirect
$ cat redirect

当然前面没有用到的<<<操作也是没有问题的,如你理解的一样,它们的区别在于重定向的方向不一致而已,>表示是从左到右,<右到左。

1.简单的重定向

在更多了解 Linux 的重定向之前,我们需要先知道一些基本的东西,前面我们已经提到过 Linux 默认提供了三个特殊设备,用于终端的显示和输出,分别为stdin(标准输入,对应于你在终端的输入),stdout(标准输出,对应于终端的输出),stderr(标准错误输出,对应于终端的输出)。

文件描述符设备文件说明
0 /dev/stdin 标准输入
1 /dev/stdout 标准输出
2 /dev/stderr 标准错误

文件描述符:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于 UNIX、Linux 这样的操作系统。

另外还有一个符号-,它可以同时作为前一个命令的。

我们可以这样使用这些文件描述符:

默认使用终端的标准输入作为命令的输入和标准输出作为命令的输出

$ cat 
(按Ctrl+C退出)

将cat的连续输出(heredoc方式)重定向到一个文件

$ mkdir Documents
$ cat > Documents/test.c\~ <<EOF
#include <stdio.h>

int main()
{
    printf("hello world\n");
    return 0;
}

EOF

将一个文件作为命令的输入,标准输出作为命令的输出

$ cat Documents/test.c\~

将echo命令通过管道传过来的数据作为cat命令的输入,将标准输出作为命令的输出

$ echo 'hi' | cat

将echo命令的输出从默认的标准输出重定向到一个普通文件

$ echo 'hello shiyanlou' > redirect
$ cat redirect

初学者这里要注意不要将管道和重定向混淆,管道默认是连接前一个命令的输出到下一个命令的输入,而重定向通常是需要一个文件来建立两个命令的连接,你可以仔细体会一下上述第三个操作和最后两个操作的异同点。

2.标准错误重定向

重定向标准输出到文件,这是一个很实用的操作,另一个很实用的操作是将标准错误重定向,标准输出和标准错误都被指向伪终端的屏幕显示,所以我们经常看到的一个命令的输出通常是同时包含了标准输出和标准错误的结果的。比如下面的操作:

# 使用cat 命令同时读取两个文件,其中一个存在,另一个不存在
$ cat Documents/test.c\~ hello.c
# 你可以看到除了正确输出了前一个文件的内容,还在末尾出现了一条错误信息
# 下面我们将输出重定向到一个文件,根据我们前面的经验,这里将在看不到任何输出了
$ cat Documents/test.c\~ hello.c > somefile

遗憾的是,这里依然出现了那条错误信息,这正是因为如我上面说的那样,标准输出和标准错误虽然都指向终端屏幕,实际它们并不一样。那有的时候我们就是要可以隐藏某些错误或者警告,那又该怎么做呢。这就需要用到我们前面讲的文件描述符了:

# 将标准错误重定向到标准输出,再将标准输出重定向到文件,注意要将重定向到文件写到前面
$ cat Documents/test.c\~ hello.c >somefile  2>&1
# 或者只用bash提供的特殊的重定向符号"&"将标准错误和标准输出同时重定向到文件
$ cat Documents/test.c\~ hello.c &>somefilehell

注意你应该在输出重定向文件描述符前加上&,否则shell会当做重定向到一个文件名为1的文件中

3.使用tee命令同时重定向到多个文件

经常你可能还有这样的需求,除了将需要将输出重定向到文件之外也需要将信息打印在终端,那么你可以使用tee命令来实现:

$ echo 'hello shiyanlou' | tee hello

4.永久重定向

你应该可以看出我们前面的重定向操作都只是临时性的,即只对当前命令有效,那如何做到“永久”有效呢,比如在一个脚本中,你需要某一部分的命令的输出全部进行重定向,难道要让你在每个命令上面加上临时重定向的操作嘛,当然不需要,我们可以使用exec命令实现“永久”重定向。exec命令的作用是使用指定的命令替换当前的 Shell,及使用一个进程替换当前进程,或者指定新的重定向:

# 先开启一个子 Shell
$ zsh
# 使用exec替换当前进程的重定向,将标准输出重定向到一个文件
$ exec 1>somefile
# 后面你执行的命令的输出都将被重定向到文件中,直到你退出当前子shell,或取消exec的重定向(后面将告诉你怎么做)
$ ls
$ exit
$ cat somefile

5.创建输出文件描述符

默认在 Shell 中可以有9个打开的文件描述符,上面我们使用了也是它默认提供的0,1,2号文件描述符,另外我们还可以使用3-8的文件描述符,只是它们默认没有打开而已,你可以使用下面命令查看当前 Shell 进程中打开的文件描述符:

$ cd /dev/fd/;ls -Al

同样使用exec命令可以创建新的文件描述符:

$ zsh
$ exec 3>somefile
# 先进入目录,再查看,否则你可能不能得到正确的结果,然后再回到上一次的目录
$ cd /dev/fd/;ls -Al;cd -
# 注意下面的命令>与&之间不应该有空格,如果有空格则会出错
$ echo "this is test" >&3
$ cat somefile
$ exit

6.关闭文件描述符

如上面我们打开的3号文件描述符,可以使用如下操作将它关闭:

$ exec 3>&-
$ cd /dev/fd;ls -Al;cd -

7.完全屏蔽命令的输出

在 Linux 中有一个被成为“黑洞”的设备文件,所以导入它的数据都将被“吞噬”。

在类 UNIX 系统中,/dev/null,或称空设备,是一个特殊的设备文件,它通常被用于丢弃不需要的输出流,或作为用于输入流的空文件,这些操作通常由重定向完成。读取它则会立即得到一个EOF。

我们可以利用设个/dev/null屏蔽命令的输出:

$ cat Documents/test.c\~ nefile 1>/dev/null 2>&1

向上面这样的操作将使你得不到任何输出结果。

8.使用 xargs 分割参数列表

xargs 是一条 UNIX 和类 UNIX 操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。

这个命令在有些时候十分有用,特别是当用来处理产生大量输出结果的命令如 find,locate 和 grep 的结果,详细用法请参看 man 文档。

$ cut -d: -f1 < /etc/passwd | sort | xargs echo

上面这个命令用于将/etc/passwd文件按:分割取第一个字段排序后,使用echo命令生成一个列表。

(30)正则表达式

正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为 regex、regexp 或 RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在 Perl 中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由 UNIX 中的工具软件(例如sedgrep)普及开的。正则表达式通常缩写成“regex”,单数有 regexp、regex,复数有 regexps、regexes、regexen。

1.基本语法:

一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。

选择

|竖直分隔符表示选择,例如"boy|girl"可以匹配"boy"或者"girl"

数量限定

数量限定除了我们举例用的*,还有+加号,?问号,.点号,如果在一个模式中不加数量限定符则表示出现一次且仅出现一次:

  • +表示前面的字符必须出现至少一次(1次或多次),例如,"goo+gle",可以匹配"gooogle","goooogle"等;
  • ?表示前面的字符最多出现一次(0次或1次),例如,"colou?r",可以匹配"color"或者"colour";
  • *星号代表前面的字符可以不出现,也可以出现一次或者多次(0次、或1次、或多次),例如,“0*42”可以匹配42、042、0042、00042等。

范围和优先级

()圆括号可以用来定义模式字符串的范围和优先级,这可以简单的理解为是否将括号内的模式串作为一个整体。例如,"gr(a|e)y"等价于"gray|grey",(这里体现了优先级,竖直分隔符用于选择a或者e而不是gra和ey),"(grand)?father"匹配father和grandfather(这里体验了范围,?将圆括号内容作为一个整体匹配)。

语法(部分)

正则表达式有多种不同的风格,下面列举一些常用的作为 PCRE 子集的适用于perlpython编程语言及grepegrep的正则表达式匹配规则:(由于markdown表格解析的问题,下面的竖直分隔符用全角字符代替,实际使用时请换回半角字符)

PCRE(Perl Compatible Regular Expressions中文含义:perl语言兼容正则表达式)是一个用 C 语言编写的正则表达式函数库,由菲利普.海泽(Philip Hazel)编写。PCRE是一个轻量级的函数库,比Boost 之类的正则表达式库小得多。PCRE 十分易用,同时功能也很强大,性能超过了 POSIX 正则表达式库和一些经典的正则表达式库。

字符描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。序列“\\”匹配“\”而“\(”则匹配“(”。
^ 匹配输入字符串的开始位置。
$ 匹配输入字符串的结束位置。
{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
* 匹配前面的子表达式零次或多次。例如,zo*能匹配“z”、“zo”以及“zoo”。*等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。
? 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
. 匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
(pattern) 匹配pattern并获取这一匹配的子字符串。该子字符串用于向后引用。要匹配圆括号字符,请使用“\(”或“\)”。
x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。
[xyz] 字符集合(character class)。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。其中特殊字符仅有反斜线\保持特殊含义,用于转义字符。其它特殊字符如星号、加号、各种括号等均作为普通字符。脱字符^如果出现在首位则表示负值字符集合;如果出现在字符串中间就仅作为普通字符。连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位则仅作为普通字符。
[^xyz] 排除型(negate)字符集合。匹配未列出的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[^a-z] 排除型的字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。

优先级

优先级为从上到下从左到右,依次降低:

运算符说明
\ 转义符
(), (?:), (?=), [] 括号和中括号
*、+、?、{n}、{n,}、{n,m} 限定符
^、$、\任何元字符 定位点和序列
 选择

 

二、grep模式匹配命令

上面空谈了那么多正则表达式的内容也并没有提及具体该如何使用它,实在枯燥,如果说正则表达式是一门武功话,那它也只能算得上一些口诀招式罢了,要把它真正练起来还得需要一些兵器在手才行,这里我们要介绍的grep命令以及后面要讲的sed,awk这些就该算作是这样的兵器了。

1.基本操作

grep命令用于打印输出文本中匹配的模式串,它使用正则表达式作为模式匹配的条件。grep支持三种正则表达式引擎,分别用三个参数指定:

参数说明
-E POSIX扩展正则表达式,ERE
-G POSIX基本正则表达式,BRE
-P Perl正则表达式,PCRE

不过在你没学过perl语言的大多数情况下你将只会使用到EREBRE,所以我们接下来的内容都不会讨论到PCRE中特有的一些正则表达式语法(它们之间大部分内容是存在交集的,所以你不用担心会遗漏多少重要内容)

在通过grep命令使用正则表达式之前,先介绍一下它的常用参数:

参数说明
-b 将二进制文件作为文本来进行匹配
-c 统计以模式匹配的数目
-i 忽略大小写
-n 显示匹配文本所在行的行号
-v 反选,输出不匹配行的内容
-r 递归匹配查找
-A n n为正整数,表示after的意思,除了列出匹配行之外,还列出后面的n行
-B n n为正整数,表示before的意思,除了列出匹配行之外,还列出前面的n行
--color=auto 将输出中的匹配项设置为自动颜色显示

 

 

2.使用正则表达式

使用基本正则表达式,BRE

  • 位置

查找/etc/group文件中以"shiyanlou"为开头的行

$ grep 'shiyanlou' /etc/group
$ grep '^shiyanlou' /etc/group
  • 数量
# 将匹配以'z'开头以'o'结尾的所有字符串
$ echo 'zero\nzo\nzoo' | grep 'z.*o'
# 将匹配以'z'开头以'o'结尾,中间包含一个任意字符的字符串
$ echo 'zero\nzo\nzoo' | grep 'z.o'
# 将匹配以'z'开头,以任意多个'o'结尾的字符串
$ echo 'zero\nzo\nzoo' | grep 'zo*'

注意:其中\n为换行符

  • 选择
# grep默认是区分大小写的,这里将匹配所有的小写字母
$ echo '1234\nabcd' | grep '[a-z]'
# 将匹配所有的数字
$ echo '1234\nabcd' | grep '[0-9]'
# 将匹配所有的数字
$ echo '1234\nabcd' | grep '[[:digit:]]'
# 将匹配所有的小写字母
$ echo '1234\nabcd' | grep '[[:lower:]]'
# 将匹配所有的大写字母
$ echo '1234\nabcd' | grep '[[:upper:]]'
# 将匹配所有的字母和数字,包括0-9,a-z,A-Z
$ echo '1234\nabcd' | grep '[[:alnum:]]'
# 将匹配所有的字母
$ echo '1234\nabcd' | grep '[[:alpha:]]'

 

下面包含完整的特殊符号及说明:

特殊符号说明
[:alnum:] 代表英文大小写字节及数字,亦即 0-9, A-Z, a-z
[:alpha:] 代表任何英文大小写字节,亦即 A-Z, a-z
[:blank:] 代表空白键与 [Tab] 按键两者
[:cntrl:] 代表键盘上面的控制按键,亦即包括 CR, LF, Tab, Del.. 等等
[:digit:] 代表数字而已,亦即 0-9
[:graph:] 除了空白字节 (空白键与 [Tab] 按键) 外的其他所有按键
[:lower:] 代表小写字节,亦即 a-z
[:print:] 代表任何可以被列印出来的字节
[:punct:] 代表标点符号 (punctuation symbol),亦即:" ' ? ! ; : # $...
[:upper:] 代表大写字节,亦即 A-Z
[:space:] 任何会产生空白的字节,包括空白键, [Tab], CR 等等
[:xdigit:] 代表 16 进位的数字类型,因此包括: 0-9, A-F, a-f 的数字与字节

注意:之所以要使用特殊符号,是因为上面的[a-z]不是在所有情况下都管用,这还与主机当前的语系有关,即设置在LANG环境变量的值,zh_CN.UTF-8的话[a-z],即为所有小写字母,其它语系可能是大小写交替的如,"a A b B...z Z",[a-z]中就可能包含大写字母。所以在使用[a-z]时请确保当前语系的影响,使用[:lower:]则不会有这个问题。

# 排除字符
$ echo 'geek|good' | grep '[^o]'

注意:^放到中括号内为排除字符,否则表示行首。

 

使用扩展正则表达式,ERE

要通过grep使用扩展正则表达式需要加上-E参数,或使用egrep

  • 数量
# 只匹配"zo"
$ echo 'zero\nzo\nzoo' | grep -E 'zo{1}'
# 匹配以"zo"开头的所有单词
$ echo 'zero\nzo\nzoo' | grep -E 'zo{1,}'
  • 选择
# 匹配"www.shiyanlou.com"和"www.google.com"
$ echo 'www.shiyanlou.com\nwww.baidu.com\nwww.google.com' | grep -E 'www\.(shiyanlou|google)\.com'
# 或者匹配不包含"baidu"的内容
$ echo 'www.shiyanlou.com\nwww.baidu.com\nwww.google.com' | grep -Ev 'www\.baidu\.com'

(31)LINUX软件包在线安装

试想一下,平时我们在使用 Windows 的时候,想要安装一个软件,我们需要在网上去下载对应软件的安装包,接着安装的时候就是不断的去点击下一步,这些流程想必大家已经经历的无数回了,但是在 Linux 下,一个命令加回车,等待一下,软件就安装好了,这就是方便的在线安装软件的方式。在学习这种安装方式之前有一点需要说明的是,在不同的linux发行版上面在线安装方式会有一些差异包括使用的命令及它们的包管理工具,因为我们的开发环境是基于ubuntu的,所以这里我们涉及的在线安装方式将只适用于ubuntu发行版,或其它基于ubuntu的发行版如国内的ubuntukylin(优麒麟),ubuntu又是基于debian的发行版,它使用的是debian的包管理工具dpkg,所以一些操作也适用与debian。而在其它一些采用其它包管理工具的发行版如redhat,centos,fedora等将不适用(redhat和centos使用rpm)

1. 先体验一下

比如我们想安装一个软件,名字叫做 w3m(w3m是一个命令行的简易网页浏览器),那么输入如下命令:

$ sudo apt-get install w3m

这样的操作你应该在前面的章节中看到过很多次了,它就表示将会安装一个软件包名为w3m的软件

执行后的效果:

$ w3m www.shiyanlou.com/faq

注意:如果你在安装一个软件之后,无法立即使用Tab键补全这可命令,你可以尝试先执行source ~/.zshrc,然后你就可以使用补全操作。

2. apt 包管理工具介绍

APT是Advance Packaging Tool(高级包装工具)的缩写,是Debian及其派生发行版的软件包管理器,APT可以自动下载,配置,安装二进制或者源代码格式的软件包,因此简化了Unix系统上管理软件的过程。APT最早被设计成dpkg的前端,用来处理deb格式的软件包。现在经过APT-RPM组织修改,APT已经可以安装在支持RPM的系统管理RPM包。这个包管理器包含以 apt-开头的的多个工具,如 apt-get apt-cache apt-cdrom 等,在Debian系列的发行版中使用。

当你在执行安装操作时,首先apt-get 工具会在本地的一个数据库中搜索关于 w3m 软件的相关信息,并根据这些信息在相关的服务器上下载软件安装,这里大家可能会一个疑问:既然是在线安装软件,为啥会在本地的数据库中搜索?要解释这个问题就得提到几个名词了:

  • 软件源镜像服务器
  • 软件源

我们需要定期从服务器上下载一个软件包列表,使用 sudo apt-get update 命令来保持本地的软件包列表是最新的(有时你也需要手动执行这个操作,比如更换了软件源),而这个表里会有软件依赖信息的记录,对于软件依赖,我举个例子:我们安装 w3m 软件的时候,而这个软件需要 libgc1c2 这个软件包才能正常工作,这个时候 apt-get 在安装软件的时候会一并替我们安装了,以保证 w3m 能正常的工作。

3.apt-get

apt-get使用各用于处理apt包的公用程序集,我们可以用它来在线安装、卸载和升级软件包等,下面列出一些apt-get包含的常用的一些工具:

工具说明
install 其后加上软件包名,用于安装一个软件包
update 从软件源镜像服务器上下载/更新用于更新本地软件源的软件包列表
upgrade 升级本地可更新的全部软件包,但存在依赖问题时将不会升级,通常会在更新之前执行一次update
dist-upgrade 解决依赖关系并升级(存在一定危险性)
remove 移除已安装的软件包,包括与被移除软件包有依赖关系的软件包,但不包含软件包的配置文件
autoremove 移除之前被其他软件包依赖,但现在不再被使用的软件包
purge 与remove相同,但会完全移除软件包,包含其配置文件
clean 移除下载到本地的已经安装的软件包,默认保存在/var/cache/apt/archives/
autoclean 移除已安装的软件的旧版本软件包

下面是一些apt-get常用的参数:

参数说明
-y 自动回应是否安装软件包的选项,在一些自动化安装脚本中使用这个参数将十分有用
-s 模拟安装
-q 静默安装方式,指定多个q或者-q=#,#表示数字,用于设定静默级别,这在你不想要在安装软件包时屏幕输出过多时很有用
-f 修复损坏的依赖关系
-d 只下载不安装
--reinstall 重新安装已经安装但可能存在问题的软件包
--install-suggests 同时安装APT给出的建议安装的软件包

4.安装软件包

关于安装,如前面演示的一样你只需要执行apt-get install <软件包名>即可,除了这一点,你还应该掌握的是如何重新安装软件包。 很多时候我们需要重新安装一个软件包,比如你的系统被破坏,或者一些错误的配置导致软件无法正常工作。

你可以使用如下方式重新安装:

$ sudo apt-get --reinstall install w3m

另一个你需要掌握的是,如何在不知道软件包完整名的时候进行安装。通常我们是使用Tab键补全软件包名,后面会介绍更好的方法来搜索软件包。有时候你需要同时安装多个软件包,你还可以使用正则表达式匹配软件包名进行批量安装。

5.软件升级

# 更新软件源
$ sudo apt-get update
# 升级没有依赖问题的软件包
$ sudo apt-get upgrade
# 升级并解决依赖关系
$ sudo apt-get dist-upgrade

6.卸载软件

# 不保留配置文件的移除
$ sudo apt-get purge w3m
# 或者 sudo apt-get --purge remove
# 移除不再需要的被依赖的软件包
$ sudo apt-get autoremove

7.软件搜索

当自己刚知道了一个软件,想下载使用,需要确认软件仓库里面有没有,就需要用到搜索功能了,命令如下:

sudo apt-cache search softname1 softname2 softname3……

apt-cache 命令则是针对本地数据进行相关操作的工具,search 顾名思义在本地的数据库中寻找有关 softname1 softname2 …… 相关软件的信息。 

 

七、遇到的问题及解决

(提示:此处由学生填写,是重要的得分点,要写出遇到的问题和解决方案以及对出现问题的思考)

1.

尝试了很多次,可能是本身的问题,唯一成功的是man 1 ls:

 

2.不会使用toiletfilget

百度之后详见学习过程(5)

3.创建用户名输入密码没有反应?

本身的设计就是不回显的

4.

没有跳到shiyanlou:~/

5.  

cd后面一定要有空格再加“~”或“..

6. 使用wq无法退出

不知道如何解决?

 

 

 

 

八、其他

(提示:此处由学生填写,灵感,领悟等)