Linux常用工具
软件包管理器yum
什么是软件包
在Linux下安装软件最直接的方法是源代码安装,但是这样的话有点麻烦,特别是对系统有依赖文件的时候还需要自行配置。
而有些人比较勤快它们提前把源代码编译,并且帮你把配置文件给配置好,并且打包好而这种包通常叫rpm安装包,而这个包还是一点缺陷的比如这款软件依赖的系统文件发生了变化,那么这个软件也就相应的运行不了,如果想要能运行要么自行配置解决,要么就卸载重新下载新版本的软件包。
而yum软件包管理器相当于手机上的”某某应用商店“我们下载直接到yum上下载即可,一般能下载是因为有人把软件都放到一个服务器上面而这个服务器我们通常叫为包服务器,在yum的包服务器软件通常是安全的(ps:可以理解成为官方发布的软件,标准包管理器)而有些软件并没有放在包管理器上而是放在扩展源包管理器上(ps:可以理解为非官方的软件,非标准包管理)这些软件并不是因为不安全才没放进标准的包管理器上可能是因为种种原因,但是这并不是我们关心的重点,我们的重点是能不能下载我们的目标软件。
如果在标准包服务器上下载不到,我们需要去非标准的包服务器上下载,而想要去非标准包服务器上下载我们需要安装一个扩展源。
sudo yum install -y epel-release //安装扩展源
yum下载&卸载
卸载指令
如果你有个软件想卸载那么你可以输入以下指令
sudo yum remove 软件名
下载指令
如果你想下载某款软件,你可以先查找它是否存在,也可以直接下载。
sudo yum list | grep 软件名 //用于查找某款软件是否在包服务器上面
sudo yum install 软件名 //用于下载软件
sudo yum list //用于查看包服务器内有些什么软件,不过由于数量过多建议把内容打印到文本内查看。
vim文本编辑工具
vim
是一款强大的文本编辑器,它可以编写代码并且使关键字代码拥有高亮且代码补齐……等等功能(ps:这些功能需要自行配置,默认啥都没有的),所以在写代码方面这款软件简直是神器。
当然它只仅仅是文本编辑器并不具备编译代码和调试……等等功能,这不像windows上的编译器,widows下面的vs、vc和dev……等等是集成编译器(文本、调试、编译、链接、生成可执行一体化的编译器称为集成编译器)在Linux下面进行写代码的时候需要用到多款软件来完成,当然LInux下面也有集成的编译器,但是个人认为用非集成的编译器比较好。
vim键盘图:
vim的多种模式
vim命令行模式
这个模式下是不能编辑文本的,一般这种模式下我们使用于退出或拷贝……等等的一些操作,如果想要编辑文本需要进入插入模式。
常用指令:
i
切换为插入模式
:
切换为底行模式
这三中模式之间的切换都必须要在命令模式下才能互相切换,具体如下图:
拷贝操作
拷贝指令 | 说明 |
---|---|
nyy | n为数字,拷贝光标所在到下n行,列如:3 yy//就是拷贝当前行和下三行,共计四行。 |
y1G | 拷贝光标所在行到第一行 |
yG | 拷贝当前行到末尾,如果遇到}那么它只会拷贝到}后的一行之后的都不会拷贝。 |
y0 | 拷贝光标前面的所有字符,且光标会移动到行首(注意:是当前行且不拷贝光标本身那个字符) |
y$ | 拷贝光标当前到行尾的字符(注意:是拷贝当前行,且包括拷贝光标的字符) |
yy | 拷贝光标当前行 |
粘贴操作
粘贴指令 | 说明 |
---|---|
p | 粘贴拷贝的内容,在光标行的下一行进行粘贴操作,如果下一行有数据那么会被推到后面,如果是和拷贝数据一样的数据是不会拷贝出来。 |
P | 粘贴拷贝内容,在光标当前行粘贴并把原光标位置的数据往下推,如果相同不会拷贝出来。 |
n + p(P) | 粘贴多分拷贝内容,n代表份数,如:33 p(P)粘贴33份内容 |
删除操作
删除操作 | 说明 |
---|---|
dd | 删除光标所在行 |
ndd | n为数字,删除多行,例如:2 dd 删除两行 |
d1G | 删除光标以上的所有数据(包括光标当前行) |
dG | 删除光标以下的所有数据(包括光标当前行) |
d$ | 当前行删除光标后面的所有字符(包括光标的字符) |
d0 | 当前行删除光标前面所有的字符(不包括光标本身) |
x | 在一行中,删除光标位置的字符 |
X | 删除光标位置的前一个字符 |
nx(X) | n为数字,删除多个字符 |
撤销操作
撤销指令 | 说明 |
---|---|
u | 撤销 |
[Ctrl]+r | 取消撤销 |
光标移动操作
光标移动指令 | 说明 |
---|---|
h 或 向左箭头键(←) | 光标向左移动一个字符 |
j 或 向下箭头键(↓) | 光标向下移动一个字符 |
k 或 向上箭头键(↑) | 光标向上移动一个字符 |
l 或 向右箭头键(→) | 光标向右移动一个字符 |
[Ctrl] + [f] | 屏幕『向下』移动一页,相当于 [Page Down]按键 (常用) |
[Ctrl] + [b] | 屏幕『向上』移动一页,相当于 [Page Up] 按键 (常用) |
[Ctrl] + [d] | 屏幕『向下』移动半页 |
[Ctrl] + [u] | 屏幕『向上』移动半页 |
+ | 光标移动到非空格符的下一行 |
- | 光标移动到非空格符的上一行 |
n | 那个 n 表示『数字』,例如 20 。按下数字后再按空格键,光标会向右移动这一行的 n 个字符。例如 20 则光标会向后面移动 20 个字符距离。 |
0 或功能键[Home] | 这是数字『 0 』:移动到这一行的最前面字符处 (常用) |
$ 或功能键[End] | 移动到这一行的最后面字符处(常用) |
^ | 移动到这行最前面的非空字符位置 |
H | 光标移动到这个屏幕的最上方那一行的第一个字符 |
M | 光标移动到这个屏幕的中央那一行的第一个字符 |
L | 光标移动到这个屏幕的最下方那一行的第一个字符 |
G | 移动到这个档案的最后一行(常用) |
nG | n 为数字。移动到这个档案的第 n 行。例如 20G 则会移动到这个档案的第 20 行(可配合 :set nu) |
gg | 移动到这个档案的第一行,相当于 1G 啊! (常用) |
n | n 为数字,光标向下移动 n 行(常用) |
w | 光标位置,跳过一个单词 |
b | 光标位置,回到上一个单词 |
e | 光标位置,跳过一个单词,但光标会在跳过的单词的最后一个字符上 |
查找
/word | 向光标之下寻找一个名称为 word 的字符串。例如要在档案内搜寻 vbird 这个字符串,就输入 /vbird 即可! (常用) |
---|---|
?word | 向光标之上寻找一个字符串名称为 word 的字符串。 |
n | 这个 n 是英文按键。代表重复前一个搜寻的动作。举例来说, 如果刚刚我们执行 /vbird 去向下搜寻 vbird 这个字符串,则按下 n 后,会向下继续搜寻下一个名称为 vbird 的字符串。如果是执行 ?vbird 的话,那么按下 n 则会向上继续搜寻名称为 vbird 的字符串! |
N | 这个 N 是英文按键。与 n 刚好相反,为『反向』进行前一个搜寻动作。 例如 /vbird 后,按下 N 则表示『向上』搜寻 vbird 。 |
:n1,n2s/word1/word2/g | n1 与 n2 为数字。在第 n1 与 n2 行之间寻找 word1 这个字符串,并将该字符串取代为 word2 !举例来说,在 100 到 200 行之间搜寻 vbird 并取代为 VBIRD 则: 『:100,200s/vbird/VBIRD/g』。(常用) |
:1,$s/word1/word2/g 或 :%s/word1/word2/g | 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 !(常用) |
:1,$s/word1/word2/gc 或 :%s/word1/word2/gc | 从第一行到最后一行寻找 word1 字符串,并将该字符串取代为 word2 !且在取代前显示提示字符给用户确认 (confirm) 是否需要取代!(常用) |
重复上一个指令
重复指令 | 说明 |
---|---|
. | 不要怀疑!这就是小数点!意思是重复前一个动作的意思。 如果你想要重复删除、重复贴上等等动作,按下小数点『.』就好了! (常用) |
vim插入模式
插入模式指令 | 说明 |
---|---|
i | 在光标位置,进入插入模式 |
I | 在光标位置非空位置,进入插入模式。 |
a | 光标位置向后移动一个字符,再进入插入模式 |
A | 光标行的最后一个字符位置向后移动一个字符,再进入插入模式 |
o | 在光标行的下一行增加一个空行,光标并移动至新增行,再进入插入模式 |
O | 在光标的上一行,增加一个空行,光标并移动至新增行,再进入插入模式。 |
cw | 删除光标位置的一个单词,并进入插入模式 |
cnw | n为数字,删除n个单词,并进入插入模式 |
vim替换模式
替换模式指令 | 说明 |
---|---|
r | 进入替换模式,替换光标位置的字符(只能替换一次) |
R | 进入替换模式,替换光标位置的字符,光标并向后移动一个字符,直到收到esc指令才结束。 |
vim底行模式
底行模式指令 | 说明 |
---|---|
q | 退出文本 |
q! | 强制退出 |
w | 保存文本 |
wq | 保存并退出 |
w! | 强制保存 |
wq! | 强制保存并退出 |
ZZ | 跟wq效果类似(ZZ不用进入底行模式) |
ZQ | 不保存并强制退出和q!类似(ZQ不用进入底行模式) |
w | 将文本的内容拷贝到一个新创建的文本内,如果是已创建的文本不能这么操作,只能是未创建的文本。 |
r 文件名 | 把另一个文档的内容拷贝到当前文本光标所在位置的下一行 |
n1,n2 w 文件名 | 将本文本第n1行到n2行的内容拷贝到另一个新创建的文档,如果新的文档易已存在,则无法执行。 |
! 指令 | 不退出文本,在文本内执行Linux指令。例如:! ls 这类操作 |
s/替换目标字符/替换后的字符 | 用于替换文本内所有相关的字符替换为新的字符。例如:s/aaa/bbb/把aaa替换成bbb |
vs | 分屏,同时进行多个文件的操作 |
vim环境变量的更改
环境变量指令 | 说明 |
---|---|
:set nu | 显示行号,设定之后,会在每一行的前缀显示该行的行号 |
:set nonu | 与 set nu 相反,为取消行号! |
块选择模式
批量注释
Ctrl + v 进入块选择模式,然后移动光标选中你要注释的行,再按大写的 I 进入行首插入模式输入注释符号如 // 或 #,输入完毕之后,按两下 ESC,Vim 会自动将你选中的所有行首都加上注释,保存退出完成注释。
取消注释:Ctrl + v 进入块选择模式,选中你要删除的行首的注释符号,注意 // 要选中两个,选好之后按 d 即可删除注释,ESC 保存退出。
底行命令注释
使用下面命令在指定的行首添加注释。
使用名命令格式: :起始行号,结束行号s/^/注释符/g(注意冒号)。
取消注释:
使用名命令格式: :起始行号,结束行号s/^注释符//g(注意冒号)。
例子:
-
在 10 - 20 行添加 // 注释
:10,20s#^#//#g
-
在 10 - 20 行删除 // 注释
:10,20s#^//##g
-
在 10 - 20 行添加 # 注释
:10,20s/^/#/g
-
在 10 - 20 行删除 # 注释
:10,20s/#//g
gcc/g++编译器的使用
gcc如何使用
语法: gcc [选项] 编译文件
功能: 用于编译C语言程序,编译C++程序使用g++。
选项:
指令 | 说明 |
---|---|
-E | 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面 |
-S | 编译到汇编语言不进行汇编和链接 |
-c | 编译到目标代码 |
-o | 文件输出到文件 |
-static | 此选项对生成的文件采用静态链接 |
-g | 生成调试信息。GNU 调试器可利用该信息 |
-shared | 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库 |
-O0(0-3) | 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 |
-w | 不生成任何警告信息。 |
-whall | 生成所有警告信息。 |
注意:gcc编译器编译不是直接生成可执行程序的,什么参数都不给的情况下它默认执行:预处理->编译->汇编->链接
预处理
预处理是程序执行的第一步,这一步主要是用于删除注释、头文件展开、宏替换和条件编译这几项操作,我们可以使用gcc的
-E
选项来进行查看它对源代码进行了那些处理。
我们可以从图中观察到,这个阶段gcc确实进行了以上处理。
编译
编译这个阶段主要做的工作就是将C代码编译成汇编代码。
汇编
这个阶段主要是生成目标文件,也就是windows下的obj文件而obj文件是二进制的因为已经成为机器码了,所以我们显示器上是无法显示出来的,通常能显示出来的都是乱码。
链接
这个阶段主要是用于链接,虽然代码已经生成为机器码了,cpu能看懂但是它找不到里面的函数调用的地址,所以我们只需进行链接obj文件即可找到对应的函数地址,这个时候代码才是可执行程序。
由于链接不要参数直接输入
gcc obj文件
这个时候会得到a.out的可执行程序,如果有重命名的话那么就不是a.out。
[ls@VM-4-7-centos 11]$ ll
total 44
-rwxrwxr-x 1 ls ls 8400 Dec 11 22:23 a.out
-rw-rw-r-- 1 ls ls 401 Dec 11 22:08 test.c
-rw-rw-r-- 1 ls ls 16921 Dec 11 22:13 test.i
-rw-rw-r-- 1 ls ls 1569 Dec 11 22:19 test.o
-rw-rw-r-- 1 ls ls 507 Dec 11 22:19 test.s
[ls@VM-4-7-centos 11]$ ./a.out
heello centos
hello world
[ls@VM-4-7-centos 11]$
注意: gcc默认生成调用的是动态链接,如果需要静态链接需要带上gcc -static
编程静态链接
库
什么是库?你可能会说我没听过库啊?而且也没使用过!
其实你一直都在使用库像C语言的头文件或者C++的头文件等等……你日常的写练习代码都是用过的,只是你没察觉到而那个阶段也不会有人跟你讲库的概念,所以你就会认为我从来没使用过库,而库又分为两种。
- 静态库
- 动态库
静态库
静态库顾名思义就是静态的,那么怎么个静态法呢?
像刚才上面的预处理阶段,我们就看到头文件展开了而且展开了很多直接让我们的代码从几十行增加到八百多行,而这是为什么呢?这其实就是静态库,静态库就是使用自己代码下面的函数时候不会去调外面的,而这样做的代价就是内存和磁盘占用就很大因为它是直接从动态库内拷贝过来的代码,但是它有一个优点不依赖第三方库任何平台都能跑移植性高。
总结:
- 优点
- 移植性高
- 不依赖第三方库
- 缺点
- 体积大
- 加载慢
- 存在空间浪费
动态库
动态库本质就是使用官方库里的函数,但是不会对其进行拷贝到本地,具体过程是:代码使用库函数->调用库->库返回调用结果。
这样做的优点就是不用会产生重复拷贝,使得代码占用体积小,内存加载更快,但是依赖第三方库平台不同库里面的内容也会不些小变动这使得移植性较差。
总结:
- 优点
- 内存加载快
- 体积小
- 不存在空间浪费
- 缺点
- 依赖第三方库
- 可移植性较差
gdb调试工具
注意: gcc编译出来的默认是release
版本,这个版本是没有 调试信息的,我们需要手动调整成debug
版本才有调试信息,需要在编译时加上-g
选项才是debug
版本。
- list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
- list/l 函数名:列出某个函数的源代码
- r或run:运行程序
- n 或 next:单条执行
- s或step:进入函数调用
- break(b) 行号:在某一行设置断点
- break 函数名:在某个函数开头设置断点
- info break :查看断点信息。
- fifinish:执行到当前函数返回,然后挺下来等待命令
- print§:打印表达式的值,通过表达式可以修改变量的值或者调用函数
- p 变量:打印变量值。
- set var:修改变量的值
- continue(或c):从当前位置开始连续而非单步执行程序
- run(或r):从开始连续而非单步执行程序
- delete breakpoints:删除所有断点
- delete breakpoints n:删除序号为n的断点
- disable breakpoints:禁用断点
- enable breakpoints:启用断点
- info(或i) breakpoints:参看当前设置了哪些断点
- display 变量名:跟踪查看一个变量,每次停下来都显示它的值
- undisplay:取消对先前设置的那些变量的跟踪
- until X行号:跳至X行
- breaktrace(或bt):查看各级函数调用及参数
- info(i) locals:查看当前栈帧局部变量的值
- quit:退出gdb
makefile自动化编译工具
makefile自动化工具能使我们减少编译时要敲的代码,同时会不会用makefile也是考察你是否具有大型项目编程的能力,因为在LInux下大型项目有上百个obj文件,如果手打的话你可以想象一下效率有多低,其次如果除了bug调试的时候这样又打一遍岂不是折磨?
所以我们有必要掌握makefile这款自动化编译工具,有了它我们开发效率会比没有使用它更快,特别是当做大项目的时候有明显的差距。
make指令
语法: make
功能: 用于执行makefile
的内容,使用make前必须有个makefile
不然无法使用。
makefile的语法
使用makefile必须明白依赖关系和依赖方法,什么是依赖关系呢?依赖关系就好比你使用某个库的函数你必须包含这个库的头文件,这就是依赖关系那么依赖方法呢?
依赖方法也很简单可以理解成调用库函数的具体操作,在Linux下以上操作都是类似的。
具体操作我们先创建一个makefile文件,接着在里面写上如下指令:
这些已经可以完成绝大多数场景的使用了,暂时先讲到这,后续的文章会补充这个工具的其它操作。
\r&\n
回车和换行是区别是什么?
你可能会说这两个不是同一个东西吗?能有啥区别不都是换行?
如果从细的讲这两个东西就不是同一个东西,因为换行是在当前行往下换,但是它的位置是不会动,也就是说在你上一行的字符下面,而不是跑到行开头。
而回车则是先换行然后再跑到行首,这就是区别那么我们说这个有啥意义呢?
当然有,我们先看一段程序。
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello Linux");
sleep(1);
return 0;
}
你们觉得是先输出再休眠还是先休眠再输出呢?
答案:其实是先休眠再输出,但是加了\n
就是先输出再休眠了,你们可能会好奇这是为什么呢?这其实是一种缓冲造成的结果。
缓冲区
一般缓冲区有三种缓冲策略分别是:无缓冲、行缓冲和全缓冲,我们当前代码所造成的情况是行缓冲。
-
无缓冲
立即刷星输出到显示器上的内容
-
行缓冲
缓冲区满了或遇到
\n
才立即刷新 -
全缓冲
缓冲区满了才刷新。
而\n
和\r
的区别在下面代码也就体现出来了,如下:
#include <stdio.h>
#include <unistd.h>
int main()
{
int i = 10;
while(i){
printf("%2d\r", i);
fflush(stdout);//使缓冲区立即刷新到屏幕
sleep(1);
i--;
}
}
我们用\r
就会发现可以获得一个倒计时的程序,如果用换行我们就会发现不能实现倒计时。