Linux的发展史
1970年:UNIX 采用汇编语言编写(不能移植) AT&T && MIT
1973年:C语言---》重写
1979年:---》收费
1983年:RMS ---》GNU计划---》开发出一套兼容UNIX的类UNIX系统(操作系统:GUN/Hurd),
自由软件基金会协助该计划的实施,让律师起草一个GPL的协议。
1989年:编写完毕GNU/Hurd操作系统相关的软件:gcc make...... 但是Hurd未实现。
1991年:Linus ---》 编写磁盘驱动程序+文件系统,形成内核雏形,并通过GPL协议加入GNU计划,最终系统更名为:GNU/Linux。
Linux的发行版本
商业组织维护的发行版本:
RHEL :(RedHat EnterPrice Linux),收费且稳定,适合作为研发搭建的大型服务器
Fedora:社区版的Redhat发展而来,免费,稳定性稍差,适合作为桌面服务器
CentOS:RHEL的克隆版本,免费,稳定性稍差,适合作为桌面服务器
社区组织维护的发型版本:
Debian:社区类Linux系统的典范,最遵循GNU计划(通过GPL协议)---》特点:包管理方式(软件包的安装以及压缩打包。。。。。)
Ubuntu:继承于Debian,又添加自己独有的一些机制(通配符,上下键翻阅历史命令以及操作,Tab自动补全。。。。)
Linux的体系结构
内核:核心组件,负责管理操作系统的执行。
进程管理,内存管理,网络管理,文件系统管理,设备驱动管理
shell:本质是一个命令行解释器,起到中间桥梁的作用,负责接收用户输入的命令,并简化其翻译提交给内核,让内核做出回应。
文件系统:
数据在设备或者分区上组织文件的一种方法(数据结构)。
分为:
磁盘文件系统(U盘),虚拟文件系统(隐藏了跨文件系统类型数据传输的细节,调用者只需要使用统一的接口,即可完成不同文件系统类型的之间的数据交互。),网络文件系统(进程间网络通信时,数据的接收以及转发)。
实用程序:每一个独立的系统,都会配备自己专属的一套程序:编辑器,编译器,浏览器,办公套件,数据库。。。。
Linux的软件包管理
软件包的命名方式图解:
目的:学会下载软件
方式1:离线安装
没有网络,首先本地必须存在待于安装的包文件,其次软件包之间的依赖关系需要自己建立,所以不建议使用(特殊情况)
方式2:在线安装
---》条件:有网络
检测Ubuntu系统是否有网络?
---》ping www.baidu.com
如何检查虚拟机的IP地址?
---》ifconfig
工具:APT
思路:
1、在工程总目录下,创建tags文件,目的是将工程中所有的文件进行关联
代码为:命令行输入--》ctags -R (-R代表递归关联)
2、在含有tags文件的路径下打开一个文件,比如:vim ./include/stu.h
3、在需要跳转的位置,比如经常在函数声明的位置,输入 ctrl }这个组合键,即可跳转至该函数的实现文件处
4、阅读完毕代码之后,通过ctrl t 组合键实现返回上一次跳转的位置。
如何设置一个固定的IP地址?
关心4个参数:IP地址(192.168.0.num) , 子网掩码(255.255.255.0) , 网关(192.168.0.1), DNS服务器(8.8.8.8 / 8.8.4.4)
Linux的网络基础
IP地址:
IP:Internet Protocol ---->网络协议,在通信中起到路由的功能
IP地址的形式:由点分十进制的数字组合而成,总共占4给字节(32位二进制数据):eg:192.168.0.89
IP地址的组成:网络地址(高位) + 主机地址(低位)
IP地址类型:因为网络地址和主机地址所占字节数的不同,可以划分为:A类 B类 C类 D类 E类
IP地址5种类型的划分,按照网络地址和主机地址所占的比例:
A类IP:网络地址占1个字节,主机地址占3个字节,并且规定网络地址的最高位是0
范围:0.0.0.0 ~ 127.255.255.255
注意:
0.0.0.0为任意地址,用户不会获得,网络地址会从1开始,主机地址也是从1开始分配给用户,127开头的IP地址都是本地环回地址,用户无网络时进程间通信,以255结尾的IP地址都是广播地址,用户也不会被分配到,因此,用户在A类IP范围中,可以获取的有效IP地址范围为:1.0.0.1 ~ 126.255.255.254
B类IP:网络地址占2个字节,主机地址占2个字节,并且规定网络地址的最高位是10
C类IP:网络地址占3个字节,主机地址占1个字节,并且规定网络地址的最高位是110
范围:192.0.0.1 ~ 223.255.255.254 (优化之后的有效IP地址范围)
D类IP:目前用于组播实现比较多
E类IP:目前处于保留,等待将来使用
子网掩码:
作用:判断当前两台主机之间的通信是外网通信还是内网通信
方法:
A:192.168.0.199 ---》子网掩码:255.255.255.0
B:192.168.2.188 ---》子网掩码:255.255.0.0
假如A想给B发消息:把A和B的IP地址均和A的子网掩码进行相与,查看网段是否一致,如果一致则代表可以直接通信即内网通信,否则需要外网通信(借助网关)。
假如B想给发消息:把A和B的IP地址均和B的子网掩码进行相与,查看网段是否一致,如果一致则代表可以直接通信即内网通信,否则需要外网通信(借助网关)。
网关:
作用:由一台主机通往另一台主机的IP地址(针对外网通信的时候)
网关可以有多个,但是一般会有一个默认网关:C类--》192.168.X.1 (X是网段号)
DNS服务器:
域名解析服务器,存储的是域名和IP的对应关系,当用户访问域名的时候,就会查询DNS服务器上的表,进而找到域名对应的IP地址。
eg:
ping www.baidu.com --->最终还是借助于DNS服务器:8.8.8.8 / 8.8.4.4 来查找www.baidu.com对应的IP地址
如果没有DNS服务器,就不识别域名,会报Unknown host。。。。
Linux下的shell命令
命令的学习:三要素
命令名称 [选项] [参数];
总结:
- 命令名称不能省略
- 选项和参数是可选的(可有可无可多个)
- 不管是命令,还是代码在同一行写不完时,需要先输入空格,在输入反斜杠,再按下回车即可在下一行进行书写。
- 将多个命令书写在一起时,多个命令之间需要通过分号来隔开。
- 用户切换命令
su:切换用户状态的命令
方式:
方式1:su 用户名:将用户身份切换至指定的用户状态,此时所在路径和切换之前的用户位置一样。
方式2:su - 用户名:将用户身份切换至指定的用户状态的同时,也将用户之前所在的路径切换至指定用户的家目录。
- 用户管理命令
2-1:修改密码
格式:
sudo passwd 用户名
注意:
输入:passwd也可修改密码,但是默认修改当前用户的密码(密码只能越来越长!,所以不建议,还是记住sudo passwd 用户名这个通用的公式即可。)
2-2:创建新用户
格式:
sudo adduser 新用户名
2-3:删除用户
格式:
sudo deluser 用户名
注意:想要彻底删除用户的时候,添加--remove-home这个选项即可。
常见的shell命令
env:打印环境变量以及变量对应值的命令,环境变量的值为多个时,以冒号隔开。
echo:标准输出命令,功能类似于Printf
用法:
方式1:打印指定的一个字符串
方式2:打印变量的值(注意:通过$符号完成对变量值的获取)
总结:不管是方式1还是方式2,通过echo 输出的时候,均需要书写””引起来就不会出错。
ln:创建链接文件的命令
链接文件的分类:
软链接:称为符号链接文件,以源文件的所在路径创建的一个文件,意味着软链接文件存储的是指向源文件的一条路径,类似于Windows下的快捷方式。
创建方式:
ln -s 源文件(带绝对路径) 软链接文件
硬链接:以物理编号inode编号创建的文件,意味着:
方式:
ln 源文件(相对/绝对路径) 硬链接文件
注意:源文件的写法,可以不加绝对路径,因为和路径没关系。只是源文件的一个别名。
对于软链接和硬链接文件的总结:
软链接:
- 源文件和软链接是两块空间,并且软链接文件存储的是指向源文件的一条路径
- 源文件和软链接的影响是双向的。
- 创建软链接文件时,源文件建议写成绝对路径的方式,可以提高软链接文件的移植性。
- 当删除源文件时,软链接立马失效,当恢复(创建一个与之前源文件同名的新文件)源文件时,此时软链接文件会生效,但是此时指向的是最新的文件。
硬链接:
- 源文件和硬链接是同一片空间,可以理解为硬链接是源文件那片空间的一个别名而已。
- 源文件和硬链接的影响是双向的。
- 创建硬链接文件时,源文件以相对路径或者绝对路径都可以,不依赖路径而存在。
- 当删除源文件时,硬链接不受影响,可以理解为那片空间的名字少了一个,此时依旧可以通过硬链接来打开之前源文件的空间并进行操作。(可以当做备份或者误删来使用)。
注意:如何确保两个文件是否为同一个文件?
-----》打印分配给每一个文件物理编号inode号来查看---》ls -i 即可打印出编号。
chmod:对于文件的文权限进行更改
创建新文件的初始权限是:rw- rw- r-- ---》0664,如果需要对该文件的 权限进行升级或者降级时,就需要通过chmod来做。
假设:文件为:test.c --->初始权限:0664
方式1: 八进制法
chmod 0774 test.c / chmod 774 test.c
方式2:符号标记法
用户:u
用户组:g
其他用户:o
所有用户:a
chmod u+x test.c
chmod u-x test.c
chmod a+x test.c
chmod +x test.c (等价于a + x)
tar:来实现打包相关的命令
选项:
-c:打包
-x:解包
-v:可视化(可以看到打包,压缩,解包,解压的过程)
-z:可以调用压缩工具为gzip
-j:可以调用压缩工具为bzip2
-f:可以指明需要打包压缩的文件名
注意: -C 代表可以指定解包或者解压之后的位置,如果不写,则默认解包或者解压到当前用户工作位置。
grep :查找对象是文件中内容,在一个文件中去匹配指定的格式,匹配搜索指定的格式(文件中)
格式:
grep 选项 格式 路径
解释:
选项:
-c:匹配包含指定格式所在行的行数
-n:匹配包含指定格式所在行
-v:匹配除了包含指定格式所在行的其他行
find:查找,查找对象是文件
格式:
find 路径 选项 描述
解释:
-name:代表需要查找指定文件名
wc:统计文件的大小,单词数,以及文件的行数
shell特殊字符
4-1:通配符
* :匹配任意长度的内容。---》最为常用。
?:匹配含有一个长度的内容
[范围]:匹配含有范围之内的一个长度的内容
[指定范围]:匹配含有指定范围之内的一个长度的内容
[^指定范围]:匹配除了指定范围之外的任何一个长度的内容
管道
格式:
command1 | command2 | ..... | commandN
理解:
将前一个命令的输出作为后一个命令的输入
补充:xargs 命令---》会具备转换功能(将输出格式化为一行,作为参数赋值给下一个命令)
命令置换
格式:
Command1 ` Command2`
理解:将Command2的输出作为Command1命令的参数
思考:管道和命令置换有啥区别?
---》理解:
管道是将输出作为输入,等价于将输出作为文本流,所以接下来的操作就会直接对该文本流进行操作
命令置换将输出作为参数,等价于在接下来操作中会进入参数所代表的文件里面去操作。
重定向
概念:重新定义输出或者输入的方向为自己指定的
输入重定向:之前对于输入,默认的方向为键盘,现在可以将默认的输入方向即从键盘获取输入源改变到从比如文件中去获取一个输入源。
eg: cat:查看指定文件的内容
cat 1.c ---》 cat < 1.c ( <可以省略不写 )
输出重定向:之前对于输出,默认的方向为终端,现在可以将默认的输出方向从向终端输出改变到向比如一个文件中去输出。
情况讨论:
>:重定向到的文件不存在时,新建并打开并存储,反之则直接先清空之前内容,再打开并存储,但是只能接收正确命令的结果。
>>:重定向到的文件不存在时,新建并打开并存储,反之以追加模式打开文件并存储,但是只能接收正确命令的结果。
- :
重定向到的文件不存在时,新建并打开并存储,反之则直接先清空之前内容,再打开并存储,但是只能接收错误命令的结果。
2>>:
重定向到的文件不存在时,新建并打开并存储,反之以追加模式打开文件并存储,但是只能接收错误命令的结果。
&>:
重定向到的文件不存在时,新建并打开并存储,反之先清空之前内容,再打开并存储,不论正确输出或者错误的结果均可接收并存储。
&>>:
重定向到的文件不存在时,新建并打开并存储,反之以追加模式打开文件并存储,不论正确输出或者错误的结果均可接收并存储。
Linux下的shell编程
- 脚本的理解
脚本也是由一系列命令组合起来,并且加入了一定的控制结构之后所形成的文本,就称之为脚本,优点是可以自动且重复的去执行某件事情,比如:开机或者关机之前以及之后可以自动的去执行一部分代码,因为脚本也是多条shell命令的有序结合,因此在终端上能够完成的事情全部可以使用脚本来完成(重复使用)。
当执行脚本的时候,shell这个解释器就会逐行去翻译命令,并将结果提交给内核,内核接收到结果之后,就会去驱动硬件进行响应。
因此:脚本就是一门解释型的语言,本质是多条shell命令的有序集合(可能会加入一定量的控制结构语句)。
总结:
shell命令:理解为用户发送给内核一种信号(该信号是由shell来完成解释)
shell:命令行解释器(专门负责将用户输入的命令或者语句翻译给内核)
shell脚本:多条shell命令的有序集合(可能会引入一些控制结构语句)
- 脚本的编写格式
第一步:顶格书写:#!/bin/bash ----》交代即将书写完毕的脚本由谁完成解释工作。
第二步:按照shell规定的语法进行编码即可。
- 脚本的编程步骤
第一步:新建一个后缀为.sh的文件(和之前C文件一样)
第二步:修改文件的权限(chmod 来修改文件的权限为可执行,至少自己具备可执行权限)
第三步:直接执行(./可执行文件名字 运行即可)
- 脚本的语法
对于变量的定义:脚本中的数据类型称为“弱类型”,意味着没有数据类型的区分。
4-1:自定义变量
方法:
变量名;----》建议大写
赋值:
变量名=值;---》等号前后不能有空格。
引用:
${变量名} / $变量名(存在风险:如果变量名和之后的字符串紧挨着时,会被视为一个新的变量名);
建议:引用变量值时,以{}的形式引用比较安全。
4-2:位置变量
理解为:变量的值可以从命令行传入
我们怎样使用传入进来的数值?---》$和数字进行结合:$N (N 是数字,从0开始)
4-3:系统预定义变量
系统之前规定将$符号和指定的另外一个字母两者相结合,之后具备一定的含义。
$#:统计命令行参数的个数(有效参数的个数--》不包含可执行文件的名字)
$@:统计传入的参数本身(有效参数)
$*:统计传入的参数本身(有效参数)
$?:获取上一条命令的退出状态:状态数值不是0就是1(0代表上一条命令时成功执行,反之为失败执行)
环境变量
---》查看系统中的所有环境变量的命令:env
操作:
添加新环境变量:
export 变量名=值 (可以一次性赋值多个,多个数值之间以冒号隔开)
修改环境变量值:
export 变量名=新值:${变量名} / export 变量名=${变量名} :新值
清除环境变量:
unset 变量名
- 脚本的语句
5-0:说明性语句
凡是以#开头的语句都是说明性语句,可以理解为注释。
5-1:功能性语句
- 动态获取变量的值
命令:read --->功能类似于scanf函数的功能
方式:
read 变量名1 变量名2 。。。 变量名 (定义变量且赋初值)
提示语句的写法:
- 方式1:通过echo “提示语句”
- 方式2:使用read的同时去打印:read -p “提示语句” 变量名
- 通配符的转义
软转义:
双引号 和 不加双引号 ---》软转义(会保留shell特殊字符的含义)
eg:
在打印输出的时,遇到${变量名}时,会先执行${变量名},访问到数值之后再去输出。还有遇到命令的时候,也会先执行命令,将命令执行之后的结果再去输出。
总结:
双引号和不加双引号在多数情况下,两者没啥区别,但是又不完全等价。
具体区别有两种情况:
情况1:含有多个空格
比如:
echo “wangjia jia”; --->原样输出
echo wangjia jia; ---》wangjia jia (中间只会有一个空格,将其他空格全都抹掉)
情况2:在含有\
综上所述:在以后输出时,建议都加上双引号,结果一定符合预期数值。
硬转义:
单引号 和 \ ---》硬转义(会屏蔽掉shell特殊字符含义)
eg:
在打印输出时,遇到${变量名}或者命令时,不会去执行${变量名}取到数值或者执行命令,反而将它们视为一个字符串去直接输出。
- expr算术运算命令
功能: + - * / %
方式:
expr 变量名1 运算符 变量名2
总结:
expr和变量名之间至少保留1个空格,运算符和两个变量名之间也要存在空格。
- 测试命令test
测试命令---->代替判断语句
测试格式:
第一种: [ 对象1 测试条件 对象2 ]
第二种: test 对象1 测试条件 对象2
测试对象:
- 整形:测试对象假设为:num1 num2
等于: num1 -eq num2
不等于:num1 -ne num2
大于: num1 -gt num2
大于等于:num1 -ge num2
小于: num1 -lt num2
小于等于: num1 -le num2
等于:equal 不等于:not equal
大于:greater than 大于等于 :greater than equal
小于:less than 小于等于:less than equal
- 字符串:测试对象假设为:str1 str2
等于: str1 = str2 (空格必须有,否则被视为变量赋值)
不等于:str1 != str2
字符串长度为0: -z str1/str2
字符串长度不为0:-n str1/str2
- 文件属性:假设测试对象为:f1 f2
-f :测试对象是否存在且为普通文件
-d :测试对象是否存在且为目录文件
-L :测试对象是否存在且为软链接文件(符号链接文件)
-r:测试对象是否存在且具备可读权限
-w:测试对象是否存在且具备可写权限
-x:测试对象是否存在且具备可执行权限
-s:测试对象的大小
f1 -nt f2:测试f1是否比f2更新(文件最后一次保存的时间)
f1 -ot f2:测试f1是否比f2更旧(文件最后一次保存的时间)
结构性语句
- 顺序结构
- 选择结构
多路分支:
if:
形式参考如下:
if 测试语句
then
命令表
elif 测试语句
then
命令表
。。。
else
命令表
fi
case:
形式参考如下:
case 变量值 in
模式1)
命令表
;;
模式2)
命令表
;;
...
*)
命令表
esac
注意:
在脚本中:与使用-a表示,或使用-o表示,非使用!表示
- 循环结构
for while
C中:
Int i = 0;
for(;表达式2;表达式3)
{
循环体
}
脚本中的for循环:
形式1:带参数列表
for 变量名 in 单词列表
do
命令表
done
- 脚本的函数
函数定义格式:
function_name()
{
命令表1
命令表2
。。。
命令表N
}
如何调用这个函数:
方式两种:
方式1: 变量名 =` function_name 参数1 参数2 。。。。`
---》查看变量名的值来获取函数调用的输出信息
方式2:function_name 参数1 参数2 。。。。。。
---》查看函数的执行结果通过打印$?
如何在子函数内部访问实参?
通过$N这样的结合访问(N是数字)
注意:
1、shell函数中的返回值范围是0-255之间,超过255从0开始重新取值(环回),但是子函数内部没有限制。
2、对于实参,可以通过位置变量来进行传参。---》$N来访问传递给实参的数值