网络对抗Linux实验楼测试
第一章 简介
Linux 主要是系统调用和内核那两层
Linux历史
操作系统始于二十世纪五十年代,当时的操作系统能运行批处理程序。批处理程序不需要用户的交互,它从文件或者穿孔卡片读取数据,然后输出到另外一个文件或者打印机。
二十世纪六十年代初,交互式操作系统开始流行。它不仅仅可以交互,还能使多个用户从不同的终端同时操作主机。这样的操作系统被称作分时操作系统,它的出现对批处理操作系统是个极大的挑战。许多人尝试开发分时操作系统, 其中包括一些大学的研究项目和商业项目。当时有个项目叫做 Multics ,它的技术在当时很具有创新性。 Multics 项目的开发并不顺利,它花费了远超过预计的资金,却没有在操作系统市场上占到多少份额。而参加该项目的一个开发团体——贝尔实验室退出了这个项目。他们在退出后开发了他们自己的一个操作系统—— UNIX 。
UNIX 最初免费发布并因此在大学里受到欢迎。后来,UNIX 实现了 TCP/IP 协议栈,成为了早期工作站的操作系统的一个流行选择。
1990 年,UNIX 在服务器市场上尤其是大学校园中成为主流操作系统,许多校园都有 UNIX 主机,当然还包括一些研究它的计算机系的学生。这些学生都渴望能在自己的电脑上运行 UNIX 。不幸的是,从那时候开始,UNIX 开始变得商业化,它的价格也变得非常昂贵。而唯一低廉的选择就是 MINIX,这是一个功能有限的类似 UNIX 的操作系统,作者 Andrew Tanenbaum 开发它的目的是用于教学。
1991 年 10 月,Linus Torvalds(Linux 之父)在赫尔辛基大学接触 UNIX,他希望能在自己的电脑上运行一个类似的操作系统。可是 UNIX 的商业版本非常昂贵,于是他从 MINIX 开始入手,计划开发一个比 MINIX 性能更好的操作系统。很快他就开始了自己的开发工作。他第一次发行的版本迅速吸引了一些黑客。尽管最初的 Linux 并没有多少用处,但由于一些黑客的加入使它很快就具有了许多吸引人的特性,甚至一些对操作系统开发不感兴趣的人也开始关注它。
Linux 本身只是操作系统的内核。内核是使其它程序能够运行的基础。它实现了多任务和硬件管理,用户或者系统管理员交互运行的所有程序实际上都运行在内核之上。其中有些程序是必需的,比如说,命令行解释器(shell),它用于用户交互和编写 shell 脚本。 Linus 没有自己去开发这些应用程序,而是使用已有的自由软件。这减少了搭建开发环境所需花费的工作量。实际上,他经常改写内核,使得那些程序能够更容易地在 Linux 上运行。许多重要的软件,包括 C 编译器,都来自于自由软件基金 GNU 项目。GNU 项目开始于 1984 年,目的是为了开发一个完全类似于 UNIX 的免费操作系统。为了表扬 GNU 对 Linux 的贡献,许多人把 Linux 称为 GNU/Linux(GNU 有自己的内核)。
1992-1993 年,Linux 内核具备了挑战 UNIX 的所有本质特性,包括 TCP/IP 网络,图形界面系统(X window ),Linux 同样也吸引了许多行业的关注。一些小的公司开始开发和发行 Linux,有几十个 Linux 用户社区成立。1994 年,Linux 杂志也开始发行。
Linux 内核 1.0 在 1994 年 3 月发布,内核的发布要经历许多开发周期,直至达到一个稳定的版本。
下面列举一些 Linux 诞生大事件:
1965 年,Bell 实验室、MIT、GE(通用电气公司)准备开发 Multics 系统,为了同时支持 300 个终端访问主机,但是 1969 年失败了;
那时候并没有鼠标、键盘,输入设备,只有卡片机。因此,如果要测试某个程序,则需要将读卡纸插入卡片机,如果有错误,还需要重新来过;Multics:Multiplexed Information and Computing Service;
1969 年,Ken Thompson(C 语言之父)利用汇编语言开发了 File Server System(Unics,即 UNIX 的原型);
因为汇编语言对于硬件的依赖性,因此只能针对特定硬件; 只是为了移植一款“太空旅游”的游戏;
1973 年,Dennis Ritchie 和 Ken Thompson 发明了 C 语言,而后写出了 UNIX 的内核;
将 B 语言改成 C 语言,由此产生了 C 语言之父;90% 的代码是 C 语言写的,10% 的代码用汇编语言写的,因此移植时只要修改那 10% 的代码即可;
1977 年,Berkeley 大学的 Bill Joy 针对他的机器修改了 UNIX 源码,称为 BSD(Berkeley Software Distribution);
Bill Joy 是 Sun 公司的创始人;
1979 年,UNIX 发布 System V,用于个人计算机;
1984 年,因为 UNIX 规定“不能对学生提供源码”,Tanenbaum 老师自己编写兼容于 UNIX 的 Minix,用于教学;
1984 年,Stallman 开始 GNU(GNU's Not Unix)项目,创办 FSF(Free Software Foundation)基金会;
产品:GCC、Emacs、Bash Shell、GLIBC;倡导“自由软件”;GNU 的软件缺乏一个开放的平台运行,只能在 UNIX 上运行;自由软件指用户可以对软件做任何修改,甚至再发行,但是始终要挂着 GPL 的版权;自由软件是可以卖的,但是不能只卖软件,而是卖服务、手册等;
1985 年,为了避免 GNU 开发的自由软件被其他人用作专利软件,因此创建 GPL(General Public License)版权声明;
1988 年,MIT 为了开发 GUI,成立了研发 XFree86 的组织;
1991 年,芬兰赫尔辛基大学的研究生 Linus Torvalds 基于 gcc、bash 开发了针对 386 机器的 Linux 内核;
1994 年,Torvalds 发布 Linux-v1.0;
1996 年,Torvalds 发布 Linux-v2.0,确定了 Linux 的吉祥物:企鹅。
UNIX 进化史(UNIX 大家族族谱 1969-2013):
Linux重要人物
- Ken Thompson:C 语言之父和 UNIX 之父
- Dennis Ritchie:C 语言之父和 UNIX 之父
- Stallman:著名黑客,GNU 创始人,开发了 Emacs、gcc、bash shell
- Bill Joy:BSD 开发者
- Tanenbaum:Minix 开发者
- Linus Torvalds:Linux 之父,芬兰赫尔辛基大学
Linux与Windows不同之处
-
免费与收费
最新正版 Windows 10,需要付费购买;
Linux 免费或少许费用。 -
软件与支持
Windows 平台:数量和质量的优势,不过大部分为收费软件;由微软官方提供重要支持和服务;
Linux 平台:大都为开源自由软件,用户可以修改定制和再发布,由于基本免费没有资金支持,部分软件质量和体验欠缺;由全球所有的 Linux 开发者和自由软件社区提供支持。 -
安全性
Windows 平台:三天两头打补丁安装系统安全更新,还是会中病毒木马;
Linux 平台:要说 Linux 没有安全问题,那当然是不可能的,这一点仁者见仁智者见智,相对来说肯定比 Windows 平台要更加安全,使用 Linux 你也不用装某杀毒、某毒霸。 -
使用习惯
Windows:普通用户基本都是纯图形界面下操作使用,依靠鼠标和键盘完成一切操作,用户上手容易,入门简单;
Linux:兼具图形界面操作(需要使用带有桌面环境的发行版)和完全的命令行操作,可以只用键盘完成一切操作,新手入门较困难,需要一些学习和指导(这正是我们要做的事情),一旦熟练之后效率极高。 -
可定制性
Windows:这些年之前算是全封闭的,系统可定制性很差;
Linux:你想怎么做就怎么做,Windows 能做到得它都能,Windows 做不到的,它也能。 -
应用范畴
或许你之前不知道 Linux ,要知道,你之前在 Windows 使用百度、谷歌,上淘宝,聊 QQ 时,支撑这些软件和服务的,是后台成千上万的 Linux 服务器主机,它们时时刻刻都在忙碌地进行着数据处理和运算,可以说世界上大部分软件和服务都是运行在 Linux 之上的。 -
Windows 没有的
稳定的系统
安全性和漏洞的快速修补
多用户
用户和用户组的规划
相对较少的系统资源占用
可定制裁剪,移植到嵌入式平台(如安卓设备)
可选择的多种图形用户界面(如 GNOME,KDE) -
Linux 没有的
特定的支持厂商
足够的游戏娱乐支持度
足够的专业软件支持度
如何学习Linux
- 学习心态
明确目的:你是要用 Linux 来干什么,搭建服务器、做程序开发、日常办公,还是娱乐游戏;
面对现实:Linux 大都在命令行下操作,能否接受不用或少用图形界面;
是学习 Linux 操作系统本身还是某一个 Linux 发行版(Ubuntu,CentOS,Fedora,OpenSUSE,Debian,Mint 等等),如果你对发行版的概念或者它们之间的关系不明确的话可以参看 Linux 发行版。
- 注重基础,从头开始
大致的学习路径如下:
第二章 基本概念和操作
桌面环境
1.Linux 桌面环境介绍
相对于现在的 Windows 系统,UNIX/Linux 本身是没有图形界面的,我们通常在 UNIX/Linux 发行版上看到的图形界面实际都只是运行在 Linux 系统之上的一套软件,类似 Windows95 之前的 Windows 的图形界面实则也只是运行在 DOS 环境的一套软件。而 Linux 上的这套软件以前是 XFree86,现在则是 xorg(X.Org),而这套软件又是通过 X 窗口系统(X Window System,也常被称为 X11 或 X)实现的,X 本身只是工具包及架构协议,而 xorg 便是 X 架构规范的一个实现体,也就是说它是实现了 X 协议规范的一个提供图形界面服务的服务器,就像实现了 http 协议提供 web 服务的 Apache 。如果只有服务器也是不能实现一个完整的桌面环境的,当然还需要一个客户端,我们称为 X Client,像如下几个大家熟知也最流行的实现了客户端功能的桌面环境 KDE,GNOME,XFCE,LXDE 。其中就有你看到的,实验楼目前使用的 XFCE 桌面环境,部分老用户可能可以回想起,实验楼之前使用的环境是 LXDE 。这也意味着在 Linux 上你可以自己选择安装不同的桌面环境,甚至可以定制自己的专属桌面。
Linux终端
终端的概念
通常我们在使用 Linux 时,并不是直接与系统打交道,而是通过一个叫做 Shell 的中间程序来完成的,在图形界面下为了实现让我们在一个窗口中完成用户输入和显示输出,Linux 系统还提供了一个叫做终端模拟器的程序(Terminal)。 下面是几个比较常见的终端模拟器: gnome-terminal,Konsole,xterm,rxvt,kvt,nxterm 和 eterm 。目前我们的实验中的终端程序是 xfce 桌面环境自带的 xfce-terminal 。不过要注意的是这里所说的终端(Terminal)和控制台(Console)是有区别的。
终端本质上是对应着 Linux 上的 /dev/tty 设备,Linux 的多用户登录就是通过不同的 /dev/tty 设备完成的,Linux 默认提供了 6 个纯命令行界面的 “terminal”(准确的说这里应该是 6 个 virtual consoles)来让用户登录。在物理机系统上你可以通过使用[Ctrl]+[Alt]+[F1]~[F6]进行切换,不过在我们的在线实验环境中可能无法切换,因为特殊功能按键会被你的主机系统劫持。当你切换到其中一个终端后想要切换回图形界面,你可以按下[Ctrl]+[Alt]+[F7]来完成。
shell
通常在图形界面中对实际体验带来差异的不是上述的不同发行版的各种终端模拟器,而是这个 Shell(壳)。有壳就有核,这里的核就是指 UNIX/Linux 内核,Shell 是指“提供给使用者使用界面”的软件(命令解析器),类似于 DOS 下的 command(命令行)和后来的 cmd.exe 。普通意义上的 Shell 就是可以接受用户输入命令的程序。它之所以被称作 Shell 是因为它隐藏了操作系统底层的细节。同样的 UNIX/Linux 下的图形用户界面 GNOME 和 KDE,有时也被叫做“虚拟 shell”或“图形 shell”。
UNIX/Linux 操作系统下的 Shell 既是用户交互的界面,也是控制系统的脚本语言。当然这一点也有别于 Windows 下的命令行,虽然该命令行也提供了很简单的控制语句。在 Windows 操作系统下,有些用户从来都不会直接使用 Shell,然而在 UNIX 系列操作系统下,Shell 仍然是控制系统启动、X11 启动和很多其它实用工具的脚本解释程序。
在 UNIX/Linux 中比较流行的常见的 Shell 有 bash、zsh、ksh、csh 等等,Ubuntu 终端默认使用的是 bash,默认的桌面环境是 GNOME 或者 Unity(基于 GNOME),但我们的环境中使用的分别是 zsh 和 xfce。
常用命令行快捷键
按键 | 作用 |
---|---|
Ctrl+d | 键盘输入结束或退出终端 |
Ctrl+s | 暂停当前程序,暂停后按下任意键恢复运行 |
Ctrl+z | 将当前程序放到后台运行,恢复到前台为命令fg |
Ctrl+a | 将光标移至输入行头,相当于Home键 |
Ctrl+e | 将光标移至输入行末,相当于End键 |
Ctrl+k | 删除从光标所在位置到行末 |
Alt+Backspace | 向前删除一个单词 |
Shift+PgUp | 将终端显示向上滚动 |
Shift+PgDn | 将终端显示向下滚动 |
通配符
通配符是一种特殊语句,主要有星号(*)和问号(?),用来对字符串进行模糊匹配(比如文件名、参数名)。当查找文件夹时,可以使用它来代替一个或多个真正字符;当不知道真正字符或者懒得输入完整名字时,常常使用通配符代替一个或多个真正字符。
终端里面输入的通配符是由 Shell 处理的,不是由所涉及的命令语句处理的,它只会出现在命令的“参数值”里(它不能出现在命令名称里, 命令不记得,那就用Tab补全)。当 Shell 在“参数值”中遇到了通配符时,Shell 会将其当作路径或文件名在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换(路径扩展);否则就将该通配符作为一个普通字符传递给“命令”,然后再由命令进行处理。总之,通配符实际上就是一种 Shell 实现的路径扩展功能。在通配符被处理后, Shell 会先完成该命令的重组,然后继续处理重组后的命令,直至执行该命令。
在创建文件的时候,如果需要一次性创建多个文件,比如:“love_1_linux.txt,love_2_linux.txt,... love_10_linux.txt”。在 Linux 中十分方便:
touch love_{1..10}_shiyanlou.txt
字符 | 含义 |
---|---|
* | 匹配 0 或多个字符 |
? | 匹配任意一个字符 |
[list] | 匹配 list 中的任意单一字符 |
[^list] | 匹配 除 list 中的任意单一字符以外的字符 |
[c1-c2] | 匹配 c1-c2 中的任意单一字符 如:[0-9][a-z] |
匹配 string1 或 string2 (或更多)其一字符串 | |
匹配 c1-c2 中全部字符 如 |
man手册
区段 说明
1 一般命令
2 系统调用
3 库函数,涵盖了 C 标准函数库
4 特殊文件(通常是/dev 中的设备)和驱动程序
5 文件格式和约定
6 游戏和屏保
7 杂项
8 系统管理命令和守护进程
要查看相应区段的内容,就在 man 后面加上相应区段的数字即可,如:
man 1 ls #会显示第一区段中的ls命令 man 页面。
所有的手册页遵循一个常见的布局,为了通过简单的 ASCII 文本展示而被优化,而这种情况下可能没有任何形式的高亮或字体控制。一般包括以下部分内容:
NAME(名称)
该命令或函数的名称,接着是一行简介。
SYNOPSIS(概要)
对于命令,正式的描述它如何运行,以及需要什么样的命令行参数。对于函数,介绍函数所需的参数,以及哪个头文件包含该函数的定义。
DESCRIPTION(说明)
命令或函数功能的文本描述。
EXAMPLES(示例)
常用的一些示例。
SEE ALSO(参见)
相关命令或函数的列表。
也可能存在其它部分内容,但这些部分没有得到跨手册页的标准化。常见的例子包括:OPTIONS(选项),EXIT STATUS(退出状态),ENVIRONMENT(环境),BUGS(程序漏洞),FILES(文件),AUTHOR(作者),REPORTING BUGS(已知漏洞),HISTORY(历史)和 COPYRIGHT(版权)。
通常 man 手册中的内容很多,你可能不太容易找到你想要的结果,不过幸运的是你可以在 man 中使用搜索/<你要搜索的关键字>,查找完毕后你可以使用n键切换到下一个关键字所在处,shift+n为上一个关键字所在处。使用Space(空格键)翻页,Enter(回车键)向下滚动一行,或者使用k,j(vim 编辑器的移动键)进行向前向后滚动一行。按下h键为显示使用帮助(因为 man 使用 less 作为阅读器,实为less工具的帮助),按下q退出。
想要获得更详细的帮助,你还可以使用info命令,不过通常使用man就足够了。如果你知道某个命令的作用,只是想快速查看一些它的某个具体参数的作用,那么你可以使用--help参数,大部分命令都会带有这个参数,如:
ls --help
有趣的Linux命令
sudo apt-get update
sudo apt-get install sysvbanner
banner shiyanlou
printerbanner -w 50 A
toilet shiyanlou
figlet shiyanlou
《黑客帝国》电影里满屏幕代码的“数字雨”,在 Linux 里面你也可以轻松实现这样的效果,你只需要一个命令 cmatrix 。
第三章 用户和文件权限
用户
su
sudo
su -
sudo adduser lilei
su -l lilei 和 su - lilei 一个效果
groups shiyanlou
其中冒号之前表示用户,后面表示该用户所属的用户组。这里可以看到 shiyanlou 用户属于 shiyanlou 用户组,每次新建用户如果不指定用户组的话,默认会自动创建一个与用户名相同的用户组(差不多就相当于家长的意思)。
sudo deluser lilei --remove-home
使用 --remove-home 参数在删除用户时候会一并将该用户的工作目录一并删除。如果不使用那么系统会自动在 /home 目录为该用户保留工作目录。
删除用户组可以使用 groupdel 命令,倘若该群组中仍包括某些用户,则必须先删除这些用户后,才能删除群组。
文件权限
一个目录同时具有读权限和执行权限才可以打开并查看内部文件,而一个目录要有写权限才允许在其中创建其它文件,这是因为目录文件实际保存着该目录里面的文件的列表等信息。
ls -a 显示隐藏文件(Linux 下以 . 开头的文件为隐藏文件)。
ls -dl <目录名> 查看某一个目录的完整属性,而不是显示目录里面的文件属性。
ls -asSh 显示所有文件大小,并以普通人类能看懂的方式呈现。
其中小 s 为显示文件大小,大 S 为按文件大小排序。
变更文件所有者
sudo chown shiyanlou iphone11
修改文件权限
chmod 600 iphone11 rw- --- ---
chmod go-rw iphone11
g、o 还有 u 分别表示 group(用户组)、others(其他用户) 和 user(用户),+ 和 - 分别表示增加和去掉相应的权限。
adduser 和 useradd 的区别是什么
答:useradd 只创建用户,不会创建用户密码和工作目录,创建完了需要使用 passwd
第四章 目录结构和文件基本操作
Linux目录与Windows目录
以往的 Windows 一直是以存储介质为主的,主要以盘符(C 盘,D 盘...)及分区来实现文件管理,然后之下才是目录,目录就显得不是那么重要,除系统文件之外的用户文件放在任何地方任何目录也是没有多大关系。所以通常 Windows 在使用一段时间后,磁盘上面的文件目录会显得杂乱无章(少数善于整理的用户除外吧)。
然而 UNIX/Linux 恰好相反,UNIX 是以目录为主的,Linux 也继承了这一优良特性。 Linux 是以树形目录结构的形式来构建整个系统的,可以理解为树形目录是一个用户可操作系统的骨架。虽然本质上无论是目录结构还是操作系统内核都是存储在磁盘上的,但从逻辑上来说 Linux 的磁盘是“挂在”(挂载在)目录上的,每一个目录不仅能使用本地磁盘分区的文件系统,也可以使用网络上的文件系统。举例来说,可以利用网络文件系统(Network File System,NFS)服务器载入某特定目录等。
FHS
FHS(英文:Filesystem Hierarchy Standard 中文:文件系统层次结构标准),多数 Linux 版本采用这种文件组织形式,FHS 定义了系统中每个区域的用途、所需要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。
FHS 定义了两层规范,第一层是, / 下面的各个目录应该要放什么文件数据,例如 /etc 应该放置设置文件,/bin 与 /sbin 则应该放置可执行文件等等。
第二层则是针对 /usr 及 /var 这两个目录的子目录来定义。例如 /var/log 放置系统日志文件,/usr/share 放置共享数据等等。
关于上面提到的 FHS,这里还有个很重要的内容你一定要明白,FHS 是根据以往无数 Linux 用户和开发者的经验总结出来的,并且会维持更新,FHS 依据文件系统使用的频繁与否以及是否允许用户随意改动(注意,不是不能,学习过程中,不要怕这些),将目录定义为四种交互作用的形态,如下表所示:
目录路径
使用 cd 命令可以切换目录,在 Linux 里面使用 . 表示当前目录,.. 表示上一级目录(注意,我们上一节介绍过的,以 . 开头的文件都是隐藏文件,所以这两个目录必然也是隐藏的,你可以使用 ls -a 命令查看隐藏文件),
- 表示上一次所在目录,~ 通常表示当前用户的 home 目录。使用 pwd 命令可以获取当前所在路径(绝对路径)。
命令
使用 touch 命令创建空白文件,关于 touch 命令,其主要作用是来更改已有文件的时间戳的(比如,最近访问时间,最近修改时间),但其在不加任何参数的情况下,只指定一个文件名,则可以创建一个指定文件名的空白文件(不会覆盖已有同名文件),当然你也可以同时指定该文件的时间戳。
若当前目录存在一个 test 文件夹,则 touch 命令,则会更改该文件夹的时间戳而不是新建文件。
使用 mkdir(make directories)命令可以创建一个空目录,也可同时指定创建目录的权限属性。
使用 -p 参数,同时创建父目录(如果不存在该父目录),如下我们同时创建一个多级目录(这在安装软件、配置安装路径时非常有用)。
还有一点需要注意的是,若当前目录已经创建了一个 test 文件,再使用 mkdir test 新建同名的文件夹,系统会报错文件已存在。这符合 Linux 一切皆文件的理念。
后台运行 &
怎么关闭 xeyes 呢?我们需要使用 kill 命令来杀死这个进程。输入上面的命令后终端会输出一个 PID,这就是 xeyes 的进程号,这个进程号不是固定的,比如我这里是 20295,那么我们输入 sudo kill -9 20295 即可结束这个进程。
第五章 环境变量和文件查找
使用 declare 命令创建一个变量名为 tmp 的变量:
declare tmp
其实也可以不用 declare 预声明一个变量,直接即用即创建,这里只是告诉你 declare 的作用,这在创建其它指定类型的变量(如数组)时会用到。
使用 = 号赋值运算符,将变量 tmp 赋值为 shiyanlou。注意,与其他语言不同的是, Shell 中的赋值操作,= 两边不可以输入空格,否则会报错。
正确的赋值
tmp=shiyanlou
错误的赋值
tmp = shiyanlou
读取变量的值,使用 echo 命令和 $ 符号($ 符号用于表示引用一个变量的值,初学者经常忘记输入):
echo $tmp
变量名只能是英文字母、数字或者下划线,且不能以数字作为开头。
命 令 | 说 明 |
---|---|
set | 显示当前 Shell 所有变量,包括其内建环境变量(与 Shell 外观等相关),用户自定义变量及导出的环境变量。 |
env | 显示与当前用户相关的环境变量,还可以让命令在指定环境中运行。 |
export | 显示从 Shell 中导出成环境变量的变量,也能通过它将自定义变量导出为环境变量。 |
永久生效
这里介绍两个重要文件 /etc/bashrc(有的 Linux 没有这个文件) 和 /etc/profile ,它们分别存放的是 shell 变量和环境变量。还有要注意区别的是每个用户目录下的一个隐藏文件:
PATH
PATH=$PATH:/home/shiyanlou/mybin
注意这里一定要使用绝对路径。
可以使用 cat /etc/shells 命令查看当前系统已安装的 Shell。
我们可以简单地使用下面命令直接添加内容到 .zshrc 中:
echo "PATH=$PATH:/home/shiyanlou/mybin" >> .zshrc
上述命令中 >> 表示将标准输出以追加的方式重定向到一个文件中,注意前面用到的 > 是以覆盖的方式重定向到一个文件中,使用的时候一定要注意分辨。在指定文件不存在的情况下都会创建新的文件。
变量删除
可以使用 unset 命令删除一个环境变量:
变量修改(字符串变量的修改)
${变量名#匹配字串} 从头向后开始匹配,删除符合匹配字串的最短数据
${变量名##匹配字串} 从头向后开始匹配,删除符合匹配字串的最长数据
${变量名%匹配字串} 从尾向前开始匹配,删除符合匹配字串的最短数据
${变量名%%匹配字串} 从尾向前开始匹配,删除符合匹配字串的最长数据
${变量名/旧的字串/新的字串} 将符合旧字串的第一个字串替换为新的字串
${变量名//旧的字串/新的字串} 将符合旧字串的全部字串替换为新的字串
source 命令还有一个别名就是 .,上面的命令如果替换成 . 的方式就该是:
. ./.zshrc
注意第一个点后面有一个空格,而且后面的文件必须指定完整的绝对或相对路径名,source 则不需要。
搜索文件
whereis,which,find 和 locate
whereis 只能搜索二进制文件(-b),man 帮助文件(-m)和源代码文件(-s)。这个搜索很快,因为它并没有从硬盘中依次查找,而是直接从数据库中查询。
locate 命令查找文件也不会遍历硬盘,它通过查询 /var/lib/mlocate/mlocate.db 数据库来检索信息。不过这个数据库也不是实时更新的,系统会使用定时任务每天自动执行 updatedb 命令来更新数据库。所以有时候你刚添加的文件,它可能会找不到,需要手动执行一次 updatedb 命令
sudo apt-get update
sudo apt-get install locate
sudo updatedb
它可以用来查找指定目录下的不同文件类型,如查找 /etc 下所有以 sh 开头的文件:
locate /etc/sh 注意,它不只是在 /etc 目录下查找,还会自动递归子目录进行查找。
如果想只统计数目可以加上 -c 参数,-i 参数可以忽略大小写进行查找
whereis 的 -b、-m、-s 同样可以使用。
which 本身是 Shell 内建的一个命令,我们通常使用 which 来确定是否安装了某个指定的程序,因为它只从 PATH 环境变量指定的路径中去搜索命令并且返回第一个搜索到的结果。也就是说,我们可以看到某个系统命令是否存在以及执行的到底是哪一个地方的命令。
find
find [path][option] [action] 。
sudo find /etc/ -name interfaces
参数 | 说明 |
---|---|
-atime | 最后访问时间 |
-ctime | 最后修改文件内容的时间 |
-mtime | 最后修改文件属性的时间 |
下面以 -mtime 参数举例:
-mtime n:n 为数字,表示为在 n 天之前的“一天之内”修改过的文件
-mtime +n:列出在 n 天之前(不包含 n 天本身)被修改过的文件
-mtime -n:列出在 n 天之内(包含 n 天本身)被修改过的文件
-newer file:file 为一个已存在的文件,列出比 file 还要新的文件名
列出 home 目录中,当天(24 小时之内)有改动的文件:
find ~ -mtime 0
压缩和解压
文件后缀名 | 说明 |
---|---|
*.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 打包文件夹,注意输入完整的参数和路径:
cd /home/shiyanlou
zip -r -q -o shiyanlou.zip /home/shiyanlou/Desktop
du -h shiyanlou.zip
file shiyanlou.zip
上面命令将目录 /home/shiyanlou/Desktop 打包成一个文件,并查看了打包后文件的大小和类型。第一行命令中,-r 参数表示递归打包包含子目录的全部内容,-q 参数表示为安静模式,即不向屏幕输出信息,-o,表示输出文件,需在其后紧跟打包输出文件名。后面使用 du 命令查看打包后文件的大小(后面会具体说明该命令)。
设置压缩级别为 9 和 1(9 最大,1 最小),重新打包:
zip -r -9 -q -o shiyanlou_9.zip /home/shiyanlou/Desktop -x ~/.zip
zip -r -1 -q -o shiyanlou_1.zip /home/shiyanlou/Desktop -x ~/.zip
这里添加了一个参数用于设置压缩级别 -[1-9],1 表示最快压缩但体积大,9 表示体积最小但耗时最久。最后那个 -x 是为了排除我们上一次创建的 zip 文件,否则又会被打包进这一次的压缩文件中,注意:这里只能使用绝对路径,否则不起作用。
我们再用 du 命令分别查看默认压缩级别、最低、最高压缩级别及未压缩的文件的大小:
du -h -d 0 *.zip ~ | sort
-h, --human-readable(顾名思义,你可以试试不加的情况)
-d, --max-depth(所查看文件的深度)
创建加密 zip 包
使用 -e 参数可以创建加密压缩包:
zip -r -e -o shiyanlou_encryption.zip /home/shiyanlou/Desktop
转windows换行符格式
zip -r -l -o shiyanlou.zip /home/shiyanlou/Desktop
需要加上 -l 参数将 LF 转换为 CR+LF 来达到以上目的。
使用 unzip 命令解压缩 zip 文件
将 shiyanlou.zip 解压到当前目录:
unzip shiyanlou.zip
使用安静模式,将文件解压到指定目录:
unzip -q shiyanlou.zip -d ziptest
上述指定目录不存在,将会自动创建。如果你不想解压只想查看压缩包的内容你可以使用 -l 参数:
unzip -l shiyanlou.zip
使用 -O(英文字母,大写 o)参数指定编码类型:
unzip -O GBK 中文压缩文件.zip
tar
创建一个 tar 包:
cd /home/shiyanlou
tar -P -cf shiyanlou.tar /home/shiyanlou/Desktop
上面命令中,-P 保留绝对路径符,-c 表示创建一个 tar 包文件,-f 用于指定创建的文件名,注意文件名必须紧跟在 -f 参数之后,比如不能写成 tar -fc shiyanlou.tar,可以写成 tar -f shiyanlou.tar -c ~。你还可以加上 -v 参数以可视的的方式输出打包的文件。
解包一个文件(-x 参数)到指定路径的已存在目录(-C 参数):
mkdir tardir
tar -xf shiyanlou.tar -C tardir
只查看不解包文件 -t 参数:
tar -tf shiyanlou.tar
保留文件属性和跟随链接(符号链接或软链接),有时候我们使用 tar 备份文件当你在其他主机还原时希望保留文件的属性(-p 参数)和备份链接指向的源文件而不是链接本身(-h 参数):
tar -cphf etc.tar /etc
对于创建不同的压缩格式的文件,对于 tar 来说是相当简单的,需要的只是换一个参数,这里我们就以使用 gzip 工具创建 *.tar.gz 文件为例来说明。
我们只需要在创建 tar 文件的基础上添加 -z 参数,使用 gzip 来压缩文件:
tar -czf shiyanlou.tar.gz /home/shiyanlou/Desktop
解压 *.tar.gz 文件:
tar -xzf shiyanlou.tar.gz
压缩文件格式 | 参数 |
---|---|
*.tar.gz | -z |
*.tar.xz | -J |
*tar.bz2 | -j |
zip:
打包 :zip something.zip something (目录请加 -r 参数)
解包:unzip something.zip
指定路径:-d 参数
tar:
打包:tar -cf something.tar something
解包:tar -xf something.tar
指定路径:-C 参数
文件系统操作与磁盘管理
使用 df 命令查看磁盘的容量
df
物理主机上的 /dev/sda2 是对应着主机硬盘的分区,后面的数字表示分区号,数字前面的字母 a 表示第几块硬盘(也可能是可移动磁盘),你如果主机上有多块硬盘则可能还会出现 /dev/sdb,/dev/sdc 这些磁盘设备都会在 /dev 目录下以文件的存在形式。
接着你还会看到"1k-块"这个陌生的东西,它表示以磁盘块大小的方式显示容量,后面为相应的以块大小表示的已用和可用容量,在你了解 Linux 的文件系统之前这个就先不管吧,我们以一种你应该看得懂的方式展示:
df -h
使用 du 命令查看目录的容量
默认同样以块的大小展示
du
加上 -h
参数,以更易读的方式展示
du -h
-d 参数指定查看目录的深度
只查看 1 级目录的信息
du -h -d 0 ~
du -h # 同 --human-readable 以 K,M,G 为单位,提高信息的可读性。
du -a # 同 --all 显示目录中所有文件的大小。
du -s # 同 --summarize 仅显示总计,只列出最后加总的值。
查看 2 级
du -h -d 1 ~
du(estimate file space usage)命令与 df(report file system disk space usage)命令只有一字之差,希望大家注意不要弄混淆了,你可以像我这样从 man 手册中获取命令的完整描述,记全称就不会搞混了。
创建虚拟磁盘/dd命令简介
dd 命令用于转换和复制文件,不过它的复制不同于 cp。之前提到过关于 Linux 的很重要的一点,一切即文件,在 Linux 上,硬件的设备驱动(如硬盘)和特殊设备文件(如 /dev/zero 和 /dev/random)都像普通文件一样,只是在各自的驱动程序中实现了对应的功能,dd 也可以读取文件或写入这些文件。这样,dd 也可以用在备份硬件的引导扇区、获取一定数量的随机数据或者空数据等任务中。dd 程序也可以在复制时处理数据,例如转换字节序、或在 ASCII 与 EBCDIC 编码间互换。
dd 的命令行语句与其他的 Linux 程序不同,因为它的命令行选项格式为 选项=值,而不是更标准的 --选项 值 或 -选项=值。dd 默认从标准输入中读取,并写入到标准输出中,但可以用选项 if(input file,输入文件)和 of(output file,输出文件)改变。
我们先来试试用 dd 命令从标准输入读入用户的输入到标准输出或者一个文件中:
输出到文件
dd of=test bs=10 count=1 # 或者 dd if=/dev/stdin of=test bs=10 count=1
输出到标准输出
dd if=/dev/stdin of=/dev/stdout bs=10 count=1
在打完了这个命令后,继续在终端打字,作为你的输入
上述命令从标准输入设备读入用户输入(缺省值,所以可省略)然后输出到 test 文件,bs(block size)用于指定块大小(缺省单位为 Byte,也可为其指定如 K,M,G 等单位),count 用于指定块数量。如上图所示,我指定只读取总共 10 个字节的数据,当我输入了 hello shiyanlou 之后加上空格回车总共 16 个字节(一个英文字符占一个字节)内容,显然超过了设定大小。使用 du 和 cat 10 个字节(那个黑底百分号表示这里没有换行符),而其他的多余输入将被截取并保留在标准输入。
前面说到 dd 在拷贝的同时还可以实现数据转换,那下面就举一个简单的例子:将输出的英文字符转换为大写再写入文件:
dd if=/dev/stdin of=test bs=10 count=1 conv=ucase
从 /dev/zero 设备创建一个容量为 256M 的空文件:
dd if=/dev/zero of=virtual.img bs=1M count=256
du -h virtual.img
使用 mkfs 命令格式化磁盘(我们这里是自己创建的虚拟磁盘镜像)
你可以在命令行输入 sudo mkfs 然后按下
我们可以简单的使用下面的命令来将我们的虚拟磁盘镜像格式化为 ext4 文件系统:
sudo mkfs.ext4 virtual.img
使用 mount 命令挂载磁盘到目录树
我们先来使用 mount 来查看下主机已经挂载的文件系统:
sudo mount
输出的结果中每一行表示一个设备或虚拟设备,每一行最前面是设备名,然后是 on 后面是挂载点,type 后面表示文件系统类型,再后面是挂载选项(比如可以在挂载时设定以只读方式挂载等等)。
那么我们如何挂载真正的磁盘到目录树呢,mount 命令的一般格式如下:
mount [options] [source] [directory]
一些常用操作:
mount [-o [操作选项]] [-t 文件系统类型] [-w|--rw|--ro] [文件系统源] [挂载点]
注意:由于实验楼的环境限制,mount 命令挂载及 umount 卸载都无法进行操作,可以简单了解这些步骤。
现在直接来挂载我们创建的虚拟磁盘镜像到 /mnt 目录:
mount -o loop -t ext4 virtual.img /mnt
也可以省略挂载类型,很多时候 mount 会自动识别
以只读方式挂载
mount -o loop --ro virtual.img /mnt
或者 mount -o loop,ro virtual.img /mnt
使用 umount 命令卸载已挂载磁盘
使用 fdisk 为磁盘分区
查看硬盘分区表信息
sudo fdisk -l
进入磁盘分区模式
sudo fdisk virtual.img
使用 losetup 命令建立镜像与回环设备的关联
sudo losetup /dev/loop0 virtual.img
如果提示设备忙你也可以使用其它的回环设备,"ls /dev/loop*"参看所有回环设备
解除设备关联
sudo losetup -d /dev/loop0
sudo apt-get install kpartx
sudo kpartx -av /dev/loop0
取消映射
sudo kpartx -dv /dev/loop0
sudo mkfs.ext4 -q /dev/mapper/loop0p1
sudo mkfs.ext4 -q /dev/mapper/loop0p5
sudo mkfs.ext4 -q /dev/mapper/loop0p6
mkdir -p /media/virtualdisk_{1..3}
挂载磁盘分区
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
Linux 下的帮助命令
内建命令实际上是 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 vim
type ls
help
help ls 不行
因为 help 命令是用于显示 shell 内建命令的简要帮助信息。帮助信息中显示有该命令的简要说明以及一些参数的使用以及说明,一定记住 help 命令只能用于显示内建命令的帮助信息,不然就会得到你刚刚得到的结果。
ls --help
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 特定的), 用来存放内核例行程序的文档 |
要是你觉得 man 显示的信息都还不够,满足不了你的需求,那试试 info 命令,注意实验楼的环境中没有安装 info,可以手动安装,安装和操作步骤如下:
info
安装 info
sudo apt-get update
sudo apt-get install info
查看 ls 命令的 info
info ls
Linux 任务计划 crontab
crontab 命令常见于 Unix 和类 Unix 的操作系统之中(Linux 就属于类 Unix 操作系统),用于设置周期性被执行的指令。
crontab 命令从输入设备读取指令,并将其存放于 crontab 文件中,以供之后读取和执行。通常,crontab 储存的指令被守护进程激活,crond 为其守护进程,crond 常常在后台运行,每一分钟会检查一次是否有预定的作业需要执行。
通过 crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell 脚本。时间间隔的单位可以是分钟、小时、日、月、周的任意组合。
这里我们看一看 crontab 的格式:
Example of job definition:
.---------------- minute (0 - 59)
| .------------- hour (0 - 23)
| | .---------- day of month (1 - 31)
| | | .------- month (1 - 12) OR jan,feb,mar,apr ...
| | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
| | | | |
* * * * * user-name command to be executed
crontab 在本实验环境中需要做一些特殊的准备,首先我们会启动 rsyslog,以便我们可以通过日志中的信息来了解我们的任务是否真正的被执行了(在本实验环境中需要手动启动,而在自己本地中 Ubuntu 会默认自行启动不需要手动启动)。
sudo apt-get install -y rsyslog
sudo service rsyslog start
下面将开始 crontab 的使用了,我们通过下面一个命令来添加一个计划任务:
crontab -e
第一次启动会出现这样一个画面,这是让我们选择编辑的工具,选择第二个基本的 vim 就可以了
而选择后我们会进入这样一个画面,这就是添加计划的地方了,
与一般的配置文档相同,以#号开头的都是注释,通过文档的最后一排我们可以猜猜 crontab 的格式是什么样的呢?
该任务是每分钟我们会在/home/shiyanlou 目录下创建一个以当前的年月日时分秒为名字的空白文件
*/1 * * * * touch /home/shiyanlou/$(date +%Y%m%d%H%M%S)
注意:
“ % ” 在 crontab 文件中,有结束命令行、换行、重定向的作用,前面加 ” \ ” 符号转义,否则,“ % ” 符号将执行其结束命令行或者换行的作用,并且其后的内容会被做为标准输入发送给前面的命令。
当然我们也可以通过这样的一个指令来查看我们添加了哪些任务:
crontab -l
虽然我们添加了任务,但是如果 cron 的守护进程并没有启动,它根本都不会监测到有任务,当然也就不会帮我们执行,我们可以通过以下 2 种方式来确定我们的 cron 是否成功的在后台启动,默默的帮我们做事,若是没有就得执行上文准备中的第二步了。
ps aux | grep cron
or
pgrep cron
我们通过这样一个命令可以查看到执行任务命令之后在日志中的信息反馈:
sudo tail -f /var/log/syslog
当我们并不需要这个任务的时候我们可以使用这么一个命令去删除任务:
crontab -r
每个用户使用 crontab -e 添加计划任务,都会在 /var/spool/cron/crontabs 中添加一个该用户自己的任务文档,这样目的是为了隔离。
如果是系统级别的定时任务,需要 root 权限执行的任务应该怎么处理?
只需要使用 sudo 编辑 /etc/crontab 文件就可以。
cron 服务监测时间最小单位是分钟,所以 cron 会每分钟去读取一次 /etc/crontab 与 /var/spool/cron/crontabs 里面的內容。
在 /etc 目录下,cron 相关的目录有下面几个:
每个目录的作用:
/etc/cron.daily,目录下的脚本会每天执行一次,在每天的 6 点 25 分时运行;
/etc/cron.hourly,目录下的脚本会每个小时执行一次,在每小时的 17 分钟时运行;
/etc/cron.monthly,目录下的脚本会每月执行一次,在每月 1 号的 6 点 52 分时运行;
/etc/cron.weekly,目录下的脚本会每周执行一次,在每周第七天的 6 点 47 分时运行;
系统默认执行时间可以根据需求进行修改。
crontab -e 表示为当前用户添加计划任务
sudo crontab -e 表示为root用户添加计划任务
使用select-editor命令切换编辑器
注意使用下面的命令启动 crontab:
sudo cron -f &
sudo cron -f &
crontab -e # 添加
0 3 * * * sudo rm /home/shiyanlou/tmp/*
0 3 * * * sudo cp /var/log/alternatives.log /home/shiyanlou/tmp/$(date +%Y-%m-%d)
命令执行顺序控制与管道
执行第一个命令,返回成功,执行第二个命令:&&
执行第一个命令,返回失败,执行第二个命令:||
Linux命令执行成功,返回0,执行不成功,返回非0(错误码)
管道 |
管道是一种通信机制,通常用于进程间的通信(也可通过 socket 进行网络通信),它表现出来的形式就是将前面每一个进程的输出(stdout)直接作为下一个进程的输入(stdin)。
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
grep
grep [命令选项] [用于匹配的表达式] [文件]
grep -rnI "shiyanlou" ~
查看环境变量中以 "yanlou" 结尾的字符串
export | grep ".*yanlou$"
-r 参数表示递归搜索子目录中的文件,-n 表示打印匹配项行号,-I 表示忽略二进制文件。
wc命令
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 个字节的,具体数目是由字符编码决定的。
sort 排序命令
反转排序:
cat /etc/passwd | sort -r
copy
按特定字段排序:
cat /etc/passwd | sort -t':' -k 3
copy
上面的-t参数用于指定字段的分隔符,这里是以":"作为分隔符;-k 字段号用于指定对哪一个字段进行排序。这里/etc/passwd文件的第三个字段为数字,默认情况下是以字典序排序的,如果要按照数字排序就要加上-n参数:
cat /etc/passwd | sort -t':' -k 3 -n
uniq 去重命令
uniq 命令可以用于过滤或者输出重复行。
我们可以使用 history 命令查看最近执行过的命令(实际为读取 ${SHELL}_history 文件,如我们环境中的 .zsh_history 文件),不过你可能只想查看使用了哪个命令而不需要知道具体干了什么,那么你可能就会要想去掉命令后面的参数然后去掉重复的命令:
history | cut -c 8- | cut -d ' ' -f 1 | uniq
copy
然后经过层层过滤,你会发现确是只输出了执行的命令那一列,不过去重效果好像不明显,仔细看你会发现它确实去重了,只是不那么明显,之所以不明显是因为 uniq 命令只能去连续重复的行,不是全文去重,所以要达到预期效果,我们先排序:
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq
或者
history | cut -c 8- | cut -d ' ' -f 1 | sort -u
copy
这就是 Linux/UNIX 哲学吸引人的地方,大繁至简,一个命令只干一件事却能干到最好。
输出重复行
输出重复过的行(重复的只输出一个)及重复次数
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -dc
输出所有重复的行
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -D
简单的文本处理
r 命令可以用来删除一段文本信息中的某些文字。或者将其进行转换。
使用方式
tr [option]...SET1 [SET2]
copy
常用的选项有
选项 说明
-d 删除和 set1 匹配的字符,注意不是全词匹配也不是按字符顺序匹配
-s 去除 set1 指定的在输入文本中连续并重复的字符
操作举例
删除 "hello shiyanlou" 中所有的'o','l','h'
$ echo 'hello shiyanlou' | tr -d 'olh'
将"hello" 中的ll,去重为一个l
$ echo 'hello' | tr -s 'l'
将输入文本,全部转换为大写或小写输出
$ echo 'input some text here' | tr '[:lower:]' '[:upper:]'
上面的'[:lower:]' '[:upper:]'你也可以简单的写作'[a-z]' '[A-Z]',当然反过来将大写变小写也是可以的
col命令
col 命令可以将Tab换成对等数量的空格键,或反转这个操作。
使用方式
col [option]
copy
常用的选项有
选项 说明
-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
join命令
学过数据库的用户对这个应该不会陌生,这个命令就是用于将两个文件中包含相同内容的那一行合并在一起。
使用方式
join [option]... file1 file2
copy
常用的选项有
选项 说明
-t 指定分隔符,默认为空格
-i 忽略大小写的差异
-1 指明第一个文件要用哪个字段来对比,默认对比第一个字段
-2 指明第二个文件要用哪个字段来对比,默认对比第一个字段
操作举例
cd /home/shiyanlou
创建两个文件
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
paste 命令
paste这个命令与join 命令类似,它是在不对比数据的情况下,简单地将多个文件合并一起,以Tab隔开。
使用方式
paste [option] file...
copy
常用的选项有
选项 说明
-d 指定合并的分隔符,默认为 Tab
-s 不合并到一行,每个文件为一行
操作举例
echo hello > file1
echo shiyanlou > file2
echo www.shiyanlou.com > file3
paste -d ':' file1 file2 file3
paste -s file1 file2 file3
可以直接使用 dos2unix 和 unix2dos 工具在windows文件和Linux文件两种格式之间进行转换,使用 file 命令可以查看文件的具体类型。
数据流重定向
文件描述符 | 设备文件 | 说明 |
---|---|---|
0 | /dev/stdin | 标准输入 |
1 | /dev/stdout | 标准输出 |
2 | /dev/stderr | 标准错误 |
文件描述符:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,
mkdir Documents
cat > Documents/test.c <<EOF
include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
EOF
标准错误重定向
将标准错误重定向到标准输出,再将标准输出重定向到文件,注意要将重定向到文件写到前面
cat Documents/test.c hello.c >somefile 2>&1
或者只用bash提供的特殊的重定向符号"&"将标准错误和标准输出同时重定向到文件
cat Documents/test.c hello.c &>somefilehell
注意你应该在输出重定向文件描述符前加上&,否则 shell 会当做重定向到一个文件名为 1 的文件中
永久重定向
exec 命令的作用是使用指定的命令替换当前的 Shell,即使用一个进程替换当前进程,或者指定新的重定向:
先开启一个子 Shell
zsh
使用exec替换当前进程的重定向,将标准输出重定向到一个文件
exec 1>somefile
后面你执行的命令的输出都将被重定向到文件中,直到你退出当前子shell,或取消exec的重定向(后面将告诉你怎么做)
ls
exit
cat somefile
创建输出文件描述符
在 Shell 中有 9 个文件描述符。上面我们使用了也是它默认提供的 0,1,2 号文件描述符。另外我们还可以使用 3-8 的文件描述符,只是它们默认没有打开而已。你可以使用下面命令查看当前 Shell 进程中打开的文件描述符:
cd /dev/fd/;ls -Al
copy
同样使用 exec 命令可以创建新的文件描述符:
zsh
exec 3>somefile
先进入目录,再查看,否则你可能不能得到正确的结果,然后再回到上一次的目录
cd /dev/fd/;ls -Al;cd -
注意下面的命令>与&之间不应该有空格,如果有空格则会出错
echo "this is test" >&3
cat somefile
exit
关闭文件描述符
exec 3>&-
cd /dev/fd;ls -Al;cd -
黑洞
在 Linux 中有一个被称为黑洞的设备文件,所有导入它的数据都将被吞噬。
在类 UNIX 系统中,/dev/null,或称空设备,是一个特殊的设备文件,它通常被用于丢弃不需要的输出流,或作为用于输入流的空文件,这些操作通常由重定向完成。读取它则会立即得到一个 EOF。
我们可以利用 /dev/null 屏蔽命令的输出:
cat Documents/test.c 1>/dev/null 2>&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 子集的适用于 perl 和 python 编程语言及 grep 或 egrep 的正则表达式匹配规则:
PCRE(Perl Compatible Regular Expressions 中文含义:perl 语言兼容正则表达式)是一个用 C 语言编写的正则表达式函数库,由菲利普.海泽(Philip Hazel)编写。PCRE 是一个轻量级的函数库,比 Boost 之类的正则表达式库小得多。PCRE 十分易用,同时功能也很强大,性能超过了 POSIX 正则表达式库和一些经典的正则表达式库。
(由于 markdown 表格解析的问题,下面的竖直分隔符 | 用全角字符代替,实际使用时请换回半角字符。
字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符。 例如 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 支持三种正则表达式引擎,分别用三个参数指定:
参数 说明
-E POSIX 扩展正则表达式,ERE
-G POSIX 基本正则表达式,BRE
-P Perl 正则表达式,PCRE
不过在你没学过 perl 语言的大多数情况下你将只会使用到 ERE 和 BRE,所以我们接下来的内容都不会讨论到 PCRE 中特有的一些正则表达式语法(它们之间大部分内容是存在交集的,所以你不用担心会遗漏多少重要内容)。
在通过grep命令使用正则表达式之前,先介绍一下它的常用参数:
参数 说明
-b 将二进制文件作为文本来进行匹配
-c 统计以模式匹配的数目
-i 忽略大小写
-n 显示匹配文本所在行的行号
-v 反选,输出不匹配行的内容
-r 递归匹配查找
-A n n 为正整数,表示 after 的意思,除了列出匹配行之外,还列出后面的 n 行
-B n n 为正整数,表示 before 的意思,除了列出匹配行之外,还列出前面的 n 行
--color=auto 将输出中的匹配项设置为自动颜色显示
查找 /etc/group 文件中以 shiyanlou 为开头的行
grep 'shiyanlou' /etc/group
grep '^shiyanlou' /etc/group
特殊符号 | 说明 |
---|---|
[: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 的数字与字节 |
当 ^ 放到中括号内为排除字符,否则表示行首。
使用扩展正则表达式,ERE
要通过 grep 使用扩展正则表达式需要加上 -E 参数,或使用 egrep。
数量
只匹配"zo"
echo 'zero\nzo\nzoo' | grep -E 'zo{1}'
匹配以"zo"开头的所有单词
echo 'zero\nzo\nzoo' | grep -E 'zo{1,}'
sed
sed 命令基本格式:
sed [参数]... [执行命令] [输入文件]...
形如:
$ sed -i 's/sad/happy/' test # 表示将test文件中的"sad"替换为"happy"
参数 说明
-n 安静模式,只打印受影响的行,默认打印输入数据的全部内容
-e 用于在脚本中添加多个执行命令一次执行,在命令行中执行多个命令通常不需要加该参数
-f filename 指定执行 filename 文件中的命令
-r 使用扩展正则表达式,默认为标准正则表达式
-i 将直接修改输入文件内容,而不是打印到标准输出设备
sed -i 's/sad/happy/g' test # g 表示全局范围
sed -i 's/sad/happy/4' test # 4 表示指定行中的第四个匹配字符串
命令 | 说明 |
---|---|
s | 行内替换 |
c | 整行替换 |
a | 插入到指定行的后面 |
i | 插入到指定行的前面 |
p | 打印指定行,通常与 -n 参数配合使用 |
d | 删除指定行 |
打印2-5行
nl passwd | sed -n '2,5p'
打印奇数行
nl passwd | sed -n '1~2p'
将输入文本中"shiyanlou" 全局替换为"hehe",并只打印替换的那一行,注意这里不能省略最后的"p"命令
sed -n 's/shiyanlou/hehe/gp' passwd
nl passwd | grep "shiyanlou"
删除第30行
sed -i '30d' passwd
awk
AWK 是一种优良的文本处理工具,Linux 及 Unix 环境中现有的功能最强大的数据处理引擎之一。AWK 是一种用于处理文本的编程语言工具。
awk 命令基本格式
awk [-F fs] [-v var=value] [-f prog-file | 'program text'] [file...]
其中 -F 参数用于预先指定前面提到的字段分隔符(还有其他指定字段的方式),-v 用于预先为 awk 程序指定变量,-f 参数用于指定 awk 命令要执行的程序文件,或者在不加 -f 参数的情况下直接将程序语句放在这里,最后为 awk 需要处理的文本输入,且可以同时输入多个文本文件。现在我们还是直接来具体体验一下吧。
变量名 | 说明 |
---|---|
FILENAME | 当前输入文件名,若有多个文件,则只表示第一个。如果输入是来自标准输入,则为空字符串 |
$0 | 当前记录的内容 |
$N | N 表示字段号,最大值为NF变量的值 |
FS | 字段分隔符,由正则表达式表示,默认为空格 |
RS | 输入记录分隔符,默认为 \n,即一行为一个记录 |
NF | 当前记录字段数 |
NR | 已经读入的记录数 |
FNR | 当前输入文件的记录数,请注意它与 NR 的区别 |
OFS | 输出字段分隔符,默认为空格 |
ORS | 输出记录分隔符,默认为 \n |
Linux 下软件安装
apt 包管理工具介绍
apt-get 是用于处理 apt包的公用程序集,我们可以用它来在线安装、卸载和升级软件包等,下面列出一些 apt-get 包含的常用的一些工具:
工具 | 说明 |
---|---|
install | 其后加上软件包名,用于安装一个软件包 |
update | 从软件源镜像服务器上下载/更新用于更新本地软件源的软件包列表 |
upgrade | 升级本地可更新的全部软件包,但存在依赖问题时将不会升级,通常会在更新之前执行一次 update |
dist-upgrade | 解决依赖关系并升级(存在一定危险性) |
remove | 移除已安装的软件包,包括与被移除软件包有依赖关系的软件包,但不包含软件包的配置文件 |
autoremove | 移除之前被其他软件包依赖,但现在不再被使用的软件包 |
purge | 与 remove 相同,但会完全移除软件包,包含其配置文件 |
clean | 移除下载到本地的已经安装的软件包,默认保存在 /var/cache/apt/archives/ |
autoclean | 移除已安装的软件的旧版本软件包 |
参数 | 说明 |
---|---|
-y | 自动回应是否安装软件包的选项,在一些自动化安装脚本中使用这个参数将十分有用 |
-s | 模拟安装 |
-q | 静默安装方式,指定多个 q 或者 -q=#,# 表示数字,用于设定静默级别,这在你不想要在安装软件包时屏幕输出过多时很有用 |
-f | 修复损坏的依赖关系 |
-d | 只下载不安装 |
--reinstall | 重新安装已经安装但可能存在问题的软件包 |
--install-suggests | 同时安装 APT 给出的建议安装的软件包 |
很多时候我们需要重新安装一个软件包,比如你的系统被破坏,或者一些错误的配置导致软件无法正常工作。你可以使用如下方式重新安装:
sudo apt-get --reinstall install
更新软件源
sudo apt-get update
升级没有依赖问题的软件包
sudo apt-get upgrade
升级并解决依赖关系
sudo apt-get dist-upgrade
卸载
sudo apt-get remove w3m
不保留配置文件的移除
sudo apt-get purge w3m
或者
sudo apt-get --purge remove w3m
移除不再需要的被依赖的软件包
sudo apt-get autoremove
当自己刚知道了一个软件,想下载使用,需要确认软件仓库里面有没有,就需要用到搜索功能了,命令如下:
sudo apt-cache search softname1 softname2 softname3……
dpkg
我们经常可以在网络上见到以deb形式打包的软件包,就需要使用dpkg命令来安装。
dpkg常用参数介绍:
参数 | 说明 |
---|---|
-i | 安装指定 deb 包 |
-R | 后面加上目录名,用于安装该目录下的所有 deb 安装包 |
-r | remove,移除某个已安装的软件包 |
-I | 显示 deb 包文件的信息 |
-s | 显示已安装软件的信息 |
-S | 搜索已安装的软件包 |
-L | 显示已安装软件包的目录信息 |
我们先使用apt-get加上-d参数只下载不安装,下载 emacs 编辑器的 deb 包:
sudo apt-get update
sudo apt-get -d install -y emacs
然后我们将第一个deb拷贝到 /home/shiyanlou 目录下,并使用dpkg安装
cp /var/cache/apt/archives/emacs24_24.5+1-6ubuntu1.1_amd64.deb ~
安装之前参看deb包的信息
sudo dpkg -I emacs24_24.5+1-6ubuntu1.1_amd64.deb
如你所见,这个包还额外依赖了一些软件包,这意味着,如果主机目前没有这些被依赖的软件包,直接使用 dpkg 安装可能会存在一些问题,因为dpkg并不能为你解决依赖关系。
使用dpkg安装
sudo dpkg -i emacs24_24.5+1-6ubuntu1.1_amd64.deb
我们将如何解决这个错误呢?这就要用到apt-get了,使用它的-f参数了,修复依赖关系的安装
sudo apt-get update
sudo apt-get -f install -y
如果你依然在纠结到底 linux 将软件安装到了什么地方,那么很幸运你将可以通过dpkg找到答案
使用dpkg -L查看deb包目录信息
sudo dpkg -L emacs24
进程
关于父进程与子进程便会提及这两个系统调用 fork() 与 exec()
fork-exec是由 Dennis M. Ritchie 创造的
fork() 是一个系统调用(system call),它的主要作用就是为当前的进程创建一个新的进程,这个新的进程就是它的子进程,这个子进程除了父进程的返回值和 PID 以外其他的都一模一样,如进程的执行代码段,内存信息,文件描述,寄存器状态等等
exec() 也是系统调用,作用是切换子进程中的执行程序也就是替换其从父进程复制过来的代码段与数据段
子进程就是父进程通过系统调用 fork() 而产生的复制品,fork() 就是把父进程的 PCB 等进程的数据结构信息直接复制过来,只是修改了 PID,所以一模一样,只有在执行 exec() 之后才会不同,而早先的 fork() 比较消耗资源后来进化成 vfork(),效率高了不少,感兴趣的同学可以查查为什么。
这就是子进程产生的由来。简单的实现逻辑就如下方所示:
pid_t p;
p = fork();
if (p == (pid_t) -1)
/* ERROR /
else if (p == 0)
/ CHILD /
else
/ PARENT */
正常情况下,父进程会收到两个返回值: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,而进程 0 就转为交换进程(也被称为空闲进程),进程 1 (init 进程)是第一个用户态的进程,再由它不断调用 fork() 来创建系统里其他的进程,所以它是所有进程的父进程或者祖先进程。同时它是一个守护程序,直到计算机关机才会停止。
通过以下的命令我们可以很明显的看到这样的结构
pstree(进程树)
进程组与 Sessions
每一个进程都会是一个进程组的成员,而且这个进程组是唯一存在的,他们是依靠 PGID(process group ID)来区别的,而每当一个进程被创建的时候,它便会成为其父进程所在组中的一员。
一般情况,进程组的 PGID 等同于进程组的第一个成员的 PID,并且这样的进程称为该进程组的领导者,也就是领导进程,进程一般通过使用 getpgrp() 系统调用来寻找其所在组的 PGID,领导进程可以先终结,此时进程组依然存在,并持有相同的 PGID,直到进程组中最后一个进程终结。
与进程组类似,每当一个进程被创建的时候,它便会成为其父进程所在 Session 中的一员,每一个进程组都会在一个 Session 中,并且这个 Session 是唯一存在的,
Session 主要是针对一个 tty 建立,Session 中的每个进程都称为一个工作(job)。每个会话可以连接一个终端(control terminal)。当控制终端有输入输出时,都传递给该会话的前台进程组。Session 意义在于将多个 jobs 囊括在一个终端,并取其中的一个 job 作为前台,来直接接收该终端的输入输出以及终端信号。 其他 jobs 在后台运行。
前台(foreground)就是在终端中运行,能与你有交互的
后台(background)就是在终端中运行,但是你并不能与其任何的交互,也不会显示其执行的过程
top 工具是我们常用的一个查看工具,能实时的查看我们系统的一些关键信息的变化:
内容 | 解释 |
---|---|
top | 表示当前程序的名称 |
11:05:18 | 表示当前的系统的时间 |
up 8 days,17:12 | 表示该机器已经启动了多长时间 |
1 user | 表示当前系统中只有一个用户 |
load average: 0.29,0.20,0.25 | 分别对应 1、5、15 分钟内 cpu 的平均负载 |
ps 命令
ps aux
使用 -l 参数可以显示自己这次登录的 bash 相关的进程信息罗列出来:
ps -l
此外我们还可以查看时,将连同部分的进程呈树状显示出来:
ps axjf
kill命令
首先我们使用图形界面打开了 gedit、gvim,用 ps 可以查看到
ps aux
使用 9 这个信号强制结束 gedit 进程
kill -9 1608
我们再查找这个进程的时候就找不到了
ps aux | grep gedit
nice命令
当然就是靠该进程的优先级值来判定进程调度的优先级,而优先级的值就是上文所提到的 PR 与 nice 来控制与体现了
而 nice 的值我们是可以通过 nice 命令来修改的,而需要注意的是 nice 值可以调整的范围是 -20 ~ 19,其中 root 有着至高无上的权力,既可以调整自己的进程也可以调整其他用户的程序,并且是所有的值都可以用,而普通用户只可以调制属于自己的进程,并且其使用的范围只能是 0 ~ 19,因为系统为了避免一般用户抢占系统资源而设置的一个限制
# 这个实验在环境中无法做,因为权限不够,可以自己在本地尝试
# 打开一个程序放在后台,或者用图形界面打开
nice -n -5 vim &
# 用 ps 查看其优先级
ps -afxo user,ppid,pid,stat,pri,ni,time,command | grep vim
我们还可以用 renice 来修改已经存在的进程的优先级,同样因为权限的原因在实验环境中无法尝试。
renice -5 pid
日志
常见的日志
日志名称 | 记录信息 |
---|---|
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 | 系统信息记录 |