1. 尝试基于gcc命令说明 c语言编译过程。
gcc编译可以执行的程序为4步: 1.预处理——2.编译——3.汇编——4.链接
gcc -E hello.c -o hello.i @对文件进行预处理
gcc -S hello.c -i hello.s @对文件只进行预处理和编译
gcc -C hello.c -o hello.o @对文件只进行预处理、编译和汇编
gcc hello.o -o hello @指定生成的输出文件为,可执行文件
预处理:宏定义展开、头文件展开、条件编译等,同时将代码中的注释删除,这里并不会检查语法
编译:检查语法,将预处理后文件编译生成汇编文件
汇编:将汇编文件生成目标文件(二进制文件)
链接:C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中去
c语言编译过程主要使用./configure 脚本来去给生成makefile文件主要分为 3步:1.安装路径 2.启用特性 3.生成makefile文件
--prefix=/usr/ @指定配置文件的安装路径
--sysconfdir=/etc/ @指定软件的安装路径
--disable、enable @关闭/打开可选特性
--with|without-PACKAGE @使用/禁用依赖包
编译完成过后通过make(make -j 2)对文件进行依赖性检查,构建依赖性应用程序
最后通过make install 将文件复制到指定目录
2. 总结程序包管理器有哪些,以及包中包含什么内容的文件,尝试这些文件如何获取命令获取? yum/dnf/apt
程序包管理器:
Rocky 系统下使用
rpm:用来管理红帽系列制定的相关软件工具,对已经编译好的软件包进行安装,升级,卸载。
yum/dnf:属于改进型的rpm软件管理器,可以配置多个资源库,同时指定多个”.rpm“包文件进行安装,自动解决rpm软件包依赖文件的问题。
Ubuntu系统下使用
dpkg:Debian系列的包管理工具
apt:作用相当于yum,配置多个资源库,自动解决dpkg包依赖的问题。
#查看包中的内容,以及包中的文件
[root@localhost ~]# rpm -qf `which httpd`
httpd-2.4.37-56.module+el8.8.0+1456+d0a01c5e.7.x86_64
[root@localhost ~]# rpm -ql httpd-2.4.37-56.module+el8.8.0+1456+d0a01c5e.7.x86_64
/etc/httpd/conf
/etc/httpd/conf.d/autoindex.conf
/etc/httpd/conf.d/userdir.conf
/etc/httpd/conf.d/welcome.conf
/etc/httpd/conf.modules.d
/etc/httpd/conf.modules.d/00-base.conf
/etc/httpd/conf.modules.d/00-dav.conf
/etc/httpd/conf.modules.d/00-lua.conf
/etc/httpd/conf.modules.d/00-mpm.conf
/etc/httpd/conf.modules.d/00-optional.conf
/etc/httpd/conf.modules.d/00-proxy.conf
/etc/httpd/conf.modules.d/00-systemd.conf
/etc/httpd/conf.modules.d/01-cgi.conf
/etc/httpd/conf.modules.d/README
/etc/httpd/conf/httpd.conf
/etc/httpd/conf/magic
/etc/httpd/logs
/etc/httpd/modules
······
3. 总结程序包获取途径,以及rpm, yum, apt命令选项示例。
1.Linux官网发行的ios系统光盘
2.第三方组织 EPEL资源库
3.官网提供的镜像服务站
4.国内的软件包等服务站
5.去网上找软件依赖包
rpm、yum、apt命令选项示例:
rpm
-q @查看软件包的版本名字
-a @查找所有包
-f @查找文件由哪个程序包安装生成的
-qi @查看包的详细信息
-ql @查看程序包安装后生成的所有文件
-qa @查询并列出所有装好的包
-qf @查看指定的文件由那个程序包安装生成
-ivh @安装
-e @卸载
-K @检查包的完整性和签名
-U @软件包升级
-F @软件包升级
yum :
list @列出所有可安装的软件包
search @查找软件包
list installed@列出所有已安装的软件包
list updates @列出所有可更新的软件包
-y install @安装软件,不加-y则会询问是否安装
remove @删除、卸载程序
update @更新软件
dpkg :
-i:@安装软件包;
-r:@删除软件包;
-P:@删除软件包的同时删除其配置文件;
-L:@显示于软件包关联的文件;
-l:@显示已安装软件包列表;
apt
purge @移除软件包及配置文件 这个删除的干净
update @刷新储存库索引
upgrade @升级所有可升级的软件包
show @显示安装详细细节
remove@卸载已安装软件
list @生成软件包列表
4. 简要总结yum/dnf工作原理。并搭建私有yum仓库(base, epel源)给另一个虚拟机使用。
yum/dnf 是Linux包管理工具,方便管理对软件包的搜索,安装,升级,删除。
1.首先安装httpd服务 yum -y install httpd
2.将第一台主机的yum配置成国内的yum源
[epel]
name=epel repo
baseurl=https://mirrors.aliyun.com/epel/$releasever/Everything/$basearch
https://mirrors.tuna.tsinghua.edu.cn/epel/$releasever/Everything/$basearch
http://mirrors.cloud.tencent.com/epel/$releaserver/Everything/$basearch
enable=1
3.下载epe源并指定安装目录
sudo mkdir -p /var/www/html/epl
dnf reposync --repoid=epel --download-metadata -p /var/www/html/
4.启动服务
systemctl enable --now httpd
5.当http共享服务器配置成功后把另外一台主机的epel的链接地址指向私有的yum源地址,即可继续使用
[epel]
name=EPEL
baseurl=https://10.0.0.114/epel/
gpgcheck=0
enabled=1
5. 总结系统安装之后的常用初始化步骤。rocky/ubuntu
#!/bin/bash
#关闭防火墙
Disabled_firewalld (){
systemctl disabled --now firewalld
}
#关闭SElinux
Disabled_SElinux (){
sed -i '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config
}
#修改网卡名称
config_neyworek(){
sed -ri '/GRUB_CMDLINE_LINUX=/s#(.*)"$#\1 net.ifnames=0"#' /etc/default/grub
grub2-mkconfig -o /boot/grub2/grub.cfg;reboot
}
#配置yum源
yum_config(){
yum install epel-release
cd /etc/yum.repos.d/
sed -i 's|^#baseurl=https://download.example/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel*
sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel*
}
#自己手动配置yum源
yum2_config(){
touch /etc/yum.repos.d/epel2.repo
cat > /etc/yum.repos.d/epel2.repo <<EOF
[AppStaram]
name=AppStaram
baseurl=file://misc/cd/AppStaram
https://mirrors.aliyun.com/centos/8/AppStream/x86_64/os
https://mirror.tuna.tsinghua.edu.cn
gpgcheck=0
[BaseOS]
name=BaseOS
baseurl=file://misc/cd/BaseOS
https://mirrors.aliyun.com/centos/8/BaseOS/x86_64/os
https://mirrors.tuna.tsinghua.edu.cn/cc/8/BaseOS/x86_64/os
gpgcheck=0
EOF
}
#安装常用软件
install_packages(){
yum -y install bash-completion psmisc lrzsz tree man-pages redhat-lsb-core zip unzip bzip2 wget tcpdump ftp rsync vim lsof
}
#自动挂载光盘
install_autofs(){
yum -y install autofs
systemctl enable --now autofs
}
#同步时间
Time (){
timedatectl set-timezone Asia/Shanghai
}
#实现邮件通信
install_mailx(){
yum -y install mailx
systemctl enable --now postfix
}
6. 解读一键安装httpd脚本,并自行实现一个一键安装脚本,要求
1)基于位置变量传递版本号
2)基于独立函数进行初始化步骤,禁用防火墙,安装开发依赖包。
3)基于独立函数进行下载包,解压包。
4)基于独立函数进行编译,安装包。
5)基于独立函数完成链接包。
6)启动服务,并输出自定义的语句,安装xxx服务
(这个脚本在结尾处有问题,文件总是链接不上,待修改)
#!/bin/bash
#前期准备
#判断当前用户是否为root用户
if [ `whoami` = "root" ];then
echo "当前用户为root状态可进行以下程序"
else
echo "当前不是root用户,请切换到root模式"
su root
fi
#基于位置变量设置版本号
version=2.4.57
#检测当前系统环境
rocky=$(grep -o rocky /etc/os-release | head -n 1)
Ubuntu=$(grep -o Ubuntu /etc/os-release | head -n 1)
mkdir -p /usr/local/install/apr
mkdir -p /usr/local/install/apr-util
mkdir -p /usr/local/install/httpd
mkdir -p /apps/httpd
#设置安装路径
httpds=/apps/httpd
#基于独立函数进行初始化步骤,禁用防火墙,安装开发依赖包
install_software(){
if [ "$rocky" = "rocky" ];then
echo "此服务器为rocky系统,正在关闭防火墙,SElinux,安装开发依赖包"
systemctl disabled --now firewalld
sed -i '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config
yum -y install gcc gcc-c++ make wget apr-devel apr-util-devel openssl-devel pcre-devel redhat-rpm-config cyrus-sasl-devel libdb-devel expat-devel bzip2
elif
[ "$Ubuntu" = "Ubuntu" ];then
echo "此服务器为Ubuntu系统,正在关闭防护墙,安装开发依赖包"
systemctl stop ufw.service
apt update
apt -y install build-essential make wget
fi
}
#基于独立函数进行下载包,安装包
install_download(){
cd /usr/local/src
wget http://archive.apache.org/dist/apr/apr-1.7.2.tar.gz
wget http://archive.apache.org/dist/apr/apr-util-1.6.2.tar.gz
wget https://dlcdn.apache.org/httpd/httpd-${version}.tar.bz2
if [ $? -eq 0 ];then
echo "httpd 下载成功并开始解压"
tar -xvf /usr/local/src/httpd-${version}.tar.bz2
tar -xvf /usr/local/src/apr-1.7.2.tar.gz
tar -xvf /usr/local/src/apr-util-1.6.2.tar.gz
else
echo "httpd 未下载成功,请检查原因"
exit
fi
}
#基于独立函数进行编译,安装包
compile (){
cd /usr/local/src/apr-1.7.2/
./configure --prefix=/usr/local/install/apr
make -j 1 && make install
cd /usr/local/src/apr-util-1.6.2/
./configure --prefix=/usr/local/install/apr-util/ --with-apr=/usr/local/install/apr
make -j 1 && make install
cd /usr/local/src/httpd-${version}
./configure --prefix=/apps/httpd/ --with-apr=/usr/local/install/apr/ --with-apr-util=/usr/local/install/apr-util/ --enable-so --enable-ssl --enable-deflate=shared --enable-expires=shared --enable-rewrite=shared --enable-static-support
make -j 1 && make install
if [ $? -eq 0 ];then
echo "安装成功"
else
echo “未安装成功”
exit
fi
}
#基于独立函数完成连接包
link(){
echo 'PATH=/apps/httpd/bin:$PATH' > /etc/profile.d/httpd.apps
ln -s /apps/httpd/bin/apachectl /usr/local/bin/
}
#启动服务,并输出自定义的语句
sys_ctl(){
apachectl start
systemctl enable package && echo "安装成功!"
}
install_software
install_download
compile
link
sys_ctl
7. 总结开放系统互联OSI模型,每层作用及对应的协议。
8. 调整动态端口范围为20000-60000
vim /etc/sysctl.conf
在文件末端下行添加:
net.ipv4.ip_local_port_range = 20000 60000
保存文件
执行以下命令,使用修改生效
sysctl -p
9. 总结TCP包头结构,TCP三次握手,4次挥手。
源端口(Source Port):16位,表示发送端口号。
目的端口(Destination Port):16位,表示接收端口号。
序列号(Sequence Number):32位,表示本次数据拆分好的包,一个一个发送过去的序列号。
确认号(Acknowledgment Number):32位,表示收到数据包确认序列号后,并期望收到下一个报文段的第一个字节的序列号。
首部长度(Header Length):4位,表示TCP头部长度(单位为4字节),最大值为60,因此TCP最多可以有40个字节的选项。
保留(Reserved):6位,保留字段。
标志位(Flags):6位,SYN、ACK、FIN、RST、PSH和URG标识TCP连接状态和数据传输方式。
窗口大小(Window Size):16位,表示接收方窗口的大小,用于流量控制。
校验和(Checksum):16位,检测TCP头部和数据的完整性。
紧急指针(Urgent Pointer):16位,表示紧急数据偏移量,该字段与URG标志一起使用,用于紧急数据传输。
选项(Options):可变长度,包含各类TCP选项字段。
TCP三次握手,其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包,来去确认双方的接收能力和发送能力是否都正常,为指定自己的初始化序列号后的可靠性进行传输。
第一次握手:建立连接时,客户端发送SYN包(SYN=J)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器SYN包,必须确认客户的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN =k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(SYN
=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
4次挥手指即将中断的TCP链接,当TCP要去断开连接时需要客户端还有服务器端总共发送四个包进行确认链接。
第一次挥手:客户端发送一个FIN,用来关闭客户端与服务器端的数据传送,客户段进入FIN_WAIT_1状态。
第二次挥手:服务器端收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务器进入CLOSE_WAIT状态。
第三次挥手:服务器端发送一个FIN,用来关闭服务器端到客户端的数据传送,服务器端进入LAST_ACK状态。
第四次挥手:客户端收到FIN后,客户端进入TIME_WAIT状态,接着发送一个ACK给服务器端,确认序号为收到序号+1,服务器端口进入CLOSED状态,完成四次挥手。
10. 总结主机到主机的包传递过程。
首先两台主机,都要确认在一个网段上。
1.应用层:主机写好的数据,发送端应用程序将对数据封装为应用层的报文,并指定要使用的传输层协议(例如HTTP、HTTPS等)
2.传输层:操作系统利用指定的传输层协议(TCP或UDP协议),将应用层的报文进行重组和分段,变成传输层的报文段,并添加传输层的信息,例如源IP地址,目标IP地址,端口号,序列号等。
3.网络层:根据操作系统的IP目标地址选择合适的网络路径和下一个路由器,将传输层的报文封装成网络层数据包。
4.数据链路层:系统再次把网络层数据包封装成数据链接包,并添加源MAC地址,目标MAC地址等信息。通过网络接口传输到目标主机。
5.物理层:数据连接通过物理层,也就是硬件设备进行传输,例如网线,网卡。
6.接收端:收到目标主机的报文后,将数据包解封成网络层。并将目标地址IP和路由器选择,数据包转给传输层。
7.传输层:收到传输层的报文段后进行重组,还原成应用层,之后交与其他应用使用。
11. 总结IP地址 A, B, C, D 类,并解析IP地址的组成
A类:
也就是IP地址前8位,表示网络ID,后24位标识主机ID。A地址用来表示网络的ID的第一位必须以0开始,其他7位,则可以是任意数值。其他7位是0则代表网络ID是最小,即为0,也就是全部都是0。当其他的7位是1是,代表网络ID最大,即为127。网络的ID不能为0,因为它有特殊用途,所以最小ID为1,网络ID也不能为127,因为网络作为回路测试用,所以有效的网络ID范围是1-126.每个网络包含224-2(224减2)台主机。
(01111111)
B类
B类地址用IP地址前16位表示网络ID,用IP地址后16位表示主机ID。B类地址用来表示网络ID的前两位必须以10开始,其他14位可以是任 意值,当其他14位全为0是网络ID最小,即为128;当其他14位全为1时网络ID最大,第一个字节数最大,即为191。B类IP地址第一个字节的有效 范围为128-191,共16384个B类网络;每个B类网络可以包含216-2台主机(即65534台主机)。
(1011111111111111)
C类
C类地址用IP地址前24位表示网络ID,用IP地址后8位表示主机ID。C类地址用来表示网络ID的前三位必须以110开始,其他22位可以是任 意值,当其他22位全为0是网络ID最小,IP地址的第一个字节为192;当其他22位全为1时网络ID最大,第一个字节数最大,即为223。C类IP地 址第一个字节的有效范围为192-223,共2097152个C类网络;每个C类网络可以包含28-2台主机(即254台主机)。
(1101111111111111111111111)
D类
D类地址用来多播使用,没有网络ID和主机ID之分,D类IP地址的第一个字节前四位必须以1110开始,其他28位可以是任何值,则D类IP地址的有效范围为224.0.0.0到239.255.255.255。
(11101111111111111111111111111111)
A类默认子掩码:255.0.0.0
B类默认子掩码:255.255.0.0
C类默认子掩码:255.255.255.0
IP地址的组成:
IPv4地址由32个二进制位组成,通常用4个十进制数表示。例如,“192.168.1.1”就是一个IPv4地址,它由4段,每段8位二进制组成。其中,“192”代表网络号,后3段(“168”、“1”、“1”)代表主机号。在IP地址中,网络号和主机号的划分是由子网掩码进行的。
IPv6地址由于长度为128位,因此通常采用16进制表示。一个IPv6地址,它由8个16位的块组成,每个块之间用冒号分隔。IPv6地址中,前面的部分代表网络号和子网号,后面的部分代表主机号。子网掩码的作用和IPv4一样,用来划分网络号和主机号。
IP中二进制的对应表:
00000000 0
10000000 128
11000000 192
11100000 224
11110000 240
11111000 248
11111100 252
11111110 254
11111111 255
12. 201.222.200.111/18计算主机数?子网掩码?说明计算方法。
计算公式:
网络数=2^可变网络ID位数
主机个数=2^主机位数 - 2
网络ID=IP和子网掩码的与运算
划分子网个数:网络ID向主机位借位,借N个主机位,则划分2^N个子网
计算主机数的方法也就是IP地址的总数减去网络地址的位数,同时再减去广播地址和网络地址的主机数:
2^(32-18)-2=16382
子网掩码:
先去确认首段IP属于哪类IP,通过确认好类别的IP选择出子掩码的默认值,两个数值同时转换为二进制,之后进行与运算
结果为:
11111111.11111111.11000000.00000000
255.255.192.0
13. 当A(10.0.1.1/16)与B(10.0.2.2/24)通信,A如何判断是否在同一个网段?A和B能否通信?
将A的IP地址子掩码进行二进制的转换,与B的IP地址和子掩码进行转换完成的二进制相比较,双方的首IP都在一个10.0.0.0的网络上,且二进制转换数值相同,A是可以B数据包,但是B不会回复,因为B判断,A与B不在同一个网段上,所以B发送信息交由路由器转达。
14. 如何将10.0.0.0/8划分32个子网?求每个子网的掩码,主机数。
10.0.0.0的子网掩码是:
255.0.0.0
11111111.00000000.00000000.00000000
从该网络中分出32个子网,需要向主机位借为作为额外的网络位:
32 = 2^5
则每个子网的掩码是:
11111111.11111000.00000000.00000000
即:255.248.0.0
其中主机的个数为:2^(32-8-5)-2=524,286
15. 通过网络配置命令,让主机可以上网。 ip, netmask, gateway, dns,主机名。相关命令总结,最终可以通过这些配置让你的主机上网。
配置IP地址和子掩码使用ip addr add 可以为网络添加一个ip地址,并使用ip link set启用网卡接口
ip addr add 192.168.1.2/24 dev eth0
ip link set eth0 up
或者使用ifconfig命令设置
ifconfig eth0 192.168.1.2 netmask 255.255.255.0
网卡生效命令
nmcli connection reload
nmcli connection up eth0
配置默认网关使用 ip route add命令可以配置默认网关
ip route add default via 192.168.1.1
配置DNS服务器
echo "nameserver 225.255.255.0" > /etc/resolv.conf
配置主机名
hostnamectl set-hostname Rocky
16. 解析/etc/sysconfig/network-scripts/ifcfg-eth0配置格式。
TYPE=Ethernet
BOOTPROTO=static
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=192.168.1.2
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
DNS1=223.5.5.5
DNS2=223.6.6.6
TYPE:网络接口类型,一般设置为Ethernet
BOOTPROTO:启用的协议类型,可设置为static(静态IP)或dhcp(动态获取IP)
NAME:网络接口名称
DEVICE:网络接口设备名称
ONBOOT:开机是否启用该网络接口,yes表示启用
IPADDR:网络接口IP地址
NETMASK:子网掩码
GATEWAY:默认网关
DNS1:首选DNS服务器
DNS2:备选DNS服务器
17. 基于配置文件或命令完成bond0配置
#配置bond0网卡
Bond0(){
/etc/sysconfig/network-scripts/ifcfg-bond0
NAME=bond0
TYPE=bond
DEVICE=bond0
IPADDR=10.0.0.100
prefix=8
#miimon指定链路监测时间间隔。如果miimon=100,那么系统每100ms检测一次链路连接状态,如果有一条线路不通就转入另一条线路
BONDING_OPTS="mode=1 miion=100 fail_over_mac=1"
/etc/sysconfig/network-scripts/ifcfg-eth0
NAME=eth0
DEVICE=eth0
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
ONBOOT=yes
/etc/sysconfig/network-scripts/ifcfg-eth1
NAME=eth1
DEVICE=eth1
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
ONBOOT=yes
}
18. 通过ifconfig命令结果找到ip地址.
[root@localhost ~]# ifconfig ens160 | grep 'netmas' | awk '{print $2}'
192.168.50.5
19. 使用脚本判断 你主机所在网络内在线的主机IP有哪些? ping通则在线。
NET=10.0.0 #本地网络号
cat /dev/null > hosts.txt
for i in {1..254};do
if ping -c1 -W1 $NET.$i &> /dev/null ;then #ping一次持续一秒
echo $NET.$i is up | tee -a hosts.txt
fi
done
20. 使用while read line和/etc/passwd,计算用户id总和。
#!/bin/env bash
# 初始化用户ID和总和变量
uid=0
sum=0
while read line; do
# 从 /etc/passwd 文件中提取用户ID
uid=$(echo "$line" | cut -d':' -f3)
# 将用户ID添加到总和中
sum=$((sum + uid))
done < /etc/passwd
# 输出ID总和
echo "用户ID总和为:$sum"