实验楼 练习 小笔记php
能够输出图形字符的命令banner
html
你能够先使用以下命令安装:前端
$ sudo apt-get updatenode
$ sudo apt-get install sysvbannerpython
而后:linux
$ banner shiyanlou
两个相似的命令toilet
,figlet
git
$ sudo apt-get install toilet正则表达式
Who am ichrome
如今咱们新建一个叫 lilei 的用户:shell
$ sudo adduser lilei
登陆用户:
-l$ sulilei
实验环境:
用户名:shiyanlou
密码:X6G4jz6z
用户及文件权限管理
实验介绍
一、Linux 中建立、删除用户,及用户组等操做。 二、Linux 中的文件权限设置。
1、Linux 用户管理
经过第一节课程的学习,你应该已经知道,Linux 是一个能够实现多用户登录的操做系统,好比“李雷”和“韩梅梅”均可以同时登录同一台主机,他们共享一些主机的资源,但他们也分别有本身的用户空间,用于存放各自的文件。但实际上他们的文件都是放在同一个物理磁盘上的甚至同一个逻辑分区或者目录里,可是因为 Linux 的 用户管理和 权限机制 ,不一样用户不能够轻易地查看、修改彼此的文件。
下面咱们就来学习一下 Linux 下的帐户管理的基础知识。
1.查看用户
请打开终端,输入命令:
$ who am i
或者
$ who mom likes
输入的第一列表示打开当前伪终端的用户的用户名(要查看当前登陆用户的用户名,去掉空格直接使用 whoami 便可),第二列的 pts/0 中 pts 表示伪终端,所谓伪是相对于 /dev/tty 设备而言的,还记得上一节讲终端时的那七个使用 [Ctrl]+[Alt]+[F1]~[F7] 进行切换的 /dev/tty 设备么,这是“真终端”,伪终端就是当你在图形用户界面使用 /dev/tty7 时每打开一个终端就会产生一个伪终端, pts/0 后面那个数字就表示打开的伪终端序号,你能够尝试再打开一个终端,而后在里面输入 who am i ,看第二列是否是就变成 pts/1 了,第三列则表示当前伪终端的启动时间。
who 命令其它经常使用参数
参数 |
说明 |
-a |
打印能打印的所有 |
-d |
打印死掉的进程 |
-m |
同am i,mom likes |
-q |
打印当前登陆用户数及用户名 |
-u |
打印当前登陆用户登陆信息 |
-r |
打印运行等级 |
2.建立用户
在 Linux 系统里, root 帐户拥有整个系统至高无上的权利,好比 新建/添加 用户。
root 权限,系统权限的一种,与 SYSTEM 权限能够理解成一个概念,但高于 Administrator 权限,root 是 Linux 和 UNIX 系统中的超级管理员用户账户,该账户拥有整个系统至高无上的权力,全部对象他均可以操做,因此不少黑客在入侵系统的时候,都要把权限提高到 root 权限,用 Windows 的方法理解也就是将本身的非法账户添加到 Administrators 用户组。更好比安卓操做系统中(基于 Linux 内核)得到 root 权限以后就意味着已经得到了手机的最高权限,这时候你能够对手机中的任何文件(包括系统文件)执行全部增、删、改、查的操做。
咱们通常登陆系统时都是以普通帐户的身份登陆的,要建立用户须要 root 权限,这里就要用到 sudo 这个命令了。不过使用这个命令有两个大前提,一是你要知道当前登陆用户的密码,二是当前用户必须在 sudo 用户组。shiyanlou 用户也属于 sudo 用户组(稍后会介绍如何查看和添加用户组)。
su,su- 与 sudo
su <user>能够切换到用户user,执行时须要输入目标用户的密码,sudo <cmd>能够以特权级别运行cmd命令,须要当前用户属于sudo组,且须要输入当前用户密码。su - <user>命令也是切换用户,同时环境变量也会跟着改变成目标用户的环境变量。
如今咱们新建一个叫 lilei 的用户:
$ sudo adduser lilei
按照提示输入 shiyanlou 密码(Linux 下密码输入一般都是不可见的),而后是给 lilei 用户设置密码,后面的选项的一些内容你能够选择直接回车使用默认值:
这个命令不但能够添加用户到系统,同时也会默认为新用户建立 home 目录:
$ ls /home
如今你已经建立好一个用户,而且你能够使用你建立的用户登陆了,使用以下命令切换登陆用户:
$ su -l lilei
退出当前用户跟退出终端同样能够使用 exit 命令或者使用快捷键 Ctrl+d。
3.用户组
在 Linux 里面每一个用户都有一个归属(用户组),用户组简单地理解就是一组用户的集合,它们共享一些资源和权限,同时拥有私有资源,就跟家的形式差很少,你的兄弟姐妹(不一样的用户)属于同一个家(用户组),大家能够共同拥有这个家(共享资源),爸妈对待大家都同样(共享权限),你偶尔写写日记,其余人未经容许不能查看(私有资源和权限)。固然一个用户是能够属于多个用户组的,正如你既属于家庭,又属于学校或公司。
在 Linux 里面如何知道本身属于哪些用户组呢?
方法一:使用groups命令
$ groups shiyanlou
其中冒号以前表示用户,后面表示该用户所属的用户组。这里能够看到 shiyanlou 用户属于 shiyanlou 用户组,每次新建用户若是不指定用户组的话,默认会自动建立一个与用户名相同的用户组(差很少就至关于家长的意思,或者说是老总)。默认状况下在sudo用户组里的能够使用sudo命令得到root权限。shiyanlou 用户也能够使用 sudo 命令,为何这里没有显示在 sudo 用户组里呢?能够查看下 /etc/sudoers.d/shiyanlou 文件,咱们在 /etc/sudoers.d目录下建立了这个文件,从而给 shiyanlou 用户赋予了 sudo 权限:
方法二:查看/etc/group文件
$ cat /etc/group | sort
这里 cat 命令用于读取指定文件的内容并打印到终端输出,后面会详细讲它的使用。| sort 表示将读取的文本进行一个字典排序再输出,而后你将看到以下一堆输出,你能够在最下面看到 shiyanlou 的用户组信息:
没找到,不要紧,你能够使用命令过滤掉一些你不想看到的结果:
$ cat /etc/group | grep -E "shiyanlou"
etc/group 文件格式说明
/etc/group 的内容包括用户组(Group)、用户组口令、GID 及该用户组所包含的用户(User),每一个用户组一条记录。格式以下:
group_name:password:GID:user_list
你看到上面的 password 字段为一个 'x' 并非说密码就是它,只是表示密码不可见而已。
将其它用户加入 sudo 用户组
默认状况下新建立的用户是不具备 root 权限的,也不在 sudo 用户组,可让其加入sudo用户组从而获取 root 权限。
$ su -l lilei
$ sudo ls
会提示 lilei 不在 sudoers 文件中,意思就是 lilei 不在 sudo 用户组中,至于 sudoers 文件(/etc/sudoers)你如今最好不要动它,操做不慎会致使比较麻烦的后果。
使用 usermod 命令能够为用户添加用户组,一样使用该命令你必需有 root 权限,你能够直接使用 root 用户为其它用户添加用户组,或者用其它已经在 sudo 用户组的用户使用 sudo 命令获取权限来执行该命令
这里我用 shiyanlou 用户执行 sudo 命令将 lilei 添加到 sudo 用户组,让它也能够使用 sudo 命令得到 root 权限
$ su shiyanlou # 此处须要输入shiyanlou用户密码,能够点击右侧工具栏中的“SSH直连”查看
$ groups lilei
$ sudo usermod -G sudo lilei
$ groups lilei
而后你再切换回 lilei 用户,如今就能够使用 sudo 获取 root 权限了。
4.删除用户
删除用户是很简单的事:
$ sudo deluser lilei --remove-home
2、Linux 文件权限
1.查看文件权限
咱们以前已经不少次用到 ls 命令了,如你所见,咱们用它来列出并显示当前目录下的文件,固然这是在不带任何参数的状况下,它能作的固然不止这么多,如今咱们就要用它来查看文件权限。
使用较长格式列出文件:
$ ls -l
你可能除了知道最后面那一项是文件名以外,其它项就不太清楚了,那么究竟是什么意思呢:
可能你仍是不太明白,好比第一项文件类型和权限那一堆东西具体指什么,连接又是什么,何为最后修改时间,下面一一道来:
关于文件类型,这里有一点你必需时刻牢记Linux 里面一切皆文件,正由于这一点才有了设备文件( /dev 目录下有各类设备文件,大都跟具体的硬件设备相关)这一说,还有 socket(网络套接字,具体是什么,感兴趣的用户能够本身去了解或期待实验楼的后续相关课程),和 pipe (管道,这个东西很重要,咱们之后将会讨论到,这里你先知道有它的存在便可)。软连接文件,连接文件是分为两种的,另外一种固然是“硬连接”(硬连接不经常使用,具体内容不做为本课程讨论重点,而软连接等同于 Windows 上的快捷方式,你记住这一点就够了)
读权限,表示你能够使用 cat <file name> 之类的命令来读取某个文件的内容;写权限,表示你能够编辑和修改某个文件; 执行权限,一般指能够运行的二进制程序文件或者脚本文件,如同 Windows 上的 'exe' 后缀的文件,不过 Linux 上不是经过文件后缀名来区分文件的类型。你须要注意的一点是,一个目录要同时具备读权限和执行权限才能够打开,而一个目录要有写权限才容许在其中建立其它文件,这是由于目录文件实际保存着该目录里面的文件的列表等信息
全部者权限,这一点相信你应该明白了,至于所属用户组权限,是指你所在的用户组中的全部其它用户对于该文件的权限,好比,你有一个艾派德,那么这个用户组权限就决定了你的兄弟姐妹有没有权限使用它破坏它和占有它。
连接到该文件所在的 inode 结点的文件名数目(关于这个概念涉及到 Linux 文件系统的相关概念知识,不在本课程的讨论范围,感兴趣的用户能够本身去了解)。
以 inode 结点大小为单位来表示的文件大小,你能够给 ls 加上 -lh 参数来更直观的查看文件的大小。
明白了文件权限的一些概念,咱们顺带补充一下关于 ls 命令的一些其它经常使用的用法:
$ ls -A
固然,你能够同时使用 '-A' 和 '-l' 参数:
$ ls -Al
查看某一个目录的完整属性,而不是显示目录里面的文件属性:
$ ls -dl <目录名>
$ ls -AsSh
其中小 s 为显示文件大小,大 S 为按文件大小排序,若须要知道如何按其它方式排序,请使用“man”命令查询。
2.变动文件全部者
假设目前是 lilei 用户登陆,新建一个文件,命名为 “iphone6”:
$ touch iphone6
可见文件全部者是 lilei :
如今,换回到shiyanlou用户身份,使用如下命令变动文件全部者为 shiyanlou :
$ cd /home/lilei
$ ls iphone6
$ sudo chown shiyanlou iphone6
$ cp iphone6 /home/shiyanlou
如今查看,发现 文件全部者成功修改成 shiyanlou :
3.修改文件权限
若是你有一个本身的文件不想被其余用户读、写、执行,那么就须要对文件的权限作修改,这里有两种方式:
每一个文件的三组权限(拥有者,所属用户组,其余用户,记住这个顺序是必定的)就对应这一个 "rwx",也就是一个 '7' ,因此若是我要将文件“iphone6”的权限改成只有我本身能够用那么就这样:
为了演示,我先在文件里加点内容:
$ echo "echo \"hello shiyanlou\"" > iphone6
而后修改权限:
$ chmod 700 iphone6
如今,其余用户已经不能读这个“iphone6”文件了:
完成上述相同的效果,你能够:
$ chmod go-rw iphone
'g''o'还有'u',分别表示group,others,user,'+','-' 就分别表示增长和去掉相应的权限。
3、更多
Linux 还有一些关于隐藏权限和特殊权限的内容,想全面了解 Linux 权限管理这部份内容的用户能够经过其余方式学习。
做业
添加一个用户loutest,使用sudo建立文件/opt/forloutest,设置成用户loutest能够读写。截图并把操做过程写入实验报告。
实验环境:
用户名:shiyanlou
密码:vRwzLsRH
一、Linux 的文件组织目录结构。 二、相对路径和绝对路径。 三、对文件的移动、复制、重命名、编辑等操做。
在讲 Linux 目录结构以前,你首先要清楚一点东西,那就是 Linux 的目录与 Windows 的目录的区别,或许对于通常操做上的感觉来讲没有多大不一样,但从它们的实现机制来讲是彻底不一样的。
一种不一样是体如今目录与存储介质(磁盘,内存,DVD 等)的关系上,以往的 Windows 一直是以存储介质为主的,主要以盘符(C 盘,D 盘...)及分区的来实现文件管理,而后之下才是目录,目录就显得不是那么重要,除系统文件以外的用户文件放在任何地方任何目录也是没有多大关系。因此一般 Windows 在使用一段时间后,磁盘上面的文件目录会显得杂乱无章(少数善于整理的用户除外吧)。然而 UNIX/Linux 刚好相反,UNIX 是以目录为主的,Linux 也继承了这一优良特性。 Linux 是以树形目录结构的形式来构建整个系统的,能够理解为一个用户可操做系统的骨架。虽然本质上不管是目录结构仍是操做系统内核都是存储在磁盘上的,但从逻辑上来讲 Linux 的磁盘是“挂在”(挂载在)目录上的,每个目录不只能使用本地磁盘分区的文件系统,也能够使用网络上的文件系统。举例来讲,能够利用网络文件系统(Network File System,NFS)服务器载入某特定目录等。
Linux 的目录结构说复杂很复杂,说简单也很简单。复杂在于,由于系统的正常运行是以目录结构为基础的,对于初学者来讲里面大部分目录都不知道其做用,重要与否,特别对于哪些曾近的重度 Windows 用户,他们会纠结很长时间,关于我安装的软件在哪里这类问题。说它简单是由于,它其中大部分目录结构是规定好了(FHS 标准),是死的,当你掌握后,你在里面的一切操做都会变得井井有理。
FHS(英文:Filesystem Hierarchy Standard 中文:文件系统层次结构标准),多数 Linux 版本采用这种文件组织形式,FHS 定义了系统中每一个区域的用途、所须要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。
FHS 定义了两层规范,第一层是, / 下面的各个目录应该要放什么文件数据,例如 /etc 应该要放置设置文件,/bin 与 /sbin 则应该要放置可执行文件等等。
第二层则是针对 /usr 及 /var 这两个目录的子目录来定义。例如 /var/log 放置系统登陆文件、/usr/share 放置共享数据等等。
若是你以为看这个不明白,那么你能够试试最真实最直观的方式,执行以下命令:
$ tree /
若是提示"command not found",就先安装:
# 由于咱们的环境的缘由,每次新启动实验会清除系统恢复初始状态,因此须要手动更新软件包索引,以便咱们安装时能找到相应软件包的源
getsudo apt-update
getsudo apt-install tree
关于上面提到的 FHS,这里还有个很重要的内容你必定要明白,FHS 是根据以往无数 Linux 用户和开发者的经验总结出来的,而且会维持更新,FHS 依据文件系统使用的频繁与否以及是否容许用户随意改动(注意,不是不能,学习过程当中,不要怕这些),将目录定义为四种交互做用的形态,以下表所示:
有人可能不明白这路径是指什么,有什么用。顾名思义,路径就是你要去哪儿的路线嘛。若是你想进入某个具体的目录或者想得到某个目录的文件(目录自己也是文件)那就得用路径来找到了。
使用 cd
命令能够切换目录,在 Linux 里面使用 .
表示当前目录,..
表示上一级目录(**注意,还记得咱们上一节介绍过的,以 .
开头的文件都是隐藏文件,因此这两个目录必然也是隐藏的,你能够使用 ls -a
命令查看隐藏文件), -
表示上一次所在目录,~
一般表示当前用户的"home"目录。使用 pwd
命令能够获取当前所在路径(绝对路径)。
进入上一级目录:
cd$..
进入你的“home”目录:
cd$~
# 或者 cd /home/<你的用户名>
使用 pwd
获取当前路径:
pwd$
关于绝对路径,简单地说就是以根"/"目录为起点的完整路径,以你所要到的目录为终点,表现形式如: /usr/local/bin
,表示根目录下的 usr 目录中的 local 目录中的 bin 目录。
相对路径,也就是相对于你当前的目录的路径,相对路径是以当前目录 .
为起点,以你所要到的目录为终点,表现形式如: usr/local/bin
(这里假设你当前目录为根目录)。你可能注意到,咱们表示相对路径实际并无加上表示当前目录的那个 .
,而是直接以目录名开头,由于这个 usr
目录为 /
目录下的子目录,是能够省略这个 .
的(之后会讲到一个相似不能省略的状况);若是是当前目录的上一级目录,则须要使用 ..
,好比你当前目录为“home”目录,根目录就应该表示为 ../../
,表示上一级目录("home"目录)的上一级目录("/"目录)。
下面咱们以你的"home"目录为起点,分别以绝对路径和相对路径的方式进入 /usr/local/bin
目录:
# 绝对路径
cdlocal$/usr//bin
# 相对路径
cdlocal$../../usr//bin
进入一个目录,能够使用绝对路径也能够使用相对路径,那咱们应该在何时选择正确的方式进入某个目录呢。就是凭直觉嘛,你以为怎样方便就使用哪个,而不用特地只使用某一种。好比假设我当前在 /usr/local/bin
目录,我想进入上一级的 local 目录你说是使用 cd ..
方便仍是 cd /usr/local
方便。而若是要进入的是 usr
目录,那么 cd /usr
,就比cd ../..
方便一点了。
提示:在进行目录切换的过程当中请多使用 Tab
键自动补全,可避免输入错误,连续按两次Tab
能够显示所有候选结果
使用 touch
命令建立空白文件,关于 touch
命令,其主要是来更改已有文件的时间戳的(好比,最近访问时间,最近修改时间),但其在不加任何参数的状况下,只指定一个文件名,则能够建立一个为指定文件名的空白文件(不会覆盖已有同名文件),固然你也能够同时指定该文件的时间戳,更多关于 touch
命令的用法,会在下一讲文件搜索中涉及。
建立名为 test 的空白文件,由于在其余目录没有权限,因此须要先 cd ~
切换回用户的/home/shiyanlou
目录:
cd$~
test$ touch
使用 mkdir
(make directories)命令能够建立一个空目录,也可同时指定建立目录的权限属性
建立名为"mydir"的空目录:
mkdir$mydir
使用 -p
参数,同时建立父目录(若是不存在该父目录),以下咱们同时建立一个多级目录(这在有时候安装软件,配置安装路径时很是有用):
mkdir$-p father/son/grandson
后面的目录路径,以绝对路径的方式表示也是能够的。
使用cp
(copy)命令复制一个文件或目录到指定目录。将以前建立的"test"文件复制到"/home/shiyanlou/father/son/grandson"目录中:
test$ cpfather/son/grandson
是否是很方便啊,若是在图形界面则须要先在源目录复制文件,再进到目的目录粘贴文件,命令行操做步骤就一步到位了嘛。
dh这个复制须要在大目录下进行,将大目录下的内容复制给子目录是能够的,要是交叉,就不行
若是直接使用cp
命令,复制一个目录的话,会出现以下错误:
要成功复制目录须要加上-r
或者-R
参数,表示递归复制,就是说有点“株连九族”的意思:
dh这个的用法见下图,复制目录,成为其子目录了。
$ cp -r father family
使用rm
(remove files or directories)命令,删除一个文件或目录:
test$ rm
有时候你会遇到想要删除一些为只读权限的文件,直接使用rm
删除会显示一个提示,以下:
你若是想忽略这提示,直接删除文件,能够使用-f
参数强制删除:
-ftest$ rm
跟复制目录同样,要删除一个目录,也须要加上-r
或-R
参数:
dh经测试,须要跑到对应的目录下才能够删除,有点小蛋疼
$ rm -r family
使用mv
(move or rename files)命令,移动文件(剪切)。将文件"file1"移动到"Documents"目录mv
源目录文件
目的目录
:
$ mkdir Documents
$ mv file1 Documents
将文件"file1"重命名为"myfile" mv
旧的文件名
新的文件名
:
dh若是没有该目录,就重命名,不然移动到该目录下面
$ mv file1 myfile
要实现批量重命名,mv 命令就有点力不从心了,咱们能够使用一个看起来更专业的命令rename
来实现。不过它是要用 perl 正则表达式来做为参数,关于正则表达式咱们要在后面才会介绍到,这里只作演示,你只要记得这个rename
命令能够批量重命名就行了,之后再从新学习也不会有任何问题,毕竟你已经掌握了一个更经常使用的mv
命令。
# 使用通配符批量建立 5 个文件
15$ touch file{..}.txt
# 批量将这 5 个后缀为 .txt 的文本文件重命名为以 .c 为后缀的文件
's/\.txt/\.c/'$ rename*.txt
# 批量将这 5 个文件,文件名改成大写
'y/a-z/A-Z/'$ rename*.c
简单解释下上面的命令,rename
是先使用第二个参数的通配符匹配全部后缀为.txt
的文件,而后使用第一个参数提供的正则表达式将匹配的这些文件的.txt
后缀替换为.c
,这一点在咱们后面学习了sed
命令后,相信你会更好的理解。
dh当年学的正则老不用又给忘记了,如今再用起来,正则仍是很不错的。
cat
,tac
和nl
命令查看文件这两个命令都是用来打印文件内容到标准输出(终端),其中cat
为正序显示,tac
倒序显示。
标准输入输出:当咱们执行一个 shell 命令行时一般会自动打开三个标准文件,即标准输入文件(stdin),默认对应终端的键盘;标准输出文件(stdout)和标准错误输出文件(stderr),这两个文件都对应被重定向到终端的屏幕,以便咱们能直接看到输出内容。进程将从标准输入文件中获得输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。
好比咱们要查看以前从"/etc"目录下拷贝来的passwd
文件:
$ cat passwd
能够加上-n
参数显示行号:
$ cat -n passwd
nl
命令,添加行号并打印,这是个比cat -n
更专业的行号打印命令。
这里简单列举它的经常使用的几个参数:
-b : 指定添加行号的方式,主要有两种:
-b a:表示不管是否为空行,一样列出行号("cat -n"就是这种方式)
-b t:只列出非空行的编号并列出(默认为这种方式)
-n : 设置行号的样式,主要有三种:
-n ln:在行号字段最左端显示
-n rn:在行号字段最右边显示,且不加0
-n rz:在行号字段最右边显示,且加0
-w : 行号字段占用的位数(默认为 6 位)
你会发现使用这几个命令,默认的终端窗口大小,一屏显示不完文本的内容,得用鼠标拖动滚动条或者滑动滚轮才能继续往下翻页,要是能够直接使用键盘操做翻页就行了,那么你就能够使用下面要介绍的命令。
more
和less
命令分页查看文件若是说上面的 cat 是用来快速查看一个文件内容的,那么这个more
和less
就是天生用来"阅读"一个文件的内容的,好比说"man"手册内部就是使用的 less 来显示内容。其中more
命令比较简单,只能向一个方向滚动,而"less"为基于"more"和"vi"(一个强大的编辑器,咱们有单独的课程来让你学习)开发,功能更强大。less 的使用基本和 more 一致,具体使用请查看 man 手册,这里只介绍 more 命令的使用。
使用more
工具打开passwd
文件:
$ more passwd
打开后默认只显示一屏内容,终端底部显示当前阅读的进度(百分比)。能够使用Enter
键向下滚动一行,使用Space
键向下滚动一屏,按下h
显示帮助,q
退出。
head
和tail
命令查看文件这两个命令那些性子比较急的人应该会比较喜欢,由于它们一个是只查看的头几行(默认为10行,不足10行则显示所有)和尾几行。仍是拿 passwd 文件举例,好比当咱们想要查看最近新增长的用户,那么咱们能够查看这个/etc/passwd
文件,不过咱们前面也看到了,这个文件里面一大堆乱糟糟的东西,看起来实在费神啊。这里想到系统新增长一个用户,应该会将用户的信息添加到passwd文件的最后,那么这时候咱们就能够使用tail
命令了:
$ tail /etc/passwd
甚至更直接的只看一行, 加上-n
参数,后面紧跟行数:
dh这边是直接显示最后几行
1$ tail -n/etc/passwd
关于tail
命令,不得不提的还有它一个很牛的参数-f
,这个参数能够实现不停地读取某个文件的内容并显示。这可以让咱们动态查看日志起到实时监视的做用,不过我不会在这门基础课程中介绍它的更多细节,感兴趣的用户能够本身去了解。
前面我提到过,在 Linux 下面文件的类型不是根据文件后缀来判断的,咱们一般使用file
命令能够查看文件的类型:
$ file /bin/ls
这表示这是一个可执行文件,运行在 64 位平台,并使用了动态连接文件(共享库)。
在 Linux 下面编辑文件一般咱们会直接使用专门的命令行编辑器好比(emacs,vim,nano),因为涉及 Linux 上的编辑器的内容比较多,且很是重要,故咱们有一门单独的基础课专门介绍这其中一个编辑器(vim)。在这里强烈但愿正在学习这门 Linux 基础课的你先在这里暂停一下,先去学习vim 编辑器的使用(至少掌握基本的操做)而后再继续本课程后面的内容,由于后面的内容会假设你已经学会了 vim 编辑器的使用。若是你想更加快速的入门,你能够直接使用 Linux 内部的 vim 学习教程,输入以下命令便可开始:
$ vimtutor
dhVim的操做手法以下:
你是否是以为在咱们的环境中学习感受轻松愉快毫无压力呢,因此偶尔偷偷懒也是没有问题的。要真是这样可不太好啊,要学会给本身点压力,稍微严格点要求本身才行。你又或许会想要是有人能监督就行了,这样你能学得更快。好吧今天就教你怎么召唤一双眼睛出来监督你:
$ xeyes
你能够使用以下命令将它放到后台运行
$ nohup xeyes &
实验环境:
用户名:shiyanlou
密码:r00Ds8ku
本节实验介绍环境变量的做用与用法,及几种搜索文件的方法。学会这些技巧高效地使用 Linux。
要解释环境变量,得先明白变量是什么,准确的说应该是 Shell 变量,所谓变量就是计算机中用于记录一个值(不必定是数值,也能够是字符或字符串)的符号,而这些符号将用于不一样的运算处理中。一般变量与值是一对一的关系,能够经过表达式读取它的值赋值给其它变量,也能够直接指定数值赋值给任意变量。为了便于运算和处理,大部分的编程语言会区分变量的类型,用于分别记录数值、字符或者字符串等等数据类型。Shell 中的变量也基本如此,有不一样类型(但不用专门指定类型名),能够参与运算,有做用域限定。
变量的做用域即变量的有效范围(好比一个函数中、一个源文件中或者全局范围),在该范围内只能有一个同名变量。一旦离开则该变量无效,如同不存在这个变量通常。
在 Shell 中如何建立一个变量,如何给变量赋值和如何读取变量的值呢?这部份内容会在bash 脚本编程这门课中详细介绍,这里我简单举例说明一下:
使用declare
命令建立一个变量名为 tmp 的变量:
declare$tmp
其实也能够不用 declare 预声明一个变量,直接即用即建立,这里只是告诉你 declare 的做用,这在建立其它指定类型的变量(如数组)时会用到。
使用=
号赋值运算符为变量 tmp 赋值为 shiyanlou:
$ tmp=shiyanlou
读取变量的值,使用echo
命令和$
符号($符号用于表示引用一个变量的值,初学者常常会忘记输入):
echo$tmp$
注意:关于变量名,并非任何形式的变量名都是可用的,变量名只能是英文字母,数字或者下划线,且不能以数字做为开头。
简单理解了变量的概念,就很好解释环境变量了,环境变量就是做用域比自定义变量要大,如Shell 的环境变量做用于自身和它的子进程。在全部的 UNIX 和类 UNIX 系统中,每一个进程都有其各自的环境变量设置,且默认状况下,当一个进程被建立时,处理建立过程当中明确指定的话,它将继承其父进程的绝大部分环境设置。Shell 程序也做为一个进程运行在操做系统之上,而咱们在 Shell中运行的大部分命令都将以 Shell 的子进程的方式运行。
一般咱们会涉及到的环境变量有三种:
也有三个与上述三种环境变量相关的命令,set
,env
,export
。这三个命令很类似,均可以用于打印相关环境变量,区别在于涉及的是不一样范围的环境变量,详见下表:
命令 |
说明 |
|
显示当前 Shell 全部环境变量,包括其内建环境变量(与 Shell 外观等相关),用户自定义变量及导出的环境变量 |
|
显示与当前用户相关的环境变量,还可让命令在指定环境中运行 |
|
显示从 Shell 中导出成环境变量的变量,也能经过它将自定义变量导出为环境变量 |
你能够更直观的使用vimdiff
工具比较一下它们之间的差异:
$ temp=shiyanlou
export$temp_env=shiyanlou
$ env|sort>env.txt
exportexport$|sort>.txt
setset$|sort>.txt
上述操做将命令输出经过管道|
使用sort
命令排序,再重定向到对象文本文件中。
exportset$ vimdiff env.txt.txt.txt
使用vimdiff
工具比较导出的几个文件的内容。
关于环境变量,能够简单的理解成在当前进程的子进程是否有效,有效则为环境变量,不然不是(有些人也将全部变量统称为环境变量,只是以全局环境变量和局部环境变量进行区分,咱们只要理解它们的实质区别便可)。咱们这里用export
命令来体会一下,先在 Shell 中设置一个变量temp=shiyanlou
,而后再新建立一个子 Shell 查看temp
变量的值:
注意:为了与普通变量区分,一般咱们习惯将环境变量名设为大写
你可能很早以前就有疑问,咱们在 Shell 中输入一个命令,Shell 是怎么知道在哪去找到这个命令而后执行的呢?这是经过环境变量PATH
来进行搜索的,熟悉 Windows 的用户可能知道 Windows 中的也是有这么一个 PATH 环境变量。这个PATH
里面就保存了Shell中执行的命令的搜索路径。
查看PATH
环境变量的内容:
echo$PATH$
默认状况下你会看到以下输出:
/usr//usr//usr//sbin://usr/g/usr//usr/local/sbin:local/bin:sbin:bin:bin:ames:local/games
若是你还记得咱们在 Linux 目录结构那一节的内容,你就应该知道上面这些目录下放的是哪一类文件了。一般这一类目录下放的都是可执行文件,当咱们在 Shell 中执行一个命令时,系统就会按照 PATH 中设定的路径按照顺序依次到目录中去查找,若是存在同名的命令,则执行先找到的那个。
下面咱们将练习建立一个最简单的可执行 Shell 脚本和一个使用 C 语言建立的"hello world"程序,若是这两部份内容你以前没有学习过,那么你能够进行一个入门学习: C 语言入门教程 高级 Bash 脚本编程指南 Linux Shell Scripting Tutorial (LSST) v2.0
建立一个 Shell 脚本文件:
$ vim hello_shell.sh
在脚本中添加以下内容,保存并退出(注意不要省掉第一行,这不是注释,论坛有用户反应会有语法错误,就是由于没有了第一行):
#!/bin/zsh
fordo((i=0; i<10; i++));
echo"hello shell"
done
exit0
为文件添加可执行权限:
chmod755$hello_shell.sh
执行脚本
$ ./hello_shell.sh
建立一个 C 语言"hello world"程序:
$ vim hello_world.c
#include <stdio.h>
int main(void)
{
printf"hello world!\n" ();
return0 ;
}
使用 gcc 生成可执行文件:
$ gcc -o hello_world hello_world.c
gcc 生成二进制文件默认具备可执行权限,不须要修改
在 shiyanlou 家目录建立一个mybin
目录,并将上述 hello_shell.sh 和 hello_world 文件移动到其中:
$ mkdir mybin
$ mv hello_shell.sh hello_world mybin/
如今你能够在mybin
目录中分别运行你刚刚建立的两个程序:
$ cd mybin
$ ./hello_shell.sh
$ ./hello_world
回到上一级目录,也就是shiyanlou
家目录,当再想运行那两个程序时,会发现提示命令找不到,除非加上命令的完整路径,但那样很不方便,如何作到想使用系统命令同样执行本身建立的脚本文件或者程序呢?那就要将命令所在路径添加到PATH
环境变量了。
在前面咱们应该注意到PATH
里面的路径是以:
做为分割符,因此咱们能够这样添加自定义路径:
:/home/shiyanlou/mybin$ PATH=$PATH
注意这里必定要使用绝对路径
如今你就能够在其余任意目录执行那两个命令了(注意须要去掉前面的./
)。你可能会意识到这样还并无很好的解决问题,由于我给 PATH 环境变量追加了一个路径,它也只是在当前 Shell 有效,我一旦退出终端,再打开就会发现又失效了。有没有方法让添加的环境变量全局有效?或者每次启动 Shell 时自动执行上面添加自定义路径到 PATH 的命令?下面咱们就来讲说后一种方式——让它自动执行。
在每一个用户的 home 目录中有一个 Shell 每次启动时会默认执行一个配置脚本,以初始化环境,包括添加一些用户自定义环境变量等等。zsh 的配置文件是.zshrc
,相应 Bash 的配置文件为.bashrc
。它们在etc
下还都有一个或多个全局的配置文件,不过咱们通常只修改用户目录下的配置文件。
咱们能够简单的使用下面命令直接添加内容到.zshrc
中:
"PATH=$PATH:/home/shiyanlou/mybin">> $ echo.zshrc
上述命令中>>
表示将标准输出以追加的方式重定向到一个文件中,注意前面用到的>
是以覆盖的方式重定向到一个文件中,使用的时候必定要注意分辨。在指定文件不存在的状况下都会建立新的文件。
变量的修改有如下几种方式:
变量设置方式 |
说明 |
|
从头向后开始匹配,删除符合匹配字串的最短数据 |
|
从头向后开始匹配,删除符合匹配字串的最长数据 |
|
从尾向前开始匹配,删除符合匹配字串的最短数据 |
|
从尾向前开始匹配,删除符合匹配字串的最长数据 |
|
将符合旧字串的第一个字串替换为新的字串 |
|
将符合旧字串的所有字串替换为新的字串 |
好比要修改咱们前面添加到 PATH 的环境变量。为了不操做失误致使命令找不到,咱们先将 PATH 赋值给一个新的自定义变量 path:
$PATH$ path=
echo$path$
${path%/home/shiyanlou/mybin}$ path=
# 或使用通配符,*表示任意多个任意字符
${path%*/mybin}$ path=
能够使用unset
命令删除一个环境变量:
unset$temp
在上面咱们在 Shell 中修改了一个配置脚本文件以后(好比 zsh 的配置文件 home 目录下的.zshrc
),每次都要退出终端从新打开甚至重启主机以后其才能生效,非常麻烦,咱们能够使用source
命令来让其当即生效,如:
source$.zshrc
source
命令还有一个别名就是.
,注意与表示当前路径的那个点区分开,虽然形式同样,但做用和使用方式同样,上面的命令若是替换成.
的方式就该是
$ . ./.zshrc
注意第一个点后面有一个空格,并且后面的文件必须指定完整的绝对或相对路径名,source 则不须要。
与搜索相关的命令经常使用的有以下几个whereis
,which
,find
,locate
。
whereis
简单快速$whereiswho
你会看到它找到了三个路径,两个可执行文件路径和一个 man 在线帮助文件所在路径,这个搜索很快,由于它并无从硬盘中依次查找,而是直接从数据库中查询。whereis
只能搜索二进制文件(-b),man帮助文件(-m)和源代码文件(-s)。若是想要得到更全面的搜索结果能够使用locate
命令。
locate
快而全经过"/var/lib/mlocate/mlocate.db"数据库查找,不过这个数据库也不是实时更新的,系统会使用定时任务天天自动执行updatedb
命令更新一次,因此有时候你刚添加的文件,它可能会找不到,须要手动执行一次updatedb
命令(在咱们的环境中必须先执行一次该命令)。它能够用来查找指定目录下的不一样文件类型,如查找 /etc 下全部以 sh 开头的文件:
$ locate /etc/sh
注意,它不仅是在 etc 目录下查找并会自动递归子目录进行查找
查找 /usr/share/ 下全部 jpg 文件:
/usr/share/$ locate\*.jpg
注意要添加*
号前面的反斜杠转义,不然会没法找到
若是想只统计数目能够加上-c
参数,-i
参数能够忽略大小写进行查找,whereis 的-b
,-m
,-s
一样能够是使用。
which
小而精which
自己是 Shell 内建的一个命令,咱们一般使用which
来肯定是否安装了某个指定的软件,由于它只从PATH
环境变量指定的路径中去搜索命令:
which$man
find
精而细find
应该是这几个命令中最强大的了,它不但能够经过文件类型、文件名进行查找并且能够根据文件的属性(如文件的时间戳,文件的权限等)进行搜索。find
命令强大到,要把它将明白至少须要单独好几节课程才行,咱们这里只介绍一些经常使用的内容。
在指定目录下搜索指定文件名的文件:
/etc/$ find-name interfaces
注意 find 命令的路径是做为第一个参数的,基本命令格式为 find [path] [option] [action]
与时间相关的命令参数:
参数 |
说明 |
|
最后访问时间 |
|
建立时间 |
|
最后修改时间 |
下面以-mtime
参数举例:
-mtime n
: n 为数字,表示为在n天以前的”一天以内“修改过的文件-mtime +n
: 列出在n天以前(不包含n天自己)被修改过的文件-mtime -n
: 列出在n天以内(包含n天自己)被修改过的文件newer file
: file为一个已存在的文件,列出比file还要新的文件名
列出 home 目录中,当天(24 小时以内)有改动的文件:
0$ find ~ -mtime
列出用户家目录下比Code文件夹新的文件:
$ find ~ -newer /home/shiyanlou/Code
《黑客帝国》电影里满屏幕代码的“数字雨”,在 Linux 里面你也能够轻松实现这样的效果,你只须要一个命令cmatrix
。
须要先安装,由于 Ubuntu 没有预装:
updateinstall$ sudo apt-get;sudo apt-getcmatrix
装好以后先不要急着执行,为了看到更好的效果,咱们须要先修改终端的主题配色,修改成黑底绿字,修改方法见下图:
而后按下F11
能够全屏显示。
文件打包与压缩
实验介绍
Linux 上经常使用的 压缩/解压 工具,介绍了 zip,rar,tar 的使用。
1、文件打包和解压缩
在讲 Linux 上的解压缩工具以前,有必要先了解如下常见经常使用的压缩包文件格式。在 Windows 上咱们最多见的不外乎这三种*.zip,*.rar,*.7z后缀的压缩文件,而在 Linux 上面常见经常使用的除了以上这三种外,还有*.gz,*.xz,*.bz2,*.tar,*.tar.gz,*.tar.xz,*tar.bz2,简单介绍以下:
文件后缀名 |
说明 |
*.zip |
zip程序打包压缩的文件 |
*.rar |
rar程序压缩的文件 |
*.7z |
7zip程序压缩的文件 |
*.tar |
tar程序打包,未压缩的文件 |
*.gz |
gzip程序(GNU zip)压缩的文件 |
*.xz |
xz程序压缩的文件 |
*.bz2 |
bzip2程序压缩的文件 |
*.tar.gz |
tar打包,gzip程序压缩的文件 |
*.tar.xz |
tar打包,xz程序压缩的文件 |
*tar.bz2 |
tar打包,bzip2程序压缩的文件 |
*.tar.7z |
tar打包,7z程序压缩的文件 |
讲了这么多种压缩文件,这么多个命令,不过咱们通常只须要掌握几个命令便可,包括zip,rar,tar。下面会依次介绍这几个命令及对应的解压命令。
1.zip压缩打包程序
$ zip -r -q -o shiyanlou.zip /home/shiyanlou
$ du -h shiyanlou.zip
$ file shiyanlou.zip
上面命令将 shiyanlou 的 home 目录打包成一个文件,并查看了打包后文件的大小和类型。第一行命令中,-r参数表示递归打包包含子目录的所有内容,-q参数表示为安静模式,即不向屏幕输出信息,-o,表示输出文件,需在其后紧跟打包输出文件名。后面使用du命令查看打包后文件的大小(后面会具体说明该命令)。
$ zip -r -9 -q -o shiyanlou_9.zip /home/shiyanlou -x ~/*.zip
$ zip -r -1 -q -o shiyanlou_1.zip /home/shiyanlou -x ~/*.zip
这里添加了一个参数用于设置压缩级别-[1-9],1表示最快压缩但体积大,9表示体积最小但耗时最久。最后那个-x是为了排除咱们上一次建立的 zip 文件,不然又会被打包进这一次的压缩文件中,注意:这里只能使用绝对路径,不然不起做用。
咱们再用du命令分别查看默认压缩级别、最低、最高压缩级别及未压缩的文件的大小:
$ du -h -d 0 *.zip ~ | sort
经过man 手册可知:
这样一目了然,你能够看到默认压缩级别应该是最高的,效果很明显,不过你在环境中操做以后看到的大小可能跟图上的有些不一样,由于在你使用过程当中,会随时还生成一些缓存文件在当前用户的家目录中,这对于咱们学习命令使用来讲,是可有可无的,能够忽略这些不一样。
使用-e参数能够建立加密压缩包:
$ zip -r -e -o shiyanlou_encryption.zip /home/shiyanlou
注意: 关于zip命令,由于 Windows 系统与 Linux/Unix 在文本文件格式上的一些兼容问题,好比换行符(为不可见字符),在 Windows 为 CR+LF(Carriage-Return+Line-Feed:回车加换行),而在 Linux/Unix 上为 LF(换行),因此若是在不加处理的状况下,在 Linux 上编辑的文本,在 Windows 系统上打开可能看起来是没有换行的。若是你想让你在 Linux 建立的 zip 压缩文件在 Windows 上解压后没有任何问题,那么你还须要对命令作一些修改:
$ zip -r -l -o shiyanlou.zip /home/shiyanlou
须要加上-l参数将LF转换为CR+LF来达到以上目的。
2.使用unzip命令解压缩zip文件
将shiyanlou.zip解压到当前目录:
$ unzip shiyanlou.zip
使用安静模式,将文件解压到指定目录:
$ unzip -q shiyanlou.zip -d ziptest
上述指定目录不存在,将会自动建立。若是你不想解压只想查看压缩包的内容你能够使用-l参数:
$ unzip -l shiyanlou.zip
注意: 使用unzip解压文件时咱们一样应该注意兼容问题,不过这里咱们关心的再也不是上面的问题,而是中文编码的问题,一般 Windows 系统上面建立的压缩文件,若是有有包含中文的文档或以中文做为文件名的文件时默认会采用 GBK 或其它编码,而 Linux 上面默认使用的是 UTF-8 编码,若是不加任何处理,直接解压的话可能会出现中文乱码的问题(有时候它会自动帮你处理),为了解决这个问题,咱们能够在解压时指定编码类型。
使用-O(英文字母,大写o)参数指定编码类型:
unzip -O GBK 中文压缩文件.zip
3.rar打包压缩命令
rar也是 Windows 上经常使用的一种压缩文件格式,在 Linux 上能够使用rar和unrar工具分别建立和解压 rar 压缩包。
$ sudo apt-get update
$ sudo apt-get install rar unrar
$ rm *.zip
$ rar a shiyanlou.rar .
上面的命令使用a参数添加一个目录~到一个归档文件中,若是该文件不存在就会自动建立。
注意:rar 的命令参数没有-,若是加上会报错。
$ rar d shiyanlou.rar .zshrc
$ rar l shiyanlou.rar
全路径解压:
$ unrar x shiyanlou.rar
去掉路径解压:
$ mkdir tmp
$ unrar e shiyanlou.rar tmp/
rar命令参数很是多,上面只涉及了一些基本操做
4.tar打包工具
在 Linux 上面更经常使用的是tar工具,tar 本来只是一个打包工具,只是同时仍是实现了对 7z,gzip,xz,bzip2 等工具的支持,这些压缩工具自己只能实现对文件或目录(单独压缩目录中的文件)的压缩,没有实现对文件的打包压缩,因此咱们也无需再单独去学习其余几个工具,tar 的解压和压缩都是同一个命令,只需参数不一样,使用比较方便。
下面先掌握tar命令一些基本的使用方式,即不进行压缩只是进行打包(建立归档文件)和解包的操做。
$ tar -cf shiyanlou.tar ~
上面命令中,-c表示建立一个 tar 包文件,-f用于指定建立的文件名,注意文件名必须紧跟在-f参数以后,好比不能写成tar -fc shiyanlou.tar,能够写成tar -f shiyanlou.tar -c ~。你还能够加上-v参数以可视的的方式输出打包的文件。上面会自动去掉表示绝对路径的/,你也能够使用-P保留绝对路径符。
$ mkdir tardir
$ tar -xf shiyanlou.tar -C tardir
$ tar -tf shiyanlou.tar
$ tar -cphf etc.tar /etc
对于建立不一样的压缩格式的文件,对于tar来讲是至关简单的,须要的只是换一个参数,这里咱们就以使用gzip工具建立*.tar.gz文件为例来讲明。
$ tar -czf shiyanlou.tar.gz ~
$ tar -xzf shiyanlou.tar.gz
如今咱们要使用其余的压缩工具建立或解压相应文件只须要更改一个参数便可:
压缩文件格式 |
参数 |
*.tar.gz |
-z |
*.tar.xz |
-J |
*tar.bz2 |
-j |
tar 命令的参数不少,不过经常使用的就是上述这些,须要了解更多你能够查看 man 手册获取更多帮助。
做业
天冷的时候,要是有个火炉就行了。这里有个有趣的程序:
$ sudo apt-get install libaa-bin
# 提示command not found,请自行解决
$ aafire
本节实验的文件系统操做的内容十分简单,只会包含几个命令的几个参数的讲解,但掌握这些也将对你在学习 Linux 和实验楼后续其余课程的过程当中有极大帮助。
由于本课程的定位为入门基础,尽快上手,故没有打算涉及太多理论内容,前面省略了关于 Linux 文件系统的一些基本知识,也由于咱们是在线实验环境,因此也避开了不多一部分但又十分重要的关于硬件的内容,咱们只能期待用户可以抱着提升自学能力的心态本身去补充相关的知识。
$ df
在实验楼的环境中你将看到以下的输出内容:
但在实际的物理主机上会更像这样:
通常使用状况下,咱们更多只是关心第一行的内容也就是环境中的rootfs
或者物理主机上的/dev/sda2
"rootfs" : (Root File System)它是 Ramfs(Ramfs 是一个很是简单的 Linux 文件系统用于实现磁盘缓存机制做为动态可调整大小的基于 ram 的文件系统)或者 tmpfs 的一个特殊实例,它做为系统启动时内核载入内存以后,在挂载真正的的磁盘以前的一个临时文件系统。一般的主机会在系统启动后用磁盘上的文件系统替换,只是在一些嵌入式系统中会只存在一个 rootfs ,或者像咱们目前遇到的状况运行在虚拟环境中共享主机资源的系统也可能会采用这种方式。
物理主机上的 /dev/sda2 是对应着主机硬盘的分区,后面的数字表示分区号,数字前面的字母 a 表示第几块硬盘(也多是可移动磁盘),你若是主机上有多块硬盘则可能还会出现 /dev/sdb,/dev/sdc 这些磁盘设备都会在 /dev 目录下以文件的存在形式。
接着你还会看到"1k-blocks"这个陌生的东西,它表示以磁盘块大小的方式显示容量,后面为相应的以块大小表示的已用和可用容量,在你了解 Linux 的文件系统以前这个就先无论吧,咱们以一种你应该看得懂的方式展现:
$ df -h
如今你就能够使用命令查看你主机磁盘的使用状况了。至于挂载点若是你还记得前面第 4 节介绍 Linux 目录树结构的内容,那么你就应该能很好的理解挂载的概念,这里就再也不赘述。
这个命令前面其实已经用了不少次了:
# 默认一样以 blocks 的大小展现
$ du
# 加上`-h`参数,以更易读的方式展现
$ du -h
-d
参数指定查看目录的深度
# 只查看1级目录的信息
-d$ du -h0 ~
# 查看2级
-d$ du -h1 ~
du
(estimate file space usage)命令与df
(report file system disk space usage)只用一字只差,首先就但愿注意不要弄混淆了,以能够像我这样从man手册中获取命令的完整描述,记全称就不会搞混了。
一般状况下,这一小节应该直接将如何挂载卸载磁盘,如何格式化磁盘,如何分区,但如你所见,咱们的环境中没东西给你挂,也没东西给你格和分,因此首先咱们会先建立一个虚拟磁盘来进行后续的练习操做
dd
命令用于转换和复制文件,不过它的复制不一样于cp
。以前提到过关于 Linux 的很重要的一点,一切即文件,在 Linux 上,硬件的设备驱动(如硬盘)和特殊设备文件(如/dev/zero
和/dev/random
)都像普通文件同样,只要在各自的驱动程序中实现了对应的功能,dd 也能够读取自和/或写入到这些文件。这样,dd
也能够用在备份硬件的引导扇区、获取必定数量的随机数据或者空数据等任务中。dd
程序也能够在复制时处理数据,例如转换字节序、或在 ASCII 与 EBCDIC 编码间互换。
dd
的命令行语句与其余的 Linux 程序不一样,由于它的命令行选项格式为选项
=
值
,而不是更标准的--
选项
值
或-
选项
=
值
。dd
默认从标准输入中读取,并写入到标准输出中,但能够用选项if
(input file,输入文件)和of
(output file,输出文件)改变。
咱们先来试试用dd
命令从标准输入读入用户输入到标准输出或者一个文件:
# 输出到文件
101# 或者 dd if=/dev/stdin of=test bs=10 count=1$ dd of=test bs=count=
# 输出到标准输出
if/dev/stdin/dev/stdout101$ dd=of=bs=count=
上述命令从标准输入设备读入用户输入(缺省值,因此可省略)而后输出到 test 文件,bs
(block size)用于指定块大小(缺省单位为 Byte,也可为其指定如'K','M','G'等单位),count
用于指定块数量。如上图所示,我指定只读取总共 10 个字节的数据,当我输入了“hello shiyanlou”以后加上空格回车总共 16 个字节(一个英文字符占一个字节)内容,显然超过了设定大小。使用和du
和cat
命令看到的写入完成文件实际内容确实只有 10 个字节(那个黑底百分号表示这里没有换行符),而其余的多余输入将被截取并保留在标准输入。
前面说到dd
在拷贝的同时还能够实现数据转换,那下面就举一个简单的例子:将输出的英文字符转换为大写再写入文件:
if/dev/of101$ dd=stdin=test bs=count=conv=ucase
你能够在man
文档中查看其余全部转换参数。
经过上面一小节,你应该掌握了dd
的基本使用,下面就来使用dd
命令来完成建立虚拟磁盘的第一步。
从/dev/zero
设备建立一个容量为 256M 的空文件:
if/dev/zero1256$ dd=of=virtual.img bs=M count=
$ du -h virtual.img
而后咱们要将这个文件格式化(写入文件系统),这里咱们要学到一个(准确的说是一组)新的命令来完成这个需求。
你能够在命令行输入 sudo mkfs
而后按下Tab
键,你能够看到不少个以 mkfs 为前缀的命令,这些不一样的后缀其实就是表示着不一样的文件系统,能够用 mkfs 格式化成的文件系统。
咱们能够简单的使用下面的命令来将咱们的虚拟磁盘镜像格式化为ext4
文件系统:
virtual$ sudo mkfs.ext4.img
能够看到实际 mkfs.ext4 是使用 mke2fs 来完成格式化工做的。mke2fs 的参数不少,不过咱们也不会常常格式化磁盘来玩,因此就掌握这基本用法吧,等你有特殊需求时,再查看 man 文档解决。
更多关于文件系统的知识,请查看wiki: 文件系统 ext3,ext4
若是你想一想知道 Linux 支持哪些文件系统你能够输入ls -l /lib/modules/$(uname -r)/kernel/fs
(咱们的环境中没法查看)查看。
用户在 Linux/UNIX 的机器上打开一个文件之前,包含该文件的文件系统必须先进行挂载的动做,此时用户要对该文件系统执行 mount 的指令以进行挂载。一般是使用在 USB 或其余可移除存储设备上,而根目录则须要始终保持挂载的状态。又由于 Linux/UNIX 文件系统能够对应一个文件而不必定要是硬件设备,因此能够挂载一个包含文件系统的文件到目录树。
Linux/UNIX 命令行的 mount 指令是告诉操做系统,对应的文件系统已经准备好,能够使用了,而该文件系统会对应到一个特定的点(称为挂载点)。挂载好的文件、目录、设备以及特殊文件便可提供用户使用。
咱们先来使用mount
来查看下主机已经挂载的文件系统:
$ sudo mount
输出的结果中每一行表示一个设备或虚拟设备,每一行最前面是设备名,而后是 on 后面是挂载点,type 后面表示文件系统类型,再后面是挂载选项(好比能够在挂载时设定以只读方式挂载等等)。
那么咱们如何挂载真正的磁盘到目录树呢,mount
命令的通常格式以下:
mount[options][source][directory]
一些经常使用操做:
mount[-o [操做选项][-t 文件系统类型][-w|--rw|--ro][文件系统源][挂载点]]
咱们如今直接来挂载咱们建立的虚拟磁盘镜像到/mnt
目录:
loop$ mount -o-t ext4 virtual.img /mnt
# 也能够省略挂载类型,不少时候 mount 会自动识别
# 以只读方式挂载
loop$ mount -o--ro virtual.img /mnt
# 或者mount -o loop,ro virtual.img /mnt
# 命令格式 sudo umount 已挂载设备名或者挂载点,如:
$ sudo umount /mnt
不过遗憾的是,因为咱们环境的问题(环境中使用的 Linux 内核在编译时没有添加对 Loop device的支持),因此你将没法挂载成功:
另外关于 loop 设备,你可能会有诸多疑问,那么请看下面来自维基百科/dev/loop的说明:
在类 UNIX 系统中,/dev/loop(或称vnd (vnode disk)、lofi(循环文件接口))是一种伪设备,这种设备使得文件能够如同块设备通常被访问。
在使用以前,循环设备必须与现存文件系统上的文件相关联。这种关联将提供给用户一个应用程序接口,接口将容许文件视为块特殊文件(参见设备文件系统)使用。所以,若是文件中包含一个完整的文件系统,那么这个文件就能如同磁盘设备通常被挂载。
这种设备文件常常被用于光盘或是磁盘镜像。经过循环挂载来挂载包含文件系统的文件,便使处在这个文件系统中的文件得以被访问。这些文件将出如今挂载点目录。若是挂载目录中自己有文件,这些文件在挂载后将被禁止使用。
一样由于环境缘由中没有物理磁盘,也没法建立虚拟磁盘的缘由咱们就没法实验练习使用该命令了,下面我将以个人物理主机为例讲解如何为磁盘分区。
# 查看硬盘分区表信息
-l$ sudo fdisk
输出结果中开头显示了我主机上的磁盘的一些信息,包括容量扇区数,扇区大小,I/O 大小等信息。
咱们重点开一下中间的分区信息,/dev/sda1,/dev/sda2 为主分区分别安装了 Windows 和 Linux 操做系统,/dev/sda3 为交换分区(能够理解为虚拟内存),/dev/sda4 为扩展分区其中包含 /dev/sda5,/dev/sda6,/dev/sda7,/dev/sda8 四个逻辑分区,由于主机上有几个分区之间有空隙,没有对齐边界扇区,因此分区之间的不是彻底连续的。
# 进入磁盘分区模式
virtual$ sudo fdisk.img
在进行操做前咱们首先应先规划好咱们的分区方案,这里我将在使用 128M(可用 127M 左右)的虚拟磁盘镜像建立一个 30M 的主分区剩余部分为扩展分区包含 2 个大约 45M 的逻辑分区。
操做完成后输入p
查看结果以下:
最后不要忘记输入w
写入分区表。
0$ sudo losetup /dev/loopvirtual.img
# 若是提示设备忙你也能够使用其它的回环设备,"ls /dev/loop*"参看全部回环设备
# 解除设备关联
0$ sudo losetup -d /dev/loop
而后再使用mkfs
格式化各分区(前面咱们是格式化整个虚拟磁盘镜像文件或磁盘),不过格式化以前,咱们还要为各分区创建虚拟设备的映射,用到kpartx
工具,须要先安装:
$ sudo apt-get install kpartx
0$ sudo kpart kpartx -av /dev/loop
# 取消映射
0$ sudo kpart kpartx -dv /dev/loop
接着再是格式化,咱们将其所有格式化为 ext4:
$ sudo mkfs.ext4 -q /dev/mapper/loop0p1
$ sudo mkfs.ext4 -q /dev/mapper/loop0p5
$ sudo mkfs.ext4 -q /dev/mapper/loop0p6
格式化完成后在/media
目录下新建四个空目录用于挂载虚拟磁盘:
mkdir_13$-p /media/virtualdisk{..}
# 挂载磁盘分区
$ sudo mount /dev/mapper/loop0p1 /media/virtualdisk_1
$ sudo mount /dev/mapper/loop0p5 /media/virtualdisk_2
$ sudo mount /dev/mapper/loop0p6 /media/virtualdisk_3
# 卸载磁盘分区
$ sudo umount /dev/mapper/loop0p1
$ sudo umount /dev/mapper/loop0p5
$ sudo umount /dev/mapper/loop0p6
而后:
$ df -h
cowsay
命令,可让你在终端里以一种动物说话的形式打印出一段话。
# 安装
$ sudo apt-get install cowsay
# 默认是一只牛
$ cowsay hello shiyanlou
# 加上'-l'参数打印全部支持的动物(其实不仅是动物)种类
$ cowsay -l
# 使用'-f'参数选择动物种类
$ cowsay -f elephant hello shiyanlou
# 此外它还能够结合咱们以前的做业讲过的 fortune 命令一块儿使用
| cowsay -f daemon$ fortune
Linux下的帮助命令
实验介绍
咱们时常使用 Linux 的命令,一些经常使用的命令即便不背咱们也能记住,而一些较长的命令或是一些不经常使用的参数甚至是不经常使用的命令到用时怎么也想不出来。本课程将带你好好利用 Linux 系统所自带的帮助工具与文档了。
实验涉及的知识点
1、内建命令与外部命令
什么是内建命令,什么是外部命令呢?这和帮助命令又有什么关系呢?
由于有一些查看帮助的工具在内建命令与外建命令上是有区别对待的。
内建命令其实是 shell 程序的一部分,其中包含的是一些比较简单的 Linux 系统命令,这些命令是写在bash源码的builtins里面的,并由 shell 程序识别并在 shell 程序内部完成运行,一般在 Linux 系统加载运行时 shell 就被加载并驻留在系统内存中。并且解析内部命令 shell 不须要建立子进程,所以其执行速度比外部命令快。好比:history、cd、exit 等等。
外部命令是 Linux 系统中的实用程序部分,由于实用程序的功能一般都比较强大,因此其包含的程序量也会很大,在系统加载时并不随系统一块儿被加载到内存中,而是在须要时才将其调用内存。虽然其不包含在 shell 中,可是其命令执行过程是由 shell 程序控制的。外部命令是在 Bash 以外额外安装的,一般放在/bin,/usr/bin,/sbin,/usr/sbin等等。好比:ls、vi等。
简单来讲就是一个是天生自带的天赋技能,一个是后天得来附加技能。咱们能够使用 type 命令来区分命令是内建的仍是外部的。例如这两个得出的结果是不一样的
type exit
type service
获得的是两种结果,如果对ls你还能获得第三种结果
#获得这样的结果说明是内建命令,正如上文所说内建命令都是在 bash 源码中的 builtins 的.def中
xxx is a shell builtin
#获得这样的结果说明是外部命令,正如上文所说,外部命令在/usr/bin or /usr/sbin等等中
xxx is /usr/sbin/xxx
#如果获得alias的结果,说明该指令为命令别名所设定的名称;
xxx is an alias for xx --xxx
2、帮助命令的使用
1. help 命令
本实验环境是 zsh,而 zsh 中内置并无 help 命令,咱们能够进入 bash 中,在 bash 中内置有该命令
bash
作好了以上的准备,咱们就能够愉快的使用 help 命令了,咱们能够尝试下这个命令:
help ls
获得的结果如图所示,为何是这样的结果?
由于 help 命令是用于显示 shell 内建命令的简要帮助信息。帮助信息中显示有该命令的简要说明以及一些参数的使用以及说明,必定记住 help 命令只能用于显示内建命令的帮助信息,否则就会获得你刚刚获得的结果。如图中 exit,cd 即是内建命令
那若是是外部命令怎么办,不能就这么抛弃它呀。其实外部命令的话基本上都有一个参数--help,这样就能够获得相应的的帮助,看到你想要的东西了。试试下面这个命令是否是能看到你想要的东西了。
ls --help
2. man 命令
你能够尝试下这个命令
man ls
获得的内容比用 help 更多更详细,并且 man 没有内建与外部命令的区分,由于 man 工具是显示系统手册页中的内容,也就是一本电子版的字典,这些内容大多数都是对命令的解释信息,还有一些相关的描述。经过查看系统文档中的 man 也能够获得程序的更多相关信息和 Linux 的更多特性。
是否是好用许多,固然也不表明 help 就没有存在的必要,当你很是紧急只是忘记改用那个参数什么的时候,help 这种显示简单扼要的信息就特别使用,如果不太紧急的时候就能够用 man 这种详细描述的查询方式
在尝试上面这个命令是咱们会发现最左上角显示“ LS (1)”,在这里,“ LS ”表示手册名称,而“(1)”表示该手册位于第一章节。这个章节又是什么?在 man 手册中一共有这么几个章节
章节数 |
说明 |
1 |
Standard commands (标准命令) |
2 |
System calls (系统调用) |
3 |
Library functions (库函数) |
4 |
Special devices (设备说明) |
5 |
File formats (文件格式) |
6 |
Games and toys (游戏和娱乐) |
7 |
Miscellaneous (杂项) |
8 |
Administrative Commands (管理员命令) |
9 |
其余(Linux特定的), 用来存放内核例行程序的文档。 |
打开手册以后咱们能够经过 pgup 与 pgdn 或者上下键来上下翻看,能够按 q 退出当前页面
3. info 命令
要是你以为man显示的信息都还不够,知足不了你的需求,那试试这个命令
#该命令在本环境中没有,通常的 bash 会自带的有。
info ls
获得的信息是否是比 man 还要多了,info 来自自由软件基金会的 GNU 项目,是 GNU 的超文本帮助系统,可以更完整的显示出 GNU 信息。因此获得的信息固然更多
man 和 info 就像两个集合,它们有一个交集部分,但与 man 相比,info 工具可显示更完整的 GNU 工具信息。若 man 页包含的某个工具的概要信息在 info 中也有介绍,那么 man 页中会有“请参考 info 页更详细内容”的字样。
3、实验总结
本节咱们讲解了内建与外部命令的差异,以及相关的帮助命令的使用。这样经过官方的文档帮助咱们最快最有效率的解决当前所遇到的窘境。灵活的使用三个帮助命令,可以很大的提升咱们的工做效率
咱们时常会有一些按期定时的任务,如周期性的清理一下/tmp,周期性的去备份一次数据库,周期性的分析日志等等。并且有时候由于某些因素的限制,执行该任务的时间会很尴尬。本课程将带你很好的利用 Linx 系统的计划工具
crontab 命令常见于 Unix 和类 Unix 的操做系统之中(Linux 就属于类 Unix 操做系统),用于设置周期性被执行的指令。该命令从输入设备读取指令,并将其存放于 crontab 文件中,以供以后读取和执行。一般,crontab 储存的指令被守护进程激活,crond 为其守护进程,crond 经常在后台运行,每一分钟会检查一次是否有预约的做业须要执行。
经过 crontab 命令,咱们能够在固定的间隔时间执行指定的系统指令或 shell script 脚本。时间间隔的单位能够是分钟、小时、日、月、周的任意组合。
crontab 在本实验环境中须要作一些特殊的准备,首先咱们会启动 rsyslog,以便咱们能够经过日志中的信息来了解咱们的任务是否真正的被执行了(在本实验环境中须要手动启动,而在本身本地中 Ubuntu 会默认自行启动不须要手动启动)
sudoservice rsyslog start
在本实验环境中 crontab 也是不被默认启动的,同时不能在后台由 upstart 来管理,因此须要咱们来启动它(一样在本实验环境中须要手动启动,本身的本地 Ubuntu 的环境中也不须要手动启动)
sudocron-f &
下面将开始 crontab 的使用了,咱们经过下面一个命令来添加一个计划任务
-ecrontab
第一次启动会出现这样一个画面,这是让咱们选择编辑的工具,选择第一个基本的 vim 就能够了
而选择后咱们会进入这样一个画面,这就是添加计划的地方了,与通常的配置文档相同,以#号开头的都是注释,经过文档的最后一排咱们能够猜猜 crontab 的格式是什么样的呢?
咱们经过这样一张图来了解 crontab 的文档编辑的格式与参数
在了解命令格式以后,咱们经过这样的一个例子来完成一个任务的添加,在文档的最后一排加上这样一排命令,该任务是每分钟咱们会在/home/shiyanlou目录下建立一个以当前的年月日时分秒为名字的空白文件
/1 * * * * touch /home/shiyanlou/*$(date +\%Y\%m\%d\%H\%M\%S)
注意 “ % ” 在 crontab 文件中,有结束命令行、换行、重定向的做用,前面加 ” \ ” 符号转意,不然,“ % ” 符号将执行其结束命令行或者换行的做用,而且其后的内容会被作为标准输入发送给前面的命令。
添加成功后咱们会获得最后一排 installing new crontab 的一个提示
固然咱们也能够经过这样的一个指令来查看咱们添加了哪些任务
-lcrontab
经过图中的显示,咱们也能够看出,咱们正确的保存而且添加成功了该任务的
虽然咱们添加了任务,可是若是 cron 的守护进程并无启动,它根本都不会监测到有任务,固然也就不会帮咱们执行,咱们能够经过一下2种方式来肯定咱们的 cron 是否成功的在后台启动,默默的帮咱们作事,如果没有就得执行上文准备中的第二步了
grepps aux |cron
or
pgrep cron
经过这个截图咱们能够看到任务在建立以后便建立了一个当时时间的文件(也就是10点18分04秒的时候),后续在每分钟的01秒时执行一次咱们的任务
咱们经过这样一个命令能够查看到执行任务命令以后在日志中的信息反馈
-flogsudo tail/var//syslog
从图中咱们能够看到分别在10点1八、1九、20、2一、2二、23分的01秒为咱们在 shiyanlou 用户的家目录下建立了文件
当咱们并不须要这个任务的时候咱们能够使用这么一个命令去删除任务
crontab-r
经过图中咱们能够看出咱们删除以后再查看任务列表,系统已经显示该用户并无任务哦
这个 crontab -e 是针对使用者的 cron 來设计的,也就是每一个用户在添加任务,就会在 /var/spool/cron/crontabs 中添加一个该用户本身的任务文档,这样能够作到隔离,独立,不会混乱。
若是是系統的例行性任務時,该怎么办呢?是否仍是须要以 crontab -e 來管理你的例行性工做排程呢?固然不须要,你只要编辑 /etc/crontab 這個档案就能够啦!有一點须要特別注意喔!那就是 crontab -e 這個 crontab 实际上是 /usr/bin/crontab 这个执行的,只是你能够 root 的身份編輯一下这个文档!
基本上, cron 这个服务的最低侦测限制是分钟,因此 cron 会每分钟去读取一次 /etc/crontab 与 /var/spool/cron/crontabs 里面的资料內容 』,所以,只要你编辑完 /etc/crontab 这个文档,而且將他存储以后,那么 cron 的设定就自动的执行了!
在/etc目录下,咱们能够观察到关于 cron 的文件有一下几个,他们的做用又是什么
固然,以上的时间均是系统默认时间,能够根据本身的需求进行修改。
更多的相关知识咱们能够用上节所学到的man命令来查看,
固然若想进一步的学习该知识或者相关只是可查看鸟哥私房菜
本节咱们讲解了 crontab 的一些简单的应用和一些简单的概念。crontab 是 Linux 系统中添加计划任务,定时执行一些必要的脚本所必不可少的工具。
顺序执行、选择执行、管道、cut 命令、grep 命令、wc 命令、sort 命令等,高效率使用 Linux 的技巧。
一般状况下,咱们每次只能在终端输入一条命令,按下回车执行,执行完成后,咱们再输入第二条命令,而后再按回车执行…… 你可能会遇到以下使用场景:我须要使用apt-get
安装一个软件,而后安装完成后当即运行安装的软件(或命令工具),又恰巧你的主机才更换的软件源尚未更新软件列表(好比以前咱们的环境中,每次从新开始实验就得sudo apt-get update,如今已经没有这个问题了),那么你可能会有以下一系列操做:
$ sudo apt-get update
# 等待——————————而后输入下面的命令
$ sudo apt-get install some-tool
# 等待——————————而后输入下面的命令
$ some-tool
这时你可能就会想要是我能够一次性输入完,让它本身去一次执行各命令就行了,这就是咱们这一小节要解决的问题。
简单的顺序执行你能够使用;
来完成,好比上述操做你能够:
getget$ sudo apt-update;sudo apt-install some-tool;some-tool
# 让它本身运行
关于上面的操做,不知你有没有思考过一个问题,若是咱们在让它自动顺序执行命令时,前面的命令执行不成功,然后面的命令又依赖与上一条命令的结果,那么就会形成花了时间,最终却获得一个错误的结果,并且有时候直观的看你还没法判断结果是否正确。那么咱们须要可以有选择性的来执行命令,好比上一条命令执行成功才继续下一条,或者不成功又该作出其它什么处理,好比咱们使用which
来查找是否安装某个命令,若是找到就执行该命令,不然什么也不作(虽然这个操做没有什么实际意义,但可帮你更好的理解一些概念):
/dev/nullin$ which cowsay>&& cowsay -f head-ohch~
你若是没有安装cowsay
,你能够先执行一次上述命令,你会发现什么也没发生,你再安装好以后你再执行一次上述命令,你也会发现一些惊喜。
上面的&&
就是用来实现选择性执行的,它表示若是前面的命令执行结果(不是表示终端输出的内容,而是表示命令执行状态的结果)返回0则执行后面的,不然不执行,你能够从$?
环境变量获取上一次命令的返回结果:
学习过 C 语言的用户应该知道在 C 语言里面&&
表是逻辑与,并且还有一个||
表示逻辑或,一样 Shell 也有一个||
,它们的区别就在于,shell中的这两个符号除了也可用于表示逻辑与和或以外,就是能够实现这里的命令执行顺序的简单控制。||
在这里就是与&&
相反的控制效果,当上一条命令执行结果为≠0($?≠0)时则执行它后面的命令:
/dev/null||"cowsay has not been install, please run 'sudo apt-get install cowsay' to install"$ which cowsay>echo
除了上述基本的使用以外,咱们还能够结合这&&
和||
来实现一些操做,好比:
whichecho"exist"echo"not exist"$cowsay>/dev/null &&||
我画个流程图来解释一下上面的流程:
上面咱们讲到将&&
和||
结合起来使用,那么是否以任意顺序都行?好比上面咱们是&&
在前||
在后,反过来能够么?会不会有问题?
管道是什么,管道是一种通讯机制,一般用于进程间的通讯(也可经过socket进行网络通讯),它表现出来的形式就是将前面每个进程的输出(stdout)直接做为下一个进程的输入(stdin)。
管道又分为匿名管道和具名管道(这里将不会讨论在源程序中使用系统调用建立并使用管道的状况,它与命令行的管道在内核中实际都是采用相同的机制)。咱们在使用一些过滤程序时常常会用到的就是匿名管道,在命令行中由|
分隔符表示,|
在前面的内容中咱们已经屡次使用到了。具名管道简单的说就是有名字的管道,一般只会在源程序中用到具名管道。下面咱们就将经过一些经常使用的能够使用管道的"过滤程序"来帮助你熟练管道的使用。
先试用一下管道,好比查看/etc
目录下有哪些文件和目录,使用ls
命令来查看:
$ ls -al /etc
有太多内容,屏幕不能彻底显示,这时候能够使用滚动条或快捷键滚动窗口来查看。不过这时候能够使用管道:
| less$ ls -al /etc
经过管道将前一个命令(ls
)的输出做为下一个命令(less
)的输入,而后就能够一行一行地看。
打印/etc/passwd
文件中以:
为分隔符的第1个字段和第6个字段分别表示用户名和其家目录:
-d':'-f$ cut /etc/passwd1,6
打印/etc/passwd
文件中每一行的前N个字符:
# 前五个(包含第五个)
5$ cut /etc/passwd -c -
# 前五个以后的(包含第五个)
5$ cut /etc/passwd -c-
# 第五个
5$ cut /etc/passwd -c
# 2到5之间的(包含第五个)
25$ cut /etc/passwd -c-
grep
命令是很强大的,也是至关经常使用的一个命令,它结合正则表达式能够实现很复杂却很高效的匹配和查找,不过在学习正则表达式以前,这里介绍它简单的使用,而关于正则表达式后面将会有单独一小节介绍到时会再继续学习grep
命令和其余一些命令。
grep
命令的通常形式为:
grep[命令选项][文件]...用于匹配的表达式...
仍是先体验一下,咱们搜索/home/shiyanlou
目录下全部包含"shiyanlou"的全部文本文件,并显示出如今文本中的行号:
grep"shiyanlou"$-rnI~
-r
参数表示递归搜索子目录中的文件,-n
表示打印匹配项行号,-I
表示忽略二进制文件。这个操做实际没有多大意义,但能够感觉到grep
命令的强大与实用。
固然也能够在匹配字段中使用正则表达式,下面简单的演示:
# 查看环境变量中以"yanlou"结尾的字符串
export".*yanlou$"$| grep
其中$
就表示一行的末尾。
wc 命令用于统计并输出一个文件中行、单词和字节的数目,好比输出/etc/passwd
文件的统计信息:
$ wc /etc/passwd
分别只输出行数、单词数、字节数、字符数和输入文本中最长一行的字节数:
# 行数
$ wc -l /etc/passwd
# 单词数
$ wc -w /etc/passwd
# 字节数
$ wc -c /etc/passwd
# 字符数
$ wc -m /etc/passwd
# 最长行字节数
$ wc -L /etc/passwd
注意:对于西文字符来讲,一个字符就是一个字节,但对于中文字符一个汉字是大于2个字节的,具体数目是由字符编码决定的
再来结合管道来操做一下,下面统计 /etc 下面全部目录数:
-l$ ls -dl /etc/*/ | wc
这个命令前面咱们也是用过屡次,功能很简单就是将输入按照必定方式排序,而后再输出,它支持的排序有按字典排序,数字排序,按月份排序,随机排序,反转排序,指定特定字段进行排序等等。
默认为字典排序:
sort$ cat /etc/passswd |
反转排序:
sort$ cat /etc/passwd |-r
按特定字段排序:
sort':'3$ cat /etc/passwd |-t-k
上面的-t
参数用于指定字段的分隔符,这里是以":"做为分隔符;-k
字段号
用于指定对哪个字段进行排序。这里/etc/passwd
文件的第三个字段为数字,默认状况下是一字典序排序的,若是要按照数字排序就要加上-n
参数:
sort':'3$ cat /etc/passwd |-t-k-n
uniq
命令能够用于过滤或者输出重复行。
咱们能够使用history
命令查看最近执行过的命令(实际为读取${SHELL}_history文件,如咱们环境中的~/.zsh_history文件),不过你可能只想查看使用了那个命令而不须要知道具体干了什么,那么你可能就会要想去掉命令后面的参数而后去掉重复的命令:
history-d' '-f$| cut -c 8- | cut1 | uniq
而后通过层层过滤,你会发现确是只输出了执行的命令那一列,不过去重效果好像不明显,仔细看你会发现它趋势去重了,只是不那么明显,之因此不明显是由于uniq
命令只能去连续重复的行,不是全文去重,因此要达到预期效果,咱们先排序:
history-d' '-f$| cut -c 8- | cut1 | sort | uniq
# 或者$ history | cut -c 8- | cut -d ' ' -f 1 | sort -u
这就是 Linux/UNIX 哲学吸引人的地方,大繁至简,一个命令只干一件事却能干到最好。
# 输出重复过的行(重复的只输出一个)及重复次数
history-d' '-f$| cut -c 8- | cut1 | sort | uniq -dc
# 输出全部重复的行
history-d' '-f$| cut -c 8- | cut1 | sort | uniq -D
文本处理命令还有不少,下一节将继续介绍一些经常使用的文本处理的命令。
使用之前介绍过的方法,安装aview
和imagemagick
,而后用asciiview
命令显示图片,使用方法能够用 man 命令查看。
dh能够的,这个实验先用实验楼的环境打开那个网址,把它保存在Desktop上面,而后再用asciiview命令打开就好,卧槽,看论坛网友的做业完成的,真有一种在上课学习的感受,我爱实验楼!
Linus大神的照片地址http://labfile.oss.aliyuncs.com/courses/1/Linus.png
这一节咱们将介绍这几个命令tr
(注意不是tar),col
,join
,paste
。实际这一节是上一节关于能实现管道操做的命令的延续,因此咱们依然将结合管道来熟悉这些命令的使用。
tr 命令能够用来删除一段文本信息中的某些文字。或者将其进行转换。
tr[option].SET1[SET2]..
选项 |
说明 |
|
删除和set1匹配的字符,注意不是全词匹配也不是按字符顺序匹配 |
|
去除set1指定的在输入文本中连续并重复的字符 |
# 删除 "hello shiyanlou" 中全部的'o','l','h'
echo'hello shiyanlou'-d'olh'$| tr
# 将"hello" 中的ll,去重为一个l
echo'hello'-s'l'$| tr
# 将输入文本,所有转换为大写或小写输出
'[:lower:]''[:upper:]'$ cat /etc/passwd | tr
# 上面的'[:lower:]' '[:upper:]'你也能够简单的写做'[a-z]' '[A-Z]',固然反过来将大写变小写也是能够的
更多 tr 的使用,你能够使用--help
或者man tr
得到。
col 命令能够将Tab
换成对等数量的空格建,或反转这个操做。
col [option]
选项 |
说明 |
|
将 |
|
将空格转换为 |
# 查看 /etc/protocols 中的不可见字符,能够看到不少 ^I ,这其实就是 Tab 转义成可见字符的符号
$ cat -A /etc/protocols
# 使用 col -x 将 /etc/protocols 中的 Tab 转换为空格,而后再使用 cat 查看,你发现 ^I 不见了
| col -x |$ cat /etc/protocolscat -A
学过数据库的用户对这个应该不会陌生,这个命令就是用于将两个文件中包含相同内容的那一行合并在一块儿。
join[option]... file1 file2
选项 |
说明 |
|
指定分隔符,默认为空格 |
|
忽略大小写的差别 |
|
指明第一个文件要用哪一个字段来对比,,默认对比第一个字段 |
|
指明第二个文件要用哪一个字段来对比,,默认对比第一个字段 |
# 建立两个文件
'1 hello'$ echo> file1
'1 shiyanlou'$ echo> file2
$ join file1 file2
# 将/etc/passwd与/etc/shadow两个文件合并,指定以':'做为分隔符
':'$ sudo join -t/etc/passwd /etc/shadow
# 将/etc/passwd与/etc/group两个文件合并,指定以':'做为分隔符, 分别比对第4和第3个字段
':'1423$ sudo join -t-/etc/passwd -/etc/group
paste
这个命令与join
命令相似,它是在不对比数据的状况下,简单地将多个文件合并一块儿,以Tab
隔开。
paste[option]file...
选项 |
说明 |
|
指定合并的分隔符,默认为Tab |
|
不合并到一行,每一个文件为一行 |
echo$hello > file1
echo$shiyanlou > file2
echo$www.shiyanlou.com > file3
-d':'$ pastefile1 file2 file3
-s$ pastefile1 file2 file3
上面这些命令不是全部你都会常常用到,不过它们确是很实用的,熟练掌握以后,能够减轻不少工做量,好比不停的用鼠标操做在 gedit 里面复制粘贴赋值粘贴,将两个文件的内容合并为一个文件,这本来只须要一个命令就能完成。
一、在《文件打包与解压缩》一节实验中提到 Windows/dos 与 Linux/UNIX 文本文件一些特殊字符不一致,如断行符 Windows 为 CR+LF(\r\n
),Linux/UNIX 为 LF(\n
)。使用cat -A
文本
能够看到文本中包含的不可见特殊字符。Linux 的\n
表现出来就是一个$
,而 Windows/dos 的表现为^M$
,能够直接使用dos2unix
和unix2dos
工具在两种格式之间进行转换,使用file
命令能够查看文件的具体类型。不过如今但愿你在不使用上述两个转换工具的状况下,使用前面学过的命令手动完成 dos 文本格式到 UNIX 文本格式的转换。
二、还记得小时候在小霸王上面玩的小蜜蜂游戏么?它的正统名字应该是Space Invaders:太空侵略者。
使用下面这个命令能够安装,之因此叫 ninvaders 是由于这款游戏是基于 ncurses 命令行图形库作的:
getsudo apt-install ninvaders
你可能对重定向这个概念感到些许陌生,但你应该在前面的课程中屡次见过>
或>>
操做了,并知道他们分别是将标准输出导向一个文件或追加到一个文件中。这其实就是重定向,将本来输出到标准输出的数据重定向到一个文件中,由于标准输出(/dev/stdout
)自己也是一个文件,咱们将命令输出导向另外一个文件天然也是没有任何问题的。
下面咱们简单的回顾一下咱们前面常常用到的两个重定向操做:
'hello shiyanlou'$ echo> redirect
'www.shiyanlou.com'>> $ echoredirect
$ cat redirect
固然前面没有用到的<
和<<
操做也是没有问题的,如你理解的同样,它们的区别在于重定向的方向不一致而已,>
表示是从左到右,<
右到左。
在更多了解 Linux 的重定向以前,咱们须要先知道一些基本的东西,前面咱们已经提到过 Linux 默认提供了三个特殊设备,用于终端的显示和输出,分别为stdin
(标准输入,对应于你在终端的输入),stdout
(标准输出,对应于终端的输出),stderr
(标准错误输出,对应于终端的输出)。
文件描述符 |
设备文件 |
说明 |
|
|
标准输入 |
|
|
标准输出 |
|
|
标准错误 |
文件描述符:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者建立一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写每每会围绕着文件描述符展开。可是文件描述符这一律念每每只适用于 UNIX、Linux 这样的操做系统。
另外还有一个符号-
,它能够同时做为前一个命令的。
咱们能够这样使用这些文件描述符:
默认使用终端的标准输入做为命令的输入和标准输出做为命令的输出
$ cat
(按Ctrl+C退出)
将cat的连续输出(heredoc方式)重定向到一个文件
$ mkdir Documents
$ cat > Documents/test.c <<EOF
#include <stdio.h>
int main()
{
printf"hello world\n" ();
return0 ;
}
EOF
将一个文件做为命令的输入,标准输出做为命令的输出
$ cat Documents/test.c
将echo命令经过管道传过来的数据做为cat命令的输入,将标准输出做为命令的输出
echo'hi'$| cat
将echo命令的输出从默认的标准输出重定向到一个普通文件
'hello shiyanlou'$ echo> redirect
$ cat redirect
初学者这里要注意不要将管道和重定向混淆,管道默认是链接前一个命令的输出到下一个命令的输入,而重定向一般是须要一个文件来创建两个命令的链接,你能够仔细体会一下上述第三个操做和最后两个操做的异同点。
重定向标准输出到文件,这是一个很实用的操做,另外一个很实用的操做是将标准错误重定向,标准输出和标准错误都被指向伪终端的屏幕显示,因此咱们常常看到的一个命令的输出一般是同时包含了标准输出和标准错误的结果的。好比下面的操做:
# 使用cat 命令同时读取两个文件,其中一个存在,另外一个不存在
$ cat Documents/test.c hello.c
# 你能够看到除了正确输出了前一个文件的内容,还在末尾出现了一条错误信息
# 下面咱们将输出重定向到一个文件,根据咱们前面的经验,这里将在看不到任何输出了
$ cat Documents/test.c hello.c > somefile
遗憾的是,这里依然出现了那条错误信息,这正是由于如我上面说的那样,标准输出和标准错误虽然都指向终端屏幕,实际它们并不同。那有的时候咱们就是要能够隐藏某些错误或者警告,那又该怎么作呢。这就须要用到咱们前面讲的文件描述符了:
# 将标准错误重定向到标准输出,再将标准输出重定向到文件,注意要将重定向到文件写到前面
21$ cat Documents/test.c hello.c >somefile >&
# 或者只用bash提供的特殊的重定向符号"&"将标准错误和标准输出同时重定向到文件
$ cat Documents/test.c hello.c &>somefilehell
注意你应该在输出重定向文件描述符前加上&
,不然shell会当作重定向到一个文件名为1的文件中
tee
命令同时重定向到多个文件常常你可能还有这样的需求,除了将须要将输出重定向到文件以外也须要将信息打印在终端,那么你能够使用tee
命令来实现:
echo'hello shiyanlou'$| tee hello
你应该能够看出咱们前面的重定向操做都只是临时性的,即只对当前命令有效,那如何作到“永久”有效呢,好比在一个脚本中,你须要某一部分的命令的输出所有进行重定向,难道要让你在每一个命令上面加上临时重定向的操做嘛,固然不须要,咱们能够使用exec
命令实现“永久”重定向。exec
命令的做用是使用指定的命令替换当前的 Shell,及使用一个进程替换当前进程,或者指定新的重定向:
# 先开启一个子 Shell
$ zsh
# 使用exec替换当前进程的重定向,将标准输出重定向到一个文件
1$ exec>somefile
# 后面你执行的命令的输出都将被重定向到文件中,直到你退出当前子shell,或取消exec的重定向(后面将告诉你怎么作)
$ ls
$ exit
$ cat somefile
默认在 Shell 中能够有9个打开的文件描述符,上面咱们使用了也是它默认提供的0
,1
,2
号文件描述符,另外咱们还能够使用3-8的文件描述符,只是它们默认没有打开而已,你能够使用下面命令查看当前 Shell 进程中打开的文件描述符:
cd$/dev/fd/;ls -Al
一样使用exec
命令能够建立新的文件描述符:
$ zsh
3$ exec>somefile
# 先进入目录,再查看,不然你可能不能获得正确的结果,而后再回到上一次的目录
$ cd /dev/fd/;ls -Al;cd -
# 注意下面的命令>与&之间不该该有空格,若是有空格则会出错
"this is test"3$ echo>&
$ cat somefile
$ exit
如上面咱们打开的3号文件描述符,能够使用以下操做将它关闭:
exec$3>&-
cdcd$/dev/fd;ls -Al;-
在 Linux 中有一个被成为“黑洞”的设备文件,因此导入它的数据都将被“吞噬”。
在类 UNIX 系统中,/dev/null,或称空设备,是一个特殊的设备文件,它一般被用于丢弃不须要的输出流,或做为用于输入流的空文件,这些操做一般由重定向完成。读取它则会当即获得一个EOF。
咱们能够利用设个/dev/null
屏蔽命令的输出:
1/dev/null21$ cat Documents/test.c nefile>>&
向上面这样的操做将使你得不到任何输出结果。
xargs 是一条 UNIX 和类 UNIX 操做系统的经常使用命令。它的做用是将参数列表转换成小块分段传递给其余命令,以免参数列表过长的问题。
这个命令在有些时候十分有用,特别是当用来处理产生大量输出结果的命令如 find,locate 和 grep 的结果,详细用法请参看 man 文档。
-d-fecho$ cut:1 < /etc/passwd | sort | xargs
上面这个命令用于将/etc/passwd
文件按:
分割取第一个字段排序后,使用echo
命令生成一个列表。
一、理解下面这段代码的的做用,实际这段代码不会正常工做,请结合这一小节的知识分析这段代码没有正确工做的缘由,并设法解决这个问题。
若是你尚未 Shell 脚本编程的基础,你能够选择跳过或者到这里高级 Bash 编程指南学习
whilereaddofilename;
$filename rm -iv
done<<(ls)
二、以前介绍过一个在命令行将图片转换为 ascii 字符查看的工具 aview/asciiview,不过它是黑白的。如今,这里是个彩色的:
$ sudo apt-get install caca-utils
$ cacaview <pic_file>
$ cacademo
$ cacafire
虽然咱们这一节的标题是正则表达式,但实际这一节实验只是介绍grep
,sed
,awk
这三个命令,而正则表达式做为这三个命令的一种使用方式(命令输出中能够包含正则表达式)。正则表达式自己的内容不少,要把它说明清楚须要单独一门课程来实现,不过咱们这一节中涉及到的相关内容一般也可以知足不少状况下的需求了。
想要更深刻地学习使用正则表达式,在这里 正则表达式基础。
什么是正则表达式呢?
正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为 regex、regexp 或 RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在不少文本编辑器里,正则表达式一般被用来检索、替换那些符合某个模式的文本。
许多程序设计语言都支持利用正则表达式进行字符串操做。例如,在 Perl 中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由 UNIX 中的工具软件(例如sed
和grep
)普及开的。正则表达式一般缩写成“regex”,单数有 regexp、regex,复数有 regexps、regexes、regexen。
简单的说形式和功能上正则表达式和咱们前面讲的通配符很像,不过它们之间又有很大差异,特别在于一些特殊的匹配字符的含义上,但愿初学者注意不要将二者弄混淆。
假设咱们有这样一个文本文件,包含"shiyanlou",和"shilouyan"这两个字符串,一样一个表达式:
shi*
若是这做为一个正则表达式,它将只能匹配 shi,而若是不是做为正则表达式*
做为一个通配符,则将同时匹配这两个字符串。这是为何呢?由于在正则表达式中*
表示匹配前面的子表达式(这里就是它前面一个字符)零次或屡次,好比它能够匹配"sh","shii","shish","shiishi"等等,而做为通配符表示匹配通配符后面任意多个任意字符,因此它能够匹配"shiyanlou",和"shilouyan"两个字符。
体验完了,下面就来开始正式学习正则表达式吧。
一个正则表达式一般被称为一个模式(pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。
|
竖直分隔符表示选择,例如"boy|girl"能够匹配"boy"或者"girl"
数量限定除了咱们举例用的*
,还有+
加号,?
问号,.
点号,若是在一个模式中不加数量限定符则表示出现一次且仅出现一次:
+
表示前面的字符必须出现至少一次(1次或屡次),例如,"goo+gle",能够匹配"gooogle","goooogle"等;?
表示前面的字符最多出现一次(0次或1次),例如,"colou?r",能够匹配"color"或者"colour";*
星号表明前面的字符能够不出现,也能够出现一次或者屡次(0次、或1次、或屡次),例如,“0*42”能够匹配4二、04二、004二、00042等。()
圆括号能够用来定义模式字符串的范围和优先级,这能够简单的理解为是否将括号内的模式串做为一个总体。例如,"gr(a|e)y"等价于"gray|grey",(这里体现了优先级,竖直分隔符用于选择a或者e而不是gra和ey),"(grand)?father"匹配father和grandfather(这里体验了范围,?
将圆括号内容做为一个总体匹配)。
正则表达式有多种不一样的风格,下面列举一些经常使用的做为 PCRE 子集的适用于perl
和python
编程语言及grep
或egrep
的正则表达式匹配规则:(因为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} |
限定符 |
^、$、\任何元字符 |
定位点和序列 |
| |
选择 |
更多正则表达式的内容能够参考如下连接:
regex的思导图:
上面空谈了那么多正则表达式的内容也并无说起具体该如何使用它,实在枯燥,若是说正则表达式是一门武功话,那它也只能算得上一些口诀招式罢了,要把它真正练起来还得须要一些兵器在手才行,这里咱们要介绍的grep
命令以及后面要讲的sed
,awk
这些就该算做是这样的兵器了。
grep
命令用于打印输出文本中匹配的模式串,它使用正则表达式做为模式匹配的条件。grep
支持三种正则表达式引擎,分别用三个参数指定:
参数 |
说明 |
|
POSIX扩展正则表达式,ERE |
|
POSIX基本正则表达式,BRE |
|
Perl正则表达式,PCRE |
不过在你没学过perl语言的大多数状况下你将只会使用到ERE
和BRE
,因此咱们接下来的内容都不会讨论到PCRE中特有的一些正则表达式语法(它们之间大部份内容是存在交集的,因此你不用担忧会遗漏多少重要内容)
在经过grep
命令使用正则表达式以前,先介绍一下它的经常使用参数:
参数 |
说明 |
|
将二进制文件做为文原本进行匹配 |
|
统计以模式匹配的数目 |
|
忽略大小写 |
|
显示匹配文本所在行的行号 |
|
反选,输出不匹配行的内容 |
|
递归匹配查找 |
|
n为正整数,表示after的意思,除了列出匹配行以外,还列出后面的n行 |
|
n为正整数,表示before的意思,除了列出匹配行以外,还列出前面的n行 |
|
将输出中的匹配项设置为自动颜色显示 |
注:在大多数发行版中是默认设置了grep的颜色的,你能够经过参数指定或修改GREP_COLOR
环境变量。
查找/etc/group
文件中以"shiyanlou"为开头的行
'shiyanlou'group$ grep/etc/
'^shiyanlou'group$ grep/etc/
# 将匹配以'z'开头以'o'结尾的全部字符串
echo'zero\nzo\nzoo''z.*o'$| grep
# 将匹配以'z'开头以'o'结尾,中间包含一个任意字符的字符串
echo'zero\nzo\nzoo''z.o'$| grep
# 将匹配以'z'开头,以任意多个'o'结尾的字符串
echo'zero\nzo\nzoo''zo*'$| grep
注意:其中\n
为换行符
# grep默认是区分大小写的,这里将匹配全部的小写字母
echo'1234\nabcd''[a-z]'$| grep
# 将匹配全部的数字
echo'1234\nabcd''[0-9]'$| grep
# 将匹配全部的数字
echo'1234\nabcd''[[:digit:]]'$| grep
# 将匹配全部的小写字母
echo'1234\nabcd''[[:lower:]]'$| grep
# 将匹配全部的大写字母
echo'1234\nabcd''[[:upper:]]'$| grep
# 将匹配全部的字母和数字,包括0-9,a-z,A-Z
echo'1234\nabcd''[[:alnum:]]'$| grep
# 将匹配全部的字母
echo'1234\nabcd''[[:alpha:]]'$| grep
下面包含完整的特殊符号及说明:
特殊符号 |
说明 |
|
表明英文大小写字节及数字,亦即 0-9, A-Z, a-z |
|
表明任何英文大小写字节,亦即 A-Z, a-z |
|
表明空白键与 [Tab] 按键二者 |
|
表明键盘上面的控制按键,亦即包括 CR, LF, Tab, Del.. 等等 |
|
表明数字而已,亦即 0-9 |
|
除了空白字节 (空白键与 [Tab] 按键) 外的其余全部按键 |
|
表明小写字节,亦即 a-z |
|
表明任何能够被列印出来的字节 |
|
表明标点符号 (punctuation symbol),亦即:" ' ? ! ; : # $... |
|
表明大写字节,亦即 A-Z |
|
任何会产生空白的字节,包括空白键, [Tab], CR 等等 |
|
表明 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''[^o]'$| grep
注意:当^
放到中括号内为排除字符,不然表示行首。
要经过grep
使用扩展正则表达式须要加上-E
参数,或使用egrep
。
# 只匹配"zo"
echo'zero\nzo\nzoo''zo{1}'$| grep -E
# 匹配以"zo"开头的全部单词
echo'zero\nzo\nzoo''zo{1,}'$| grep -E
注意:推荐掌握{n,m}
便可,+
,?
,*
,这几个不太直观,且容易弄混淆。
# 匹配"www.shiyanlou.com"和"www.google.com"
echo'www.shiyanlou.com\nwww.baidu.com\nwww.google.com''www\.(shiyanlou|google)\.com'$| grep -E
# 或者匹配不包含"baidu"的内容
echo'www.shiyanlou.com\nwww.baidu.com\nwww.google.com''www\.baidu\.com'$| grep -Ev
注意:由于.
号有特殊含义,因此须要转义。
关于正则表达式和grep
命令的内容就介绍这么多,下面会介绍两个更强大的工具sed
和awk
,但一样也正是由于这两个工具的强大,咱们的内容没法包含它们的所有,这里将只对基本内容做介绍。
sed
工具在 man 手册里面的全名为"sed - stream editor for filtering and transforming text ",意即,用于过滤和转换文本的流编辑器。
在 Linux/UNIX 的世界里敢称为编辑器的工具,大都非等闲之辈,好比前面的"vi/vim(编辑器之神)","emacs(神的编辑器)","gedit"这些个编辑器。sed
与上述的最大不一样之处大于它是一个非交互式的编辑器,下面咱们就开始介绍sed
这个编辑器。
sed 命令基本格式:
sed [参数]... [执行命令] [输入文件]...
# 形如:
'1s/sad/happy/'test# 表示将test文件中第一行的"sad"替换为"happy"$ sed -i
参数 |
说明 |
|
安静模式,只打印受影响的行,默认打印输入数据的所有内容 |
|
用于在脚本中添加多个执行命令一次执行,在命令行中执行多个命令一般不须要加该参数 |
|
指定执行filename文件中的命令 |
|
使用扩展正则表达式,默认为标准正则表达式 |
|
将直接修改输入文件内容,而不是打印到标准输出设备 |
sed执行命令格式:
n1,n2[][]command
n1~step[][]command
# 其中一些命令能够在后面加上做用范围,形如:
$ sed -i 's/sad/happy/g' test # g表示全局范围
$ sed -i 's/sad/happy/4' test # 4表示指定行中的第四个匹配字符串
其中n1,n2表示输入内容的行号,它们之间为,
逗号则表示从n1到n2行,若是为~
波浪号则表示从n1开始以step为步进的全部行;command为执行动做,下面为一些经常使用动做指令:
命令 |
说明 |
|
行内替换 |
|
整行替换 |
|
插入到指定行的后面 |
|
插入到指定行的前面 |
|
打印指定行,一般与 |
|
删除指定行 |
咱们先找一个用于练习的文本文件:
$ cp /etc/passwd ~
# 打印2-5行
'2,5p'$ nl passwd | sed -n
# 打印奇数行
'1~2p'$ nl passwd | sed -n
# 将输入文本中"shiyanlou" 全局替换为"hehe",并只打印替换的那一行,注意这里不能省略最后的"p"命令
's/shiyanlou/hehe/gp'$ sed -npasswd
注意: 行内替换能够结合正则表达式使用。
grep"shiyanlou"$ nl passwd |
# 删除第21行
'21c\www.shiyanlou.com'$ sed -npasswd
关于sed命令就介绍这么多,你若是但愿了解更多sed的高级用法,你能够参看以下连接:
看到上面的标题,你可能会感到惊异,难道咱们这里要学习的是一门“语言”么,确切的说,咱们是要在这里学习awk
文本处理语言,只是咱们并不会在这里学习到比较完整的关于awk
的内容,仍是由于前面的缘由,它太强大了,它的应用无处不在,咱们没法在这里以简短的文字描述面面俱到,若是你有目标成为一个linux系统管理员,确实想学好awk
,你一不用担忧,实验楼会在以后陆续上线linux系统管理员的学习路径,里面会有单独的关于正则表达式
,awk
,sed
等相关课程,敬请期待吧。下面的内容,咱们就做为一个关于awk
的入门体验章节吧,其中会介绍一些awk
的经常使用操做。
AWK
是一种优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一.其名称得自于它的创始人Alfred Aho(阿尔佛雷德·艾侯)、Peter Jay Weinberger(彼得·温伯格)和Brian Wilson Kernighan(布莱恩·柯林汉)姓氏的首个字母.AWK程序设计语言,三位建立者已将它正式定义为“样式扫描和处理语言”。它容许您建立简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其余的功能。最简单地说,AWK是一种用于处理文本的编程语言工具。
在大多数linux发行版上面,实际咱们使用的是gawk(GNU awk,awk的GNU版本),在咱们的环境中ubuntu上,默认提供的是mawk,不过咱们一般能够直接使用awk命令(awk语言的解释器),由于系统已经为咱们建立好了awk指向mawk的符号连接。
$ ll /usr/bin/awk
nawk: 在 20 世纪 80 年代中期,对 awk语言进行了更新,并不一样程度地使用一种称为 nawk(new awk) 的加强版本对其进行了替换。许多系统中仍然存在着旧的awk 解释器,但一般将其安装为 oawk (old awk) 命令,而 nawk 解释器则安装为主要的 awk 命令,也能够使用 nawk 命令。Dr. Kernighan 仍然在对 nawk 进行维护,与 gawk 同样,它也是开放源代码的,而且能够免费得到; gawk: 是 GNU Project 的awk解释器的开放源代码实现。尽管早期的 GAWK 发行版是旧的 AWK 的替代程序,但不断地对其进行了更新,以包含 NAWK 的特性; mawk 也是awk编程语言的一种解释器,mawk遵循 POSIX 1003.2 (草案 11.3)定义的 AWK 语言,包含了一些没有在AWK 手册中提到的特点,同时 mawk 提供一小部分扩展,另外听说mawk是实现最快的awk
awk全部的操做都是基于pattern(模式)—action(动做)对来完成的,以下面的形式:
$ pattern {action}
你能够看到就如同不少编程语言同样,它将全部的动做操做用一对{}
花括号包围起来。其中pattern一般是是表示用于匹配输入的文本的“关系式”或“正则表达式”,action则是表示匹配后将执行的动做。在一个完整awk操做中,这二者能够只有其中一个,若是没有pattern则默认匹配输入的所有文本,若是没有action则默认为打印匹配内容到屏幕。
awk
处理文本的方式,是将文本分割成一些“字段”,而后再对这些字段进行处理,默认状况下,awk以空格做为一个字段的分割符,不过这不是固定了,你能够任意指定分隔符,下面将告诉你如何作到这一点。
awk[-F fs][-v var=value][-f prog-file | 'program text'][file...]
其中-F
参数用于预先指定前面提到的字段分隔符(还有其余指定字段的方式) ,-v
用于预先为awk
程序指定变量,-f
参数用于指定awk
命令要执行的程序文件,或者在不加-f
参数的状况下直接将程序语句放在这里,最后为awk
须要处理的文本输入,且能够同时输入多个文本文件。如今咱们仍是直接来具体体验一下吧。
先用vim新建一个文本文档
test$ vim
包含以下内容:
Ilikelinux
www.shiyanlou.com
# "quote>" 不用输入
'{$ awk
> }'test
# 或者写到一行
'{print}'test$ awk
说明:在这个操做中我是省略了patter
,因此awk
会默认匹配输入文本的所有内容,而后在"{}"花括号中执行动做,即print
打印全部匹配项,这里是所有文本内容
'{$ awk
> if(NR==1){
> print $1 "\n" $2 "\n" $3
> } else {
> print}
> }'test
# 或者
'{$ awk
> if(NR==1){
> OFS="\n"
> print $1, $2, $3
> } else {
> print}
> }'test
说明:你首先应该注意的是,这里我使用了awk
语言的分支选择语句if
,它的使用和不少高级语言如C/C++
语言基本一致,若是你有这些语言的基础,这里将很好理解。另外一个你须要注意的是NR
与OFS
,这两个是awk
内建的变量,NR
表示当前读入的记录数,你能够简单的理解为当前处理的行数,OFS
表示输出时的字段分隔符,默认为" "空格,如上图所见,咱们将字段分隔符设置为\n
换行符,因此第一行本来以空格为字段分隔的内容就分别输出到单独一行了。而后是$N
其中N为相应的字段号,这也是awk
的内建变量,它表示引用相应的字段,由于咱们这里第一行只有三个字段,因此只引用到了$3
。除此以外另外一个这里没有出现的$0
,它表示引用当前记录(当前行)的所有内容。
'.''{$ awk -F
> if(NR==2){
> print $1 "\t" $2 "\t" $3
> }}'test
# 或者
'$ awk
> BEGIN{
> FS="."
> OFS="\t" # 若是写为一行,两个动做语句之间应该以";"号分开
> }{
> if(NR==2){
> print $1, $2, $3
> }}'test
说明:这里的-F
参数,前面已经介绍过,它是用来预先指定待处理记录的字段分隔符。咱们须要注意的是除了指定OFS
咱们还能够在print
语句中直接打印特殊符号如这里的\t
,print打印的非变量内容都须要用""一对引号包围起来。上面另外一个版本,展现了实现预先指定变量分隔符的另外一种方式,即便用BEGIN
,就这个表达式指示了,其后的动做将在全部动做以前执行,这里是FS
赋值了新的"."点号代替默认的" "空格
注意:首先说明一点,咱们在学习和使用awk的时候应该尽量将其做为一门程序语言来理解,这样将会使你学习起来更容易,因此初学阶段在练习awk
时应该尽可能按照我那样的方式分多行按照通常程序语言的换行和缩进来输入,而不是所有写到一行(固然这在你熟练了以后是没有任何问题的)。
变量名 |
说明 |
|
当前输入文件名,如有多个文件,则只表示第一个。若是输入是来自标准输入,则为空字符串 |
|
当前记录的内容 |
|
N表示字段号,最大值为 |
|
字段分隔符,由正则表达式表示,默认为" "空格 |
|
输入记录分隔符,默认为"\n",即一行为一个记录 |
|
当前记录字段数 |
|
已经读入的记录数 |
|
当前输入文件的记录数,请注意它与NR的区别 |
|
输出字段分隔符,默认为" "空格 |
|
输出记录分隔符,默认为"\n" |
关于awk
的内容本课程将只会包含这些内容,若是你想了解更多,请期待后续课程,或者参看一下连接内容:
一、练习其余几个命令动做的使用。
二、一个在线游戏,固然咱们主要目的是学习,这个游戏也是有寓教于乐的性质,让你快速学会vim的基础操做:
介绍 Ubuntu 下软件安装的几种方式,及 apt,dpkg 工具的使用。
一般 Linux 上的软件安装主要有三种方式:
这几种安装方式各有优劣,而大多数软件包会采用多种方式发布软件,因此咱们经常须要所有掌握这几种软件安装方式,以便适应各类环境。下面将介绍前三种安装方式,从源码编译安装你将在 Linux 程序设计中学习到。
试想一下,平时咱们在使用 Windows 的时候,想要安装一个软件,咱们须要在网上去下载对应软件的安装包,接着安装的时候就是不断的去点击下一步,这些流程想必你们已经经历的无数回了,可是在 Linux 下,一个命令加回车,等待一下,软件就安装好了,这就是方便的在线安装软件的方式。在学习这种安装方式以前有一点须要说明的是,在不一样的linux发行版上面在线安装方式会有一些差别包括使用的命令及它们的包管理工具,由于咱们的开发环境是基于ubuntu的,因此这里咱们涉及的在线安装方式将只适用于ubuntu发行版,或其它基于ubuntu的发行版如国内的ubuntukylin(优麒麟),ubuntu又是基于debian的发行版,它使用的是debian的包管理工具dpkg,因此一些操做也适用与debian。而在其它一些采用其它包管理工具的发行版如redhat,centos,fedora等将不适用(redhat和centos使用rpm)。
好比咱们想安装一个软件,名字叫作 w3m
(w3m是一个命令行的简易网页浏览器),那么输入以下命令:
get$ sudo apt-install w3m
这样的操做你应该在前面的章节中看到过不少次了,它就表示将会安装一个软件包名为w3m
的软件
咱们来看看命令执行后的效果:
$ w3m www.shiyanlou.com/faq
注意:若是你在安装一个软件以后,没法当即使用Tab
键补全这可命令,你能够尝试先执行source ~/.zshrc
,而后你就能够使用补全操做。
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
能正常的工做。
apt-get
使用各用于处理apt
包的公用程序集,咱们能够用它来在线安装、卸载和升级软件包等,下面列出一些apt-get
包含的经常使用的一些工具:
工具 |
说明 |
|
其后加上软件包名,用于安装一个软件包 |
|
从软件源镜像服务器上下载/更新用于更新本地软件源的软件包列表 |
|
升级本地可更新的所有软件包,但存在依赖问题时将不会升级,一般会在更新以前执行一次 |
|
解决依赖关系并升级(存在必定危险性) |
|
移除已安装的软件包,包括与被移除软件包有依赖关系的软件包,但不包含软件包的配置文件 |
|
移除以前被其余软件包依赖,但如今再也不被使用的软件包 |
|
与remove相同,但会彻底移除软件包,包含其配置文件 |
|
移除下载到本地的已经安装的软件包,默认保存在/var/cache/apt/archives/ |
|
移除已安装的软件的旧版本软件包 |
下面是一些apt-get
经常使用的参数:
参数 |
说明 |
|
自动回应是否安装软件包的选项,在一些自动化安装脚本中使用这个参数将十分有用 |
|
模拟安装 |
|
静默安装方式,指定多个 |
|
修复损坏的依赖关系 |
|
只下载不安装 |
|
从新安装已经安装但可能存在问题的软件包 |
|
同时安装APT给出的建议安装的软件包 |
关于安装,如前面演示的同样你只须要执行apt-get install <
软件包名
>
便可,除了这一点,你还应该掌握的是如何从新安装软件包。 不少时候咱们须要从新安装一个软件包,好比你的系统被破坏,或者一些错误的配置致使软件没法正常工做。
你能够使用以下方式从新安装:
get$ sudo apt---reinstall install w3m
另外一个你须要掌握的是,如何在不知道软件包完整名的时候进行安装。一般咱们是使用Tab
键补全软件包名,后面会介绍更好的方法来搜索软件包。有时候你须要同时安装多个软件包,你还能够使用正则表达式匹配软件包名进行批量安装。
# 更新软件源
get$ sudo apt-update
# 升级没有依赖问题的软件包
get$ sudo apt-upgrade
# 升级并解决依赖关系
get$ sudo apt-dist-upgrade
若是你如今以为 w3m
这个软件不合本身的胃口,或者是找到了更好的,你须要卸载它,那么简单!一样是一个命令加回车 sudo apt-get remove w3m
,系统会有一个确认的操做,以后这个软件便“滚蛋了”。
或者,你能够执行
# 不保留配置文件的移除
get$ sudo apt-purge w3m
# 或者 sudo apt-get --purge remove
# 移除再也不须要的被依赖的软件包
get$ sudo apt-autoremove
当本身刚知道了一个软件,想下载使用,须要确认软件仓库里面有没有,就须要用到搜索功能了,命令以下:
cachesearchsudo apt-softname1 softname2 softname3……
apt-cache
命令则是针对本地数据进行相关操做的工具,search
顾名思义在本地的数据库中寻找有关 softname1
softname2
…… 相关软件的信息。如今咱们试试搜索一下以前咱们安装的软件 w3m
,如图:
结果显示了4个 w3m
相关的软件,而且有相关软件的简介。
关于在线安装的的内容咱们就介绍这么多,想了解更多关于APT的内容,你能够参考:
dpkg 是 Debian 软件包管理器的基础,它被伊恩·默多克建立于 1993 年。dpkg 与 RPM 十分类似,一样被用于安装、卸载和供给和 .deb 软件包相关的信息。
dpkg 自己是一个底层的工具。上层的工具,像是 APT,被用于从远程获取软件包以及处理复杂的软件包关系。"dpkg"是"Debian Package"的简写。
咱们常常能够在网络上简单以deb
形式打包的软件包,就须要使用dpkg
命令来安装。
dpkg
经常使用参数介绍:
参数 |
说明 |
|
安装指定deb包 |
|
后面加上目录名,用于安装该目录下的全部deb安装包 |
|
remove,移除某个已安装的软件包 |
|
显示 |
|
显示已安装软件的信息 |
|
搜索已安装的软件包 |
|
显示已安装软件包的目录信息 |
咱们先使用apt-get
加上-d
参数只下载不安装,下载emacs编辑器的deb包,下载完成后,咱们能够查看/var/cache/apt/archives/目录下的内容,以下图:
而后咱们将第一个deb
拷贝到home目录下,并使用dpkg
安装
314$ cp /var/cache/apt/archives/emacs24_24.+-ubuntu1_amd64.deb ~
# 安装以前参看deb包的信息
314$ sudo dpkg -I emacs24_24.+-ubuntu1_amd64.deb
如你所见,这个包还额外依赖了一些软件包,这意味着,若是主机目前没有这些被依赖的软件包,直接使用dpkg安装可能会存在一些问题,由于dpkg
并不能为你解决依赖关系。
# 使用dpkg安装
314$ sudo dpkg -i emacs24_24.+-ubuntu1_amd64.deb
跟前面预料的同样,这里你可能出现了一些错误:
咱们将如何解决这个错误了,这就要用到apt-get
了,使用它的-f
参数了,修复依赖关系的安装
-f$ sudo apt-getinstall
没有任何错误,这样咱们就安装成功了,而后你能够运行emacs程序
若是你依然在纠结到底linux将软件安装到了什么地方,那么很幸运你将能够经过dpkg
找到答案
使用dpkg -L
查看deb
包目录信息
$ sudo dpkg -L emacs
dpkg
还有一些其余的参数,这里将做为练习题由你本身来学习
二进制包的安装比较简单,咱们须要作的只是将从网络上下载的二进制包解压后放到合适的目录,而后将包含可执行的主程序文件的目录添加进PATH
环境变量便可,若是你不知道该放到什么位置,请从新复习第四节关于 Linux 目录结构的内容。
这一节是本课程的最后一节,因此这里咱们给你们介绍一个颇有趣的命令。
安装:
get$ sudo apt-install bb
Linux中也不免遇到某个程序无响应的状况,咱们经过一些命令来帮助咱们让系统可以更流畅的运行,而在此以前咱们须要对进程的基础知识有必定的了解,才能更好更有效率的使用Linux提供的工具
首先程序与进程是什么?程序与进程又有什么区别?
程序(procedure)不太精确地说,程序就是执行一系列有逻辑,有顺序结构的指令,为咱们提供所须要的服务。就如咱们去餐馆,给服务员说我要牛肉盖浇饭,她执行了作牛肉盖浇饭这么一个程序,最后咱们获得了这么一盘牛肉盖浇饭。它须要去执行,否则它就像一本武功秘籍,放在那里。
进程(process)进程是程序在一个数据集合上的一次执行过程,在早期的UNIX,Linux 2.4及更早的版本中,它是系统进行资源分配和调度的独立基本单位。同上一个例子,就如咱们去了餐馆,给服务员说我要牛肉盖浇饭,她执行了作牛肉盖浇饭这么一个程序,而里面作饭的是一个进程,超牛肉汤汁的是一个进程,把牛肉汤汁与饭混合在一块儿的是一个进程,把饭端上桌的是一个进程。它就像是咱们在看武功秘籍这么一个过程,而后一个篇章一个篇章的去练
简单来讲,程序是为了完成某种任务而设计的软件,好比vim是程序。什么是进程呢?进程就是运行中的程序。
程序只是一些列指令的集合,是一个静止的实体,而进程不一样,进程有一下的特性
并发在一个时间段内,宏观来看有多个程序都在活动,有条不紊的执行
并行在每个瞬间,都有多个程序都在同时执行,这个必须有多个 CPU 才行
引入进程是由于传统意义上的程序已经不足以描述 OS 中各类活动之间的动态性、并发行、独立性还有相互制约性。就好比程序就像一个公司,只是一些证书,文件的堆积(静态实体)。而当公司运做起来就有各个部门的区分,财务部,技术部,销售部等等,就像各个进程,各个部门之间能够独立运作,也能够有交互(独立性、并发性)
而随着程序的发展越作越大,又会继续细分,从而引入了线程的概念,当代多数操做系统、Linux 2.6及更新的版本中,进程自己不是基本运行单位,而是线程的容器。就像上述所说的,每一个部门又会细分为各个工做小组(线程),而工做小组须要的资源须要向上级(进程)申请。
线程(thread)是操做系统可以进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运做单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中能够并发多个线程,每条线程并行执行不一样的任务。由于线程中几乎不包含系统资源,因此执行更快、更有效率
简而言之,一个程序至少有一个进程,一个进程至少有一个线程。线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执行过程当中拥有独立的内存单元,而多个线程共享内存,从而极大地提升了程序的运行效率。就以下图所示:
大概明白进程是个什么样的存在,进一步对于进程的一个了解就是进程分类,咱们能够从两个角度来分,第一个角度以进程的功能与服务的对象来分;第二个角度以应用程序的服务类型来分
第一个角度来看,咱们能够分为用户进程与系统进程
第二角度来看,咱们能够将进程分为交互进程、批处理进程、守护进程
进程有这么多的种类,那么进程之间定是有相关性的,而这些有关联性的进程又是如何产生的,如何衍生的?
就好比咱们启动了终端,就是启动了一个 bash 进程,咱们能够在 bash 中再输入 bash 则会再启动一个 bash 的进程,此时第二个 bash 进程就是由第一个 bash 进程建立出来的,他们直接又是个什么关系?
咱们通常称呼第一个 bash 进程是第二 bash 进程的父进程,第二 bash 进程是第一个 bash 进程的子进程,这层关系是如何得来的呢?
关于父进程与子进程便会说起这两个系统调用 fork()
与 exec()
fork-exec是由 Dennis M. Ritchie 创造的
fork() 是一个系统调用(system call),它的主要做用就是为当前的进程建立一个新的进程,这个新的进程就是它的子进程,这个子进程除了父进程的返回值和 PID 之外其余的都如出一辙,如进程的执行代码段,内存信息,文件描述,寄存器状态等等
exec() 也是系统调用,做用是切换子进程中的执行程序也就是替换其从父进程复制过来的代码段与数据段
下图能够很形象的表示他们的做用(此图来源于鸟哥私房菜):
子进程就是父进程经过系统调用 fork()
而产生的复制品,fork()
就是把父进程的 PCB 等进程的数据结构信息直接复制过来,只是修改了 PID,因此如出一辙,指挥在执行 exec()
以后才会不一样,而早先的 fork()
比较消耗资源后来进化成 vfork()
,效率高了很多,感兴趣的同窗能够查查为何?
这就是子进程产生的由来。简单的逻辑就以下方所示【注释1】
pid_tp;
p = fork();
ifpid_t-1(p == ())
/* ERROR */
elseif0(p ==)
/* CHILD */
else
/* PARENT */
既然子进程是经过父进程而衍生出来的,那么子进程的退出与资源的回收定然与父进程有很大的相关性。当一个子进程要正常的终止运行时,或者该进程结束时它的主函数 main()
会执行 exit(n);
或者 return n
,这里的返回值 n 是一个信号,系统会把这个 SIGCHLD 信号传给其父进程,固然如果异常终止也每每是由于这个信号。
而这个时候的子进程代码执行部分其实已经结束执行了,系统的资源也进本归还给系统了,可是其进程的进程控制块(PCB)仍驻留在内存中,而它的 PCB 还在,表明这个进程还存在(由于 PCB 就是进程存在的惟一标志,里面有 PID 等消息),并无消亡,这样的进程称之为僵尸进程(Zombie)
如图中第三行第四列标题是 S,此处的 S 是进程的状态的意思,而在下属的第三行是 Z,而此处的 Z 即是 Zombie 的意思。( ps 命令将在后续详解)
正常状况下,父进程会收到两个返回值一个是 exit code 也是 SIGCHLD 信号与 reason for termination 以后,父进程会使用 wait(&status)
系统调用以获取子进程的退出状态,而后内核就能够从内存中释放已结束的子进程的 PCB;而如若父进程没有这么作的话,子进程的 PCB 就会一直驻留在内存中,一直留在系统中作为僵尸进程(Zombie)。
虽然僵尸进程是已经放弃了几乎全部内存空间,没有任何可执行代码,也不能被调度,在进程列表中保留一个位置,记载该进程的退出状态等信息供其父进程收集,从而释放它。可是 Linux 系统中能使用的 PID 是有限的,若是系统中存在有大量的僵尸进程,系统将会由于没有可用的 PID 从而致使不能产生新的进程。
而另外若是父进程结束(非正常的结束),未能即便收回子进程,子进程仍在运行,这样的子进程称之为孤儿进程。在 Linux 系统中,孤儿进程通常会被 init 进程所“收养”,成为 init 的子进程。由 init 来作善后处理,因此它并不至于像僵尸进程那样无人问津,无论不顾,大量存在会有危害。
进程 0 是系统引导时建立的一个特殊进程,也称之为内核初始化,其最后一个动做就是调用 fork()
建立出一个子进程运行/sbin/init
可执行文件,而该进程就是 PID=1 的进程1,也就是 init 进程,而进程 0 就转为交换进程(也被称为空闲进程),而进程 1 (init 进程)是第一个普通用户态的进程,再由它不断调用 fork() 来建立系统里其余的进程,因此它是全部进程的父进程或者祖先进程。同时它是一个守护程序,直到计算机关机才会中止。
经过一下的命令咱们能够很明显的看到这样的一个结构
pstree
或者今后图咱们能够更加形象的看清子父进程的关系
经过以上的显示结果咱们能够看的很清楚,init 为全部进程的父进程或者说是祖先进程
咱们还能够使用这样一个命令来看,其中 pid 就是该进程的一个惟一编号,ppid 就是该进程的父进程的 pid,command 就是该进程是执行什么样的程序或者脚本而产生的
commandps-fxo user,ppid,pid,pgid,
能够在图中看见咱们执行的 ps 就是由 zsh 经过 fork-exec 建立的子进程而执行的
使用这样的一个命令咱们也能清楚的看见 init 如上文所说是由进程0这个初始化进程来建立而出的子进程,而其余的进程基本是由 init 建立的子进程,或者是由它的子进程建立出来的子进程。因此 init 是用户进程的第一个进程也是全部用户进程的父进程或者祖先进程。(ps 命令将在后续课程详解)
就像一个树状图,而 init 进程就是这棵树的根,其余进程由根不断的发散,开枝散叶
每个进程都会是一个进程组的成员,并且这个进程组是惟一存在的,他们是依靠 PGID(process group ID)来区别的,而每当一个进程被建立的时候,它便会成为其父进程所在组中的一员。
通常状况,进程组的 PGID 等同于进程组的第一个成员的 PID,而且这样的进程称为该进程组的领导者,也就是领导进程,进程通常经过使用 getpgrp()
系统调用来寻找其所在组的 PGID,领导进程能够先终结,此时进程组依然存在,并持有相同的PGID,直到进程组中最后一个进程终结。
与进程组相似,每当一个进程被建立的时候,它便会成为其父进程所在 Session 中的一员,每个进程组都会在一个 Session 中,而且这个 Session 是惟一存在的,
Session 主要是针对一个 tty 创建,Session 中的每一个进程都称为一个工做(job)。每一个会话能够链接一个终端(control terminal)。当控制终端有输入输出时,都传递给该会话的前台进程组。Session 意义在于将多个jobs囊括在一个终端,并取其中的一个 job 做为前台,来直接接收该终端的输入输出以及终端信号。 其余jobs在后台运行。
前台(foreground)就是在终端中运行,与你能有交互的
后台(background)就是在终端中运行,可是你并不能与其任何的交互,也不会显示其执行的过程
bash(Bourne-Again shell)支持工做控制(job control),而sh(Bourne shell)并不支持。
而且每一个终端或者说 bash 只能管理当前终端的中的 job,不能管理其余终端中的 job。好比我当前存在两个 bash 分别为 bash一、bash2,bash1 只能管理其本身里面的 job 并不能管理 bash2 里面的 job
咱们都知道当一个进程在前台运做时咱们能够用 ctrl + c
来终止它,可是如果在后台的话就不行了,而且在一个终端 bash 中只能管理当前 bash 里的 job.
咱们能够经过 &
这个符号,让咱们的命令在后台中运行
ls&
图中所显示的 [1] 236
分别是该工做的 job number 与该进程的 PID,而最后一行的 Done 表示该命令已经在后台执行完毕。
咱们还能够经过 ctrl + z
使咱们的当前工做中止并丢到后台中去
被中止并放置在后台的工做咱们能够使用这个命令来查看
jobs
其中第一列显示的为被放置后台的工做的编号,而第二列的 + 表示最近被放置后台的工做,同时也表示预设的工做,也就是如果有什么针对后台的工做的操做,首先对预设的工做,- 表示倒数第二被放置后台的工做,倒数第三个之后都不会有这样的符号修饰,第三列表示它们的状态,而最后一列表示该进程执行的命令
咱们能够经过这样的一个命令将后台的工做拿到前台来
#后面不加参数提取预设工做,加参数提取指定工做的编号
fg [%jobnumber]
以前咱们经过 ctrl + z
使得工做中止放置在后台,如果咱们想让其在后台运做咱们就使用这样一个命令
#与fg相似,加参则指定,不加参则取预设
bg [%jobnumber]
既然有方法将被放置在后台的工做提至前台或者让它从中止到继续运行在后台,固然也有方法删除一个工做,或者重启等等
#kill的使用格式以下
kill-signal %jobnumber
#signal从1-64个信号值能够选择,能够这样查看
#在 bash 中能够看到更全面的信息,进入的方法就是输入 bash
kill-l
其中经常使用的有这些信号值
信号值 |
做用 |
-1 |
从新读取参数运行,相似与restart |
-2 |
如同 ctrl+c 的操做退出 |
-9 |
强制终止该任务 |
-15 |
正常的方式终止该任务 |
注意
如果在使用kill+信号值而后直接加数字的话,这个数字表明的是 pid,你将会对 pid 对应的进程作操做
如果在使用kill+信号值而后%jobnumber,这时所操做的对象才是 job,这个数字就是就当前 bash 中后台的运行的 job 的 ID
经过本实验咱们初步的了解进程在系统中存在的概念,以及进程的如何在系统中衍生,发展,以及进程之间存在的相互关系,能够为咱们在后续学习进程管理打下基础,同时了解了工做与进程,以及工做管理的一些使用性的操做。
<span id="jump"> 注释1:此处参考来自于https://www.win.tue.nl/~aeb/linux/lk/lk-10.html </span>
经过本实验咱们将掌握一些 Linux 所提供的工具来进行进程的查看与控制,掌握这些工具让咱们能在某些进程出异常的时候咱们能及时的解决与查看
无论在测试的时候仍是在实际的生产环境中或者本身的使用过程当中,不免遇到进程的一些异常,因此 Linux 为咱们提供了一些工具能够查看进程的一些状态信息,咱们能够经过 top 动态实时的查看进程的状态的已经系统的一些信息如 CPU、内存信息等等,咱们一样能够经过 ps 来静态查看当前的进程信息,同时咱们还能够使用 pstree 来查看当前活跃进程的树形结构
top 工具是咱们经常使用的一个查看工具,他能实时的查看咱们系统的关键一些关键信息的变化已经进程在进程中的实时变化
top
top 是一个在前台执行的程序,因此执行知道便在这样的一个交互界面,咱们能够经过一些指令来作一些操做,筛选。首先咱们先来了解一些显示了哪些信息
咱们看到 top 显示的第一排,
内容 |
解释 |
top |
表示当前程序的名称 |
11:05:18 |
表示当前的系统的时间 |
up 8 days,17:12 |
表示该机器已经启动了多长时间 |
1 user |
表示当前系统中只有一个用户 |
load average: 0.29,0.20,0.25 |
分别对应一、五、15分钟内cpu的平均负载 |
load average 在 wikipedia 中的解释是 the system load is a measure of the amount of work that a computer system is doing 也就是对当前 CPU 工做量的度量,具体来讲也就是指运行队列的平均长度,也就是等待CPU的平均进程数相关的一个计算值。
咱们该如何看待这个load average 数据呢?
假设咱们的系统是单CPU单内核的,把它比喻成是一条单向的桥,把CPU任务比做汽车。
这是单个 CPU 单核的状况,而实际生活中咱们须要将获得的这个值除以咱们的核数来看。咱们能够经过一下的命令来查看 CPU 的个数与核心数
#查看物理CPU的个数
#cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l
#每一个cpu的核心数
grep"physical id"grep"0"cat /proc/cpuinfo |||wc -l
经过上面的指数咱们能够得知 load 的临界值为 1 ,可是在实际生活中,比较有经验的运维或者系统管理员会将临界值定为0.7。这里的指数都是除以核心数之后的值,不要混淆了
一般咱们都会先看 15 分钟的值来看这个大致的趋势,而后再看 5 分钟的值对比来看是否有降低的趋势。
查看 busybox 的代码能够知道,数据是每 5 秒钟就检查一次活跃的进程数,而后计算出该值,而后 load 从/proc/loadavg 中读取的。而这个 load 的值是如何计算的呢,这是 load 的计算的源码
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point(定点) */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals,每隔5秒计算一次平均负载值 */
#define CALC_LOAD(load, exp, n) \
load *= exp; \
load += n*(FIXED_1 - exp); \
load >>= FSHIFT;
unsignedlong3avenrun[];
EXPORT_SYMBOL(avenrun);
/*
* calc_load - given tick count, update the avenrun load estimates.
* This is called while holding a write_lock on xtime_lock.
*/
staticinlinevoidunsignedlongcalc_load(ticks)
{
unsignedlong/* fixed-point */ active_tasks;
staticint count = LOAD_FREQ;
count -= ticks;
if0 (count <) {
count += LOAD_FREQ;
active_tasks = count_active_tasks();
CALC_LOAD0 (avenrun[], EXP_1, active_tasks);
CALC_LOAD1 (avenrun[], EXP_5, active_tasks);
CALC_LOAD2 (avenrun[], EXP_15, active_tasks);
}
}
有兴趣的朋友能够研究一下,是如何计算的。代码中的后面这部分至关于它的计算公式
咱们回归正题,来看 top 的第二行数据,基本上第二行是进程的一个状况统计
内容 |
解释 |
Tasks: 26 total |
进程总数 |
1 running |
1个正在运行的进程数 |
25 sleeping |
25个睡眠的进程数 |
0 stopped |
没有中止的进程数 |
0 zombie |
没有僵尸进程数 |
来看 top 的第三行数据,这一行基本上是 CPU 的一个使用状况的统计了
内容 |
解释 |
Cpu(s): 1.0%us |
用户空间占用CPU百分比 |
1.0% sy |
内核空间占用CPU百分比 |
0.0%ni |
用户进程空间内改变过优先级的进程占用CPU百分比 |
97.9%id |
空闲CPU百分比 |
0.0%wa |
等待输入输出的CPU时间百分比 |
0.1%hi |
硬中断(Hardware IRQ)占用CPU的百分比 |
0.0%si |
软中断(Software IRQ)占用CPU的百分比 |
0.0%st |
(Steal time) 是当 hypervisor 服务另外一个虚拟处理器的时候,虚拟 CPU 等待实际 CPU 的时间的百分比 |
CPU 利用率,是对一个时间段内 CPU 使用情况的统计,经过这个指标能够看出在某一个时间段内 CPU 被占用的状况,Load Average 是 CPU 的 Load,它所包含的信息不是 CPU 的使用率情况,而是在一段时间内 CPU 正在处理以及等待 CPU 处理的进程数状况统计信息,这两个指标并不同。
来看 top 的第四行数据,这一行基本上是内存的一个使用状况的统计了
内容 |
解释 |
8176740 total |
物理内存总量 |
8032104 used |
使用的物理内存总量 |
144636 free |
空闲内存总量 |
313088 buffers |
用做内核缓存的内存量 |
注意
系统的中可用的物理内存最大值并非 free 这个单一的值,而是 free + buffers + swap 中的 cached 的和
来看 top 的第五行数据,这一行基本上是交换区的一个使用状况的统计了
内容 |
解释 |
total |
交换区总量 |
used |
使用的交换区总量 |
free |
空闲交换区总量 |
cached |
缓冲的交换区总量,内存中的内容被换出到交换区,然后又被换入到内存,但使用过的交换区还没有被覆盖 |
在下面就是进程的一个状况了
列名 |
解释 |
PID |
进程id |
USER |
该进程的所属用户 |
PR |
该进程执行的优先级priority 值 |
NI |
该进程的 nice 值 |
VIRT |
该进程任务所使用的虚拟内存的总数 |
RES |
该进程所使用的物理内存数,也称之为驻留内存数 |
SHR |
该进程共享内存的大小 |
S |
该进程进程的状态: S=sleep R=running Z=zombie |
%CPU |
该进程CPU的利用率 |
%MEM |
该进程内存的利用率 |
TIME+ |
该进程活跃的总时间 |
COMMAND |
该进程运行的名字 |
注意
NICE 值叫作静态优先级,是用户空间的一个优先级值,其取值范围是-20至19。这个值越小,表示进程”优先级”越高,而值越大“优先级”越低。nice值中的 -20 到 19,中 -20 优先级最高, 0 是默认的值,而 19 优先级最低
PR 值表示 Priority 值叫动态优先级,是进程在内核中实际的优先级值,进程优先级的取值范围是经过一个宏定义的,这个宏的名称是MAX_PRIO,它的值为140。Linux实际上实现了140个优先级范围,取值范围是从0-139,这个值越小,优先级越高。而这其中的 0 - 99 是实时的值,而 100 - 139 是给用户的。
其中 PR 中的 100 to 139 值部分有这么一个对应 PR = 20 + (-20 to +19),这里的 -20 to +19 即是nice值,因此说两个虽然都是优先级,并且有千丝万缕的关系,可是他们的值,他们的做用范围并不相同
VIRT 任务所使用的虚拟内存的总数,其中包含全部的代码,数据,共享库和被换出 swap空间的页面等所占据空间的总数
在上文咱们曾经说过 top 是一个前台程序,因此是一个能够交互的
经常使用交互命令 |
解释 |
q |
退出程序 |
I |
切换显示平均负载和启动时间的信息 |
P |
根据CPU使用百分比大小进行排序 |
M |
根据驻留内存大小进行排序 |
i |
忽略闲置和僵死的进程,这是一个开关式命令 |
k |
终止一个进程,系统提示输入 PID 及发送的信号值。通常终止进程用15信号,不能正常结束则使用9信号。安全模式下该命令被屏蔽。 |
好好的利用 top 可以颇有效的帮助咱们观察到系统的瓶颈所在,或者是系统的问题所在
ps 也是咱们最经常使用的查看进程的工具之一,咱们经过这样的一个命令来了解一下,他能给我带来哪些消息
psaux
psaxjf
咱们来整体了解下会出现哪些信息给咱们,这些信息又表明着什么
内容 |
解释 |
F |
进程的标志 為 4 表示此程序的權限為 root,若為 1 則表示此子程序僅進行複製(fork)而沒有實際執行(exec) |
USER |
进程的属主 |
PID |
进程的ID |
PPID |
其父进程的PID |
SID |
session的ID |
TPGID |
前台进程组的ID |
%CPU |
进程占用的CPU百分比 |
%MEM |
占用内存的百分比 |
NI |
进程的NICE值 |
VSZ |
进程使用虚拟内存大小 |
RSS |
驻留内存中页的大小 |
TTY |
终端ID |
S or STAT |
进程状态 |
WCHAN |
正在等待的进程资源 |
START |
启动进程的时间 |
TIME |
进程消耗CPU的时间 |
COMMAND |
命令的名称和参数 |
TPGID栏写着-1的都是没有控制终端的进程,也就是守护进程
STAT表示进程的状态,而进程的状态有不少,以下表所示
状态 |
解释 |
R |
Running.运行中 |
S |
Interruptible Sleep.等待调用 |
D |
Uninterruptible Sleep.不可终端睡眠 |
T |
Stoped.暂停或者跟踪状态 |
X |
Dead.即将被撤销 |
Z |
Zombie.僵尸进程 |
W |
Paging.内存交换 |
N |
优先级低的进程 |
< |
优先级高的进程 |
s |
进程的领导者 |
L |
锁定状态 |
l |
多线程状态 |
+ |
前台进程 |
其中的 D 不可终端睡眠的状态,处在这种状态的进程不接受外来的任何signal,因此没法使用 kill 命令杀掉处于D状态的进程,不管是 kill,kill -9 仍是 kill -15,通常处于这种状态多是进程 IO 的时候出问题了。
ps 工具备许多的参数,下面给你们解释部分经常使用的参数
使用 -l 参数能够显示本身此次登录的 bash 相关的进程信息罗列出来
-lps
相对来讲咱们更加经常使用下面这个命令,他将会罗列出全部的进程信息
psaux
如果查找其中的某个进程的话,咱们还能够配合着 grep 和正则表达式一块儿使用
psaux | grep zsh
此外咱们还能够查看时,将连同部分的进程呈树状显示出来
psaxjf
固然若是你以为使用这样的此时没有把你想要的信息放在一块儿,咱们也能够是用这样的命令,来自定义咱们所须要的参数显示
commandps-afxo user,ppid,pid,pgid,
这是一个简单而又实用的工具,想要更灵活的使用,想要知道更多的参数咱们能够使用 man 来获取更多相关的信息
经过 pstree 能够很直接的看到相同的进程数量,最主要的仍是咱们能够看到全部进程的之间的相关性。
pstree
pstree-up
#参数选择:
#-A :各程序树之间以 ASCII 字元來連接;
#-p :同时列出每一个 process 的 PID;
#-u :同时列出每一个 process 的所屬帐户名称。
上个实验中咱们讲诉了进程之间是如何衍生,之间又有什么相关性,咱们来回顾一下,当一个进程结束的时候或者要异常结束的时候,会向其父进程返回一个或者接收一个 SIGHUP 信号而作出的结束进程或者其余的操做,这个 SIGHUP 信号不只能够由系统发送,咱们能够使用 kill 来发送这个信号来操做进程的结束或者重启等等。
上节课程咱们使用 kill 命令来管理咱们的一些 job,这节课咱们将尝试用 kill 来操做下一些不属于 job 范畴的进程,直接对 pid 下手
#首先咱们使用图形界面打开了 gedit、gvim,用 ps 能够查看到
ps aux
#使用9这个信号强制结束 gedit 进程
kill91608-
#咱们在查找这个进程的时候就找不到了
grepps aux |gedit
咱们在是使用 ps 命令的时候咱们能够看到大部分的进程都是处于休眠的状态,若是这些进程都被唤醒,那么该谁最早享受 CPU 的服务,后面的进程又该是一个什么样的顺序呢?进程调度的队列又该如何去排列呢?
固然就是靠该进程的优先级值来断定进程调度的优先级,而优先级的值就是上文所提到的 PR 与 nice 来控制与体现了
而 nice 的值咱们是能够经过 nice 命令来修改的,而须要注意的是 nice 值能够调整的范围是 -20 ~ 19,其中 root 有着至高无上的权力,既能够调整本身的进程也能够调整其余用户的程序,而且是全部的值均可以用,而普通用户只能够调制属于本身的进程,而且其使用的范围只能是 0 ~ 19,由于系统为了不通常用户抢占系统资源而设置的一个限制
#这个实验在环境中没法作,由于权限不够,能够本身在本地尝试
#打开一个程序放在后台,或者用图形界面打开
5nice -n -vim &
#用 ps 查看其优先级
stattimegrepps -afxo user,ppid,pid,,pri,ni,,command |vim
咱们还能够用 renice 来修改已经存在的进程的优先级,一样由于权限的缘由在实验环境中没法尝试
renice5-pid
经过本实验咱们学会了进程的查看命令 ps,pstree,top,以及使用这些命令是所获得的信息的含义,从而获取咱们想要,咱们须要的信息,同是咱们学会了进程的管理命令 kill,nice,renice
<span id=jump> 注释1: 该例子参考于http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages</span>
日志数据能够是有价值的信息宝库,也能够是毫无价值的数据泥潭。它能够记录下系统所产生的全部行为,并按照某种规范表达出来。咱们能够使用日志系统所记录的信息为系统进行排错,优化系统的性能,或者根据这些信息调整系统的行为。收集你想要的数据,分析出有价值的信息,能够提升系统、产品的安全性,能够帮助开发完善代码,优化产品。日志会成为在事故发生后查明“发生了什么”的一个很好的“取证”信息来源。日志能够为审计进行审计跟踪。
日志是一个系统管理员,一个运维人员,甚至是开发人员不可或缺的东西,系统用久了偶尔也会出现一些错误,咱们须要日志来给系统排错,在一些网络应用服务不能正常工做的时候,咱们须要用日志来作问题定位,日志仍是过往时间的记录本,咱们能够经过它知道咱们是否被不明用户登录过等等。
在 Linux 中大部分的发行版都内置使用 syslog 系统日志,那么经过前期的课程咱们了解到常见的日志通常存放在 /var/log
中,咱们来看看其中有哪些日志
根据图中所显示的日志,咱们能够根据服务对象粗略的将日志分为两类
系统日志主要是存放系统内置程序或系统内核之类的日志信息如 alternatives.log
、btmp
等等,应用日志主要是咱们装的第三方应用所产生的日志如 tomcat7
、apache2
等等。
接下来咱们来看看常见的系统日志有哪些,他们都记录了怎样的信息
日志名称 |
记录信息 |
alternatives.log |
系统的一些更新替代信息记录 |
apport.log |
应用程序崩溃信息记录 |
apt/history.log |
使用apt-get安装卸载软件的信息记录 |
apt/term.log |
使用apt-get时的具体操做,如 package 的下载打开等 |
auth.log |
登陆认证的信息记录 |
boot.log |
系统启动时的程序服务的日志信息 |
btmp |
错误登录的信息记录 |
Consolekit/history |
控制台的信息记录 |
dist-upgrade |
dist-upgrade这种更新方式的信息记录 |
dmesg |
启动时,显示屏幕上内核缓冲信息,与硬件有关的信息 |
dpkg.log |
dpkg命令管理包的日志。 |
faillog |
用户登陆失败详细信息记录 |
fontconfig.log |
与字体配置有关的信息记录 |
kern.log |
内核产生的信息记录,在本身修改内核时有很大帮助 |
lastlog |
用户的最近信息记录 |
wtmp |
登陆信息的记录。wtmp能够找出谁正在登录进入系统,谁使用命令显示这个文件或信息等 |
syslog |
系统信息记录 |
而在本实验环境中没有 apport.log 是由于 apport 这个应用程序须要读取一些内核的信息来收集判断其余应用程序的信息,从而记录应用程序的崩溃信息。而在本实验环境中的咱们没有这个权限,因此将 apport 从内置应用值剔除,天然而然就没有它的日志信息了。
只闻其名,不见其人,咱们并不能真正体会这些日志记录的内容。首先咱们来看 alternatives.log
中的信息,在本实验环境中没有任何日志输出是由于刚刚启动的系统中并无任何的更新迭代。我能够看看从其余地方截取过来的内容
update2016-07-02133616with--install /usr/bin/x-www-browser x-www-browser /usr/bin/google-chrome-stable 200-alternatives::: run
update2016-07-02133616with--install /usr/bin/gnome-www-browser gnome-www-browser /usr/bin/google-chrome-stable 200-alternatives::: run
update2016-07-02133616with--install /usr/bin/google-chrome google-chrome /usr/bin/google-chrome-stable 200-alternatives::: run
咱们能够从中获得信息有程序做用,日期,命令,成功与否的返回码
咱们用这样的命令来看看 auth.log
中的信息
logless auth.
咱们能够从中获得的信息有日期与 ip 地址的来源以及登录的用户与工具
在 apt 文件夹中的日志信息,其中有两个日志文件 history.log
与 term.log
,两个日志文件的区别在于 history.log
主要记录了进行了那个操做,相关的依赖有哪些,而 term.log
则是较为具体的一些操做,主要就是下载包,打开包,安装包等等的细节操做。
咱们经过这样的例子就能够很明显的看出区别,在本实验环境中由于是刚启动的环境,因此两个日志中的信息都是空的
loglogless /var//apt/history.
loglogless /var//apt/term.
而后咱们来安装 git 这个程序,由于本实验环境中本有预装 git 因此这里真正执行的操做是一个更新的操做,但这并不影响
getsudo apt-install git
成功的执行以后咱们再来查看两个日志的内容变化
其余的日志格式也都相似与以前咱们所查看的日志,主要即是时间,操做。而这其中有两个比较特殊的日志,其查看的方式比较不同凡响,由于这两个日志并非 ASCII 文件而是被编码成了二进制文件,因此咱们并不能直接使用 less、cat、more 这样的工具来查看,这两个日志文件是 wtmp,lastlog
咱们查看的方法是使用 last 与 lastlog 工具来提取其中的信息
关于这两个工具的更深刻使用咱们能够使用前面的学习过的 man 来查看
这些日志是如何产生的,而且经过上面的例子咱们能够看出大部分的日志信息彷佛格式都都很相似,而且为何都会出如今这个文件夹中。
这样的实现能够经过两种方式,一种是由软件开发商本身来自定义日志格式而后指定输出日志位置,还有一种方式就是 Linux 提供的日志服务程序,而咱们这里系统日志是经过 syslog 来实现,提供日志管理服务。
syslog 是一个系统日志记录程序,在早期的大部分 Linux 发行版都是内置 syslog,让其做为系统的默认日志收集工具,虽然时代的进步与发展,syslog 已经年老体衰跟不上时代的需求,因此他被 rsyslog 所代替了,较新的Ubuntu、Fedora 等等都是默认使用 rsyslog 做为系统的日志收集工具
rsyslog的全称是 rocket-fast system for log,它提供了高性能,高安全功能和模块化设计。rsyslog可以接受从各类各样的来源,将其输入,输出的结果到不一样的目的地。rsyslog能够提供超过每秒一百万条消息给目标文件,
这样能实时收集日志信息的程序都会有其守护进程如 rsyslog 的守护进程即是 rsyslogd
由于一些缘由本实验环境中默认并无打开这个服务,咱们能够手动开启这项服务,而后来查看
sudoservice rsyslog start
ps aux | grep syslog
既然它是一个服务,那么它即是能够配置,为咱们提供一些咱们自定义的服务
首先咱们来看 rsyslog 的配置文件是什么样子的,而 rsyslog 的配置文件有两个,一个是 /etc/rsyslog
一个是 /etc/rsyslog.d/50-default.conf
。第一个主要是配置的环境,也就是 rsyslog 的加载什么模块,文件的所属者等;而第二个主要是配置的 Filter Conditions
vim /etc/rsyslog.conf
50defaultvim /etc/rsyslog.d/-.conf
看了以后并不知道从何如何,也不知道他在写什么,咱们仍是来看看 rsyslog 的结构框架,数据流的走向吧。
经过这个简单的流程图咱们能够知道 rsyslog 主要是由 Input、Output、Parser 这样三个模块构成的,而且了解到数据的简单走向,首先经过 Input module 来收集消息,而后将获得的消息传给 Parser module,经过分析模块的层层处理,将真正须要的消息传给 Output module,而后便输出至日志文件中
上文提到过 rsyslog 号称能够提供超过每秒一百万条消息给目标文件,怎么只是这样简单的结构。咱们能够经过下图来作更深刻的了解
图片来源于http://www.rsyslog.com/doc/queues_analogy.html
Rsyslog 架构如图中所示,从图中咱们能够很清楚的看见,rsyslog 还有一个核心的功能模块即是 Queue,也正是由于它才能作到如此高的并发。
第一个模块即是 Input,该模块的主要功能就是从各类各样的来源出收集 messages,经过一下这些接口实现
接口名 |
做用 |
im3195 |
RFC3195 Input Module |
imfile |
Text File Input Module |
imgssapi |
GSSAPI Syslog Input Module |
imjournal |
Systemd Journal Input Module |
imklog |
Kernel Log Input Module |
imkmsg |
/dev/kmsg Log Input Module |
impstats |
Generate Periodic Statistics of Internal Counters |
imptcp |
Plain TCP Syslog |
imrelp |
RELP Input Module |
imsolaris |
Solaris Input Module |
imtcp |
TCP Syslog Input Module |
imudp |
UDP Syslog Input Module |
imuxsock |
Unix Socket Input |
而 Output 中也有许多可用的接口,能够经过 man 或者官方的文档查看
而这些模块接口的使用须要经过 $ModLoad 指令来加载,那么返回上文的图中,配置生效的头两行能够看懂了,默认加载了 imklog、imuxsock 这两个模块
在配置中 rsyslog 支持三种配置语法格式:
sysklogd 是老的简单格式,一些新的语法特性不支持。而 legacy rsyslog 是以 dollar 符($)开头的语法,在v6及以上的版本还在支持,就如上文所说的 $ModLoad
还有一些插件和特性可能只在此语法下支持。而以 $
开头的指令是全局指令,全局指令是 rsyslogd 守护进程的配置指令,每行只能有一个指令。 RainnerScript 是最新的语法。在官网上 rsyslog 大多推荐这个语法格式来配置
老的语法格式(sysklogd & legacy rsyslog)是以行为单位。新的语法格式(RainnerScript)能够分割多行。
注释有两种语法:
/* .. */
执行顺序: 指令在 rsyslog.conf 文件中是从上到下的顺序执行的。
模板是 rsyslog 一个重要的属性,它能够控制日志的格式,支持相似 template() 语句的基于 string 或 plugin 的模板,即是经过它来自定义咱们的日志格式
legacy 格式使用 $template 的语法,不过这个在之后要移除,因此最好使用新格式 template():,以避免将来忽然不工做了也不知道为何
模板定义的形式有四种,适用于不一样的输出模块,通常简单的格式,能够使用 string 的形式,复杂的格式,建议使用 list 的形式,使用 list 的形式,能够使用一些额外的属性字段(property statement)
若是不指定输出模板,rsyslog 会默认使用 RSYSLOG_DEFAULT。若想更深刻的学习能够查看官方文档
了解了 rsyslog 环境的配置文件以后,咱们看向 /etc/rsyslog.d/50-default.conf
这个配置文件,这个文件中主要是配置的 Filter Conditions,也就咱们在流程图中所看见的 Parser & Filter Engine
,它的名字叫 Selectors 是过滤 syslog 的传统方法,他主要由两部分组成,facility
与 priority
,其配置格式以下
logfacility.priority _location
其中一个 priority 能够指定多个 facility,多个 facility 之间使用逗号 ,
分割开
rsyslog 经过 Facility 的概念来定义日志消息的来源,以便对日志进行分类,Facility 的种类有:
类别 |
解释 |
kern |
内核消息 |
user |
用户信息 |
|
邮件系统消息 |
daemon |
系统服务消息 |
auth |
认证系统 |
authpriv |
权限系统 |
syslog |
日志系统自身消息 |
cron |
计划安排 |
news |
新闻信息 |
local0~7 |
由自定义程序使用 |
而另一部分 priority 也称之为 serverity level,除了日志的来源之外,对统一源产生日志消息还须要进行优先级的划分,而优先级的类别有一下几种:
类别 |
解释 |
emergency |
系统已经没法使用了 |
alert |
必须当即处理的问题 |
critical |
很严重了 |
error |
错误 |
warning |
警告信息 |
notice |
系统正常,可是比较重要 |
informational |
正常 |
debug |
debug的调试信息 |
panic |
很严重可是已淘汰不经常使用 |
none |
没有优先级,不记录任何日志消息 |
咱们来看看系统中的配置
loglogauth,authpriv.* /var//auth.
这里的意思是 auth 与 authpriv 的全部优先级的信息全都输出于 /var/log/auth.log
日志中
而其中有相似于这样的配置信息意思有细微的差异
loglogkern.* -/var//kern.
-
表明异步写入,也就是日志写入时不须要等待系统缓存的同步,也就是日志还在内存中缓存也能够继续写入无需等待彻底写入硬盘后再写入。一般用于写入数据比较大时使用。
到此咱们对 rsyslog 的配置就有了必定的了解,若想更深刻学习模板,队列的高级应用,你们可去查看官网的文档,须要注意的是 rsyslog 每一个版本之间差别化比较大,学习以前先查看本身所使用的版本,再去查看相关的文档
与日志相关的还有一个还有经常使用的命令 logger
,logger 是一个 shell 命令接口,能够经过该接口使用 Syslog 的系统日志模块,还能够从命令行直接向系统日志文件写入信息。
#首先将syslog启动起来
sudo service rsyslog start
#向 syslog 写入数据
testlocalping 127.0.0.1 | logger -it logger_-p3.notice &
#查看是否有数据写入
-flogtail/var//syslog
从图中咱们能够看到咱们成功的将 ping 的信息写入了 syslog 中,格式也就是使用的 rsyslog 的默认模板
咱们能够经过 man 来查看 logger 的更深刻用法,上诉命令中
参数 |
内容 |
-i |
在每行都记录进程ID |
-t |
添加tag标签 |
-p |
设置日志的facility与priority |
在本地的机器中天天都有成百上千条日志被写入文件中,更别说是咱们的服务器,天天都会有数十兆甚至更多的日志信息被写入文件中,若是是这样的话,天天看着咱们的日志文件不断的膨胀,那岂不是要占用许多的空间,因此有个叫 logrotate 的东西诞生了。
logrotate 程序是一个日志文件管理工具。用来把旧的日志文件删除,并建立新的日志文件。咱们能够根据日志文件的大小,也能够根据其天数来切割日志,来管理日志。这个过程又叫作“转储”
大多数Linux发行版使用 logrotate 或 newsyslog 对日志进行管理。logrotate 程序不但能够压缩日志文件,减小存储空间,还能够将日志发送到指定 E-mail,方便管理员及时查看日志。
显而易见,logrotate 是基于 CRON 来运行的,其脚本是 /etc/cron.daily/logrotate;同时咱们能够在 /etc/logrotate
中找到其配置文件
cat/etc/logrotate
这其中的具体意思是什么呢?
# see "man logrotate" for details //能够查看帮助文档
# rotate log files weekly
//设置每周转储一次(daily、weekly、monthly固然能够使用这些参数天天、星期,月 )weekly
# keep 4 weeks worth of backlogs
4//最多转储4次rotate
# create new (empty) log files after rotating old ones
//当转储后文件不存在时建立它create
# uncomment this if you want your log files compressed
//经过gzip压缩方式转储(nocompress能够不压缩)compress
# RPM packages drop log rotation information into this directory
include//其余日志文件的转储方式配置文件,包含在该目录下/etc/logrotate.d
# no packages own wtmp -- we'll rotate them here
var//设置/var/log/wtmp日志文件的转储参数//log/wtmp {
//每个月转储 monthly
0664//转储后文件不存在时建立它,文件全部者为root,所属组为utmp,对应的权限为0664 createroot utmp
1//最多转储一次 rotate
}
固然在 /etc/logrotate.d/ 中有各项应用的 logrotate 配置,还有更多的配置参数,你们能够使用 man 查看,如按文件大小转储,按当前时间格式命名等等参数配置。
经过本实验咱们了解系统日志结构,以及咱们能够从中获取什么样的信息,给咱们带来什么样的价值。还有日志工具的配置,以及省心省力的 logrotate