1. 尝试基于gcc命令说明 c语言编译过程。
程序的编译安装过程:源代码–预处理–编译–汇编–链接–执行
相应的gcc编译过程如下:
#逐步执行
gcc -E hello.c -o hello.i #对原程序文件进行预处理
gcc -S hello.c -o hello.s #对预处理文件编译
gcc -c hello.s -o hello.o #对汇编文件进行编译
gcc hello.o -o hello #对目标文件进行链接,生成可执行文件
#一步完成编译
gcc hello.c -o hello
C语言编译过程主要分三大步:
- configure 主要作用是设置安装路径,启动特性,依赖检查。最终生成makefile
./configure [options]
--prefix=/PATH #指定程序的安装路径,默认为/usr/local
--sysconfdir=/PATH #指定配置文件的安装位置
--disable|enable-FEATURE #关闭/打开相关特性
--with|without-PACKAGE #使用/禁用依赖包
- make 根据make file构建应用程序
- make install 复制文件到相应路径
2. 总结程序包管理器有哪些,以及包中包含什么内容的文件,尝试这些文件如何获取命令获取? yum/dnf/apt
程序包管理器:
- rpm,红帽系列系统的包管理工具,对预编译的软件包进行管理(安装,升级,卸载)
- dpkg,Debian系列的包管理工具
- yum/dnf 解决rpm包依赖关系
- apt 解决dpkg包依赖关系
查看包中内容
#查看某个文件是由哪个程序包提供的
[root@rocky87 ~]# rpm -qf `which ssh`
openssh-clients-8.0p1-17.el8_7.x86_64
#查看程序包中包含的文件
[root@rocky87 ~]# rpm -ql openssh-clients-8.0p1-17.el8_7.x86_64
/etc/ssh/ssh_config
/etc/ssh/ssh_config.d
/etc/ssh/ssh_config.d/05-redhat.conf
/usr/bin/scp
/usr/bin/sftp
/usr/bin/ssh
/usr/bin/ssh-add
/usr/bin/ssh-agent
/usr/bin/ssh-copy-id
/usr/bin/ssh-keyscan
/usr/lib/.build-id
/usr/lib/.build-id/12
/usr/lib/.build-id/12/c18367260b1e7951e369943602256bcd374c32
/usr/lib/.build-id/18
/usr/lib/.build-id/18/647669fd7f7736df61689b93ffcc3c810c1871
/usr/lib/.build-id/3b
/usr/lib/.build-id/3b/a78cf8965ce90008707751d1cd941fe1b6302d
/usr/lib/.build-id/4c
/usr/lib/.build-id/4c/f627b5cb43f9b9e6093666ffcf245049b65856
/usr/lib/.build-id/70
/usr/lib/.build-id/70/5ddd8eff2e024b3d026f6c62ff8452864dcf8c
/usr/lib/.build-id/ad
/usr/lib/.build-id/ad/9a8f0e77cab6ba5fc6a50c8e2eed6794107a92
/usr/lib/.build-id/ee
/usr/lib/.build-id/ee/128f0a7ab0b7f52054696888f816d095fdede0
/usr/libexec/openssh/ssh-pkcs11-helper
/usr/share/man/man1/scp.1.gz
/usr/share/man/man1/sftp.1.gz
/usr/share/man/man1/ssh-add.1.gz
/usr/share/man/man1/ssh-agent.1.gz
/usr/share/man/man1/ssh-copy-id.1.gz
/usr/share/man/man1/ssh-keyscan.1.gz
/usr/share/man/man1/ssh.1.gz
/usr/share/man/man5/ssh_config.5.gz
/usr/share/man/man8/ssh-pkcs11-helper.8.gz
#dpkg
root@ubuntu1804:~# dpkg -S `which ssh`
openssh-client: /usr/bin/ssh
root@ubuntu1804:~# dpkg -L openssh-client
/.
/etc
/etc/ssh
/etc/ssh/moduli
/etc/ssh/ssh_config
/usr
/usr/bin
/usr/bin/scp
/usr/bin/sftp
/usr/bin/ssh
/usr/bin/ssh-add
/usr/bin/ssh-agent
/usr/bin/ssh-argv0
/usr/bin/ssh-copy-id
/usr/bin/ssh-keygen
/usr/bin/ssh-keyscan
/usr/lib
/usr/lib/openssh
/usr/lib/openssh/agent-launch
/usr/lib/openssh/ssh-keysign
/usr/lib/openssh/ssh-pkcs11-helper
/usr/lib/systemd
/usr/lib/systemd/user
/usr/lib/systemd/user/graphical-session-pre.target.wants
/usr/lib/systemd/user/ssh-agent.service
/usr/share
/usr/share/apport
/usr/share/apport/package-hooks
/usr/share/apport/package-hooks/openssh-client.py
/usr/share/doc
/usr/share/doc/openssh-client
/usr/share/doc/openssh-client/NEWS.Debian.gz
/usr/share/doc/openssh-client/OVERVIEW.gz
/usr/share/doc/openssh-client/README
/usr/share/doc/openssh-client/README.Debian.gz
/usr/share/doc/openssh-client/README.dns
/usr/share/doc/openssh-client/README.tun.gz
/usr/share/doc/openssh-client/changelog.Debian.gz
/usr/share/doc/openssh-client/copyright
/usr/share/doc/openssh-client/faq.html
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/openssh-client
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/scp.1.gz
/usr/share/man/man1/sftp.1.gz
/usr/share/man/man1/ssh-add.1.gz
/usr/share/man/man1/ssh-agent.1.gz
/usr/share/man/man1/ssh-argv0.1.gz
/usr/share/man/man1/ssh-copy-id.1.gz
/usr/share/man/man1/ssh-keygen.1.gz
/usr/share/man/man1/ssh-keyscan.1.gz
/usr/share/man/man1/ssh.1.gz
/usr/share/man/man5
/usr/share/man/man5/moduli.5.gz
/usr/share/man/man5/ssh_config.5.gz
/usr/share/man/man8
/usr/share/man/man8/ssh-keysign.8.gz
/usr/share/man/man8/ssh-pkcs11-helper.8.gz
/usr/bin/slogin
/usr/lib/systemd/user/graphical-session-pre.target.wants/ssh-agent.service
/usr/share/man/man1/slogin.1.gz
3. 总结程序包获取途径,以及rpm, yum, apt命令选项示例。
- 系统发行版的光盘
- 官网,镜像服务站
- 第三方组织,EPEL
- 软件项目站点
- 搜索引擎
#包查询
rpm -a #查找所有包
rpm -f #查找文件由哪个程序包安装生成的
rpm -qi #查看包的详细信息
rpm -ql #查看程序包安装后生成的所有文件
yum list #查看所有包
dpkg -l
dpkg -S 查看文件来自哪个包
apt list
#包安装
rpm -ivh #无法解决包依赖问题
dpkg -i
yum install
apt install
#包卸载
rpm -e #会保留配置文件
yum remove | erase
apt remove
apt purge #同时会删除配置文件
#查看仓库列表
yum repolist #查看所有程序包
4. 简要总结yum/dnf工作原理。并搭建私有yum仓库(base, epel源)给另一个虚拟机使用。
工作原理:yum源服务提供者会将编译好的rpm包以及包相关的元数据文件提前放在yum仓库,当用户通过yum包管理工具安装软件时,会下载仓库中的元数据,查询仓库中的数据库涉及的相关包以及依赖包,然后熊仓库下载并安装软件包
搭建私有yum仓库:
#仓库服务器配置
[root@rocky87 dev]#yum -y install httpd
[root@rocky87 dev]#systemctl start httpd
[root@rocky87 dev]# mount /dev/sr0 /mnt/cdrom/
[root@rocky87 dev]# mkdir /var/www/html/centos/8/
[root@rocky87 dev]# cp -a /mnt/* /var/www/html/centos/8/
#客户端配置
[root@centos79 yum.repos.d]# cat test.repo
[testbase]
name=testbase
baseurl=http://10.0.0.4/centos/8/BaseOS
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
[testextras]
name=testextras
baseurl=http://10.0.0.4/centos/extras
enabled=1
[root@centos79 yum.repos.d]# yum repolist testbase 2> /dev/null
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: ftp.sjtu.edu.cn
* epel: ftp.iij.ad.jp
* extras: mirror.lzu.edu.cn
* updates: ftp.sjtu.edu.cn
repo id repo name status
testbase testbase 1,723
repolist: 1,723
5. 总结系统安装之后的常用初始化步骤。rocky/ubuntu
关闭SELinux
sed -i '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config
关闭防火墙
systemctl disable --now firewalld
支持光盘
/misc/cd对应就是光盘内容 yum -y install autofs systemctl enable --now autofs
修改网卡名称
[root@rocky8 ~]#sed -ri '/GRUB_CMDLINE_LINUX=/s#(.*)"$#\1 net.ifnames=0"#' /etc/default/grub
[root@rocky8 ~]#grub2-mkconfig -o /boot/grub2/grub.cfg
[root@rocky8 ~]#reboot
最小化安装系统后,建议安装常用软件
yum -y install autofs vim-enhanced tcpdump autofs chrony lrzsz tree telnet ftp lftp redhat-lsb-core bash-completion net-tools postfix wget bzip2 zip unzip xz lsof mlocate man-pages rsync
Ubuntu开启root远程登录功能
#sudo -i
#passwd root
#sed -i '/PermitRootLogin/c PermitRootLogin yes' /etc/ssh/sshd_config
#systemctl restart sshd
6. 解读一键安装httpd脚本,并自行实现一个一键安装脚本
要求
1)基于位置变量传递版本号
2)基于独立函数进行初始化步骤,禁用防火墙,安装开发依赖包。
3)基于独立函数进行下载包,解压包。
4)基于独立函数进行编译,安装包。
5)基于独立函数完成链接包。
6)启动服务,并输出自定义的语句,安装xxx服务
#!/bin/bash
HTTPD_VERSION=$1
SRC_DIR=/usr/local/src
TAR=.tar.bz2
RAW_FILE=httpd-${HTTPD_VERSION}${TAR}
INSTALL_DIR=/apps/httpd/
HTTPD_URL=https://dlcdn.apache.org/httpd/httpd-${HTTPD_VERSION}${TAR}
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
initiall_prepare () {
color "禁用防火墙" 0
[ $ID == "centos" ] && sed -i '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config
[ $(systemctl is-active firewalld) == 'inactive' ] || systemctl disable --now firewalld
color "开始安装 httpd 依赖包" 0
if [ $ID == "centos" ] ;then
if [[ $VERSION_ID =~ ^7 ]];then
yum -y -q install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
elif [[ $VERSION_ID =~ ^8 ]];then
yum -y -q install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
color '不支持此系统!' 1
exit
fi
elif [ $ID == "rocky" ];then
yum -y -q install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
apt update &> /dev/null
apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev &> /dev/null
fi
}
package_prepare () {
[ -e ${INSTALL_DIR} ] && { color "httpd 已安装,请卸载后再安装" 1; exit; }
cd ${SRC_DIR}
if [ -e ${RAW_FILE} ];then
color "相关文件已准备好" 0
else
color '开始下载 HTTPD 源码包' 0
wget ${HTTPD_URL}
[ $? -ne 0 ] && { color "下载 ${RAW_FILE}文件失败" 1; exit; }
fi
}
install () {
color "开始安装 HTTPD" 0
if id apache &> /dev/null;then
color "apache 用户已存在" 1
else
useradd -s /sbin/nologin -r apache
color "创建 apache 用户" 0
fi
cd $SRC_DIR
tar xf ${RAW_FILE}
HTTPD_DIR=`echo ${RAW_FILE}| sed -nr 's/^(.*[0-9])\.tar.*/\1/p'`
cd ${HTTPD_DIR}
./configure --prefix=${INSTALL_DIR} --enable-ssl --disable-status
make -j $CPUS && make install
[ $? -eq 0 ] && color "httpd 编译安装成功" 0 || { color "httpd 编译安装失败,退出!" 1 ;exit; }
ln -s ${INSTALL_DIR}bin/apachectl /usr/local/bin/
color "httpd 安装完成" 0
}
initiall_prepare
package_prepare
install
apachectl start && color "httpd 已启动" 0
8. 调整动态端口范围为20000-60000
#临时生效
echo 20000 60000 > /proc/sys/net/ipv4/ip_local_port_range
#永久生效
vim /etc/sysctl.conf
net.ipv4.ip_local_port_range = 20000 60000
sysctl -p
9. 总结TCP包头结构,TCP三次握手,4次挥手。
TCP包头结构
● 数据偏移:表示TCP报文段的首部长度,共4位,由于TCP首部包含一个长度可变的选项部分,需要指定这个TCP报文段到底多长。它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。该字段的单位是32位(即4个字节),4位二进制最大表示15,所以数据偏移也就是TCP首部最大60字节。
● URG:表示本报文段中发送的数据是否包含紧急数据,后面的紧急指针字段只有当URG=1时才有效
● PSH:提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间。如果为1,则表示对方应当立即把数据提交给上层应用,而不是缓存起来,如果应用程序不将接收到的数据读走,就会一直停留在TCP接收缓冲区中
● 紧急指针:标记紧急数据在数据字段中的位置
● 窗口大小:表示现在允许对方发送的数据量,也就是告诉对方,从本报文段的确认号开始允许对方发送的数据量,达到此值,需要ACK确认后才能再继续传送后面数据,由window size value * window size scaling factor(此值在三次握手阶段TCP选项window scale协商得到)得出此值
TCP包头常见选项:
● 最大报文段长度MSS(maximum segment size):指明自己期望对方发送TCP报文段时数据字段的长度。MSS需要设置尽可能大,只要IP层传输时不需要再分片就行。MTU=MSS+TCP header+IP header
● 窗口扩大 window scale:为了扩大窗口。由于TCP首部的窗口大小字段长度是16位,所以其表示的最大数是65535。但随着时延和带宽比较大的通信产生,需要更大的窗口来满足性能和吞吐率,所以产生了窗口扩大选项
● 时间戳:可以用来计算RTT,发送方发送报文时,把当前的时间值放入时间戳字段,接收方收到后发送确认报文,把这个时间戳字段值赋值到确认报文中,发送方式收到确认报文后可计算出RTT。
TCP三次握手
- 客户端A发送SYN给服务端B,此时A进入SYN-SENT状态
- 一开始处于listen状态,收到SYN后响应SYN ACK进行第二次握手,B进入SYN_RECV状态
- A受到B发来的SYN ACK消息后,返回ACK,完成第三次握手,此时A进入ESTABLISHED状态
- B在收到ACK后也进入ESTABLISHED状态
TCP四次挥手
- A发送FIN消息后进入FIN-WAIT1状态
- B收到FIN消息后返回 ACK,并进入CLOS_WAIT状态
- B发送完数据后发出FIN消息,并进入LAST-ACK状态
- A收到FIN后进入FIN-WAIT2状态,并响应ACK,并进入TIME_WAIT状态,并开始计时,达到2MSL后会自动进入CLOSE状态
- B在收到A的ACK后进入CLOSE状态
13. 当A(10.0.1.1/16)与B(10.0.2.2/24)通信,A如何判断是否在同一个网段?A和B能否通信?
当A访问B时,A的地址与掩码相与得到10.0.0.0/16,B的地址与A的掩码相与得到10.0.0.0/16,两者一致,因此A认为跟B在同一网段,直接通过ARP广播获取B的mac地址
当B放访问A时,B的地址与掩码相与得到10.0.2.0/24,A的地址与B的掩码相与得到10.0.1.0/24,两者不一致,因此B认为跟A不在同一个网段,因此B会根据路由表把数据包先发给网关
15. 通过网络配置命令,让主机可以上网。 ip, netmask, gateway, dns,主机名。相关命令总结,最终可以通过这些配置让你的主机上网。
ip addr add 10.0.0.8/24 dev ens33 #配置地址
ip route add default via 10.0.0.2 dev ens33 #配置默认路由
echo 8.8.8.8 >> /etc/resolv.conf #配置DNS
hostnamectl set-hostname rocky #修改主机名
[root@rocky ~]# ping www.baidu.com #实现上网
PING www.a.shifen.com (36.152.44.95) 56(84) bytes of data.
64 bytes from 36.152.44.95 (36.152.44.95): icmp_seq=1 ttl=128 time=23.5 ms
64 bytes from 36.152.44.95 (36.152.44.95): icmp_seq=2 ttl=128 time=21.1 ms
64 bytes from 36.152.44.95 (36.152.44.95): icmp_seq=3 ttl=128 time=14.7 ms
64 bytes from 36.152.44.95 (36.152.44.95): icmp_seq=4 ttl=128 time=46.10 ms
16. 解析/etc/sysconfig/network-scripts/ifcfg-eth0配置格式。
NAME=<friendly name for users to see>
DEVICE=<name of physical device >
IPADDRn=
PREFIXn=
Network prefix.It takes precedence over NETMASK when both PREFIX and NETMASK are set.
NETMASKn=
The "n" is expected to be consecutive positive integers starting from 0.
It can be omitted if there is only one address being configured.
GATEWAY=
ONBOOT=yes|no
BOOTPROTO=none|bootp|dhcp
'bootp' or 'dhcp' cause a DHCP client to run on the device. Any other value causes any static configuration in the file to be applied.
DNS{1,2}=<ip address>
DEFROUTE=yes|no (set this interface as default route? yes is default)
17. 基于配置文件或命令完成bond0配置
创建bonding设备的配置文件
[root@centos79 network-scripts]# cat /etc/sysconfig/network-scripts/ifcfg-bond0
NAME=bond0
DEVICE=bond0
TYPE=bond
BOOTPROTO=none
IPADDR=10.0.0.3
NETMASK=255.255.255.0
GATEWAY=10.0.0.2
BONDING_OPTS="mode=1 miimon=100 fail_over_mac=1"
#miimon指定链路监测时间间隔。如果miimon=100,那么系统每100ms检测一次链路状态,如果有一条线路不通就转入另一条
[root@centos79 network-scripts]# cat /etc/sysconfig/network-scripts/ifcfg-ens33
DEVICE=ens33
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
ONBOOT=yes
NAME=ens33
[root@centos79 network-scripts]# cat /etc/sysconfig/network-scripts/ifcfg-ens37
DEVICE=ens37
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
ONBOOT=yes
NAME=ens37
[root@centos79 network-scripts]#systemctl restart network
[root@centos79 network-scripts]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP group default qlen 1000
link/ether 00:0c:29:46:8a:2c brd ff:ff:ff:ff:ff:ff
3: ens37: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP group default qlen 1000
link/ether 00:0c:29:46:8a:36 brd ff:ff:ff:ff:ff:ff
5: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:46:8a:2c brd ff:ff:ff:ff:ff:ff
inet 10.0.0.3/24 brd 10.0.0.255 scope global bond0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe46:8a2c/64 scope link
valid_lft forever preferred_lft forever
查看bond状态
[root@centos79 network-scripts]# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
Bonding Mode: fault-tolerance (active-backup) (fail_over_mac active)
Primary Slave: None
Currently Active Slave: ens37
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0
Slave Interface: ens33
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 1
Permanent HW addr: 00:0c:29:46:8a:2c
Slave queue ID: 0
Slave Interface: ens37
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 00:0c:29:46:8a:36
Slave queue ID: 0
[root@centos79 network-scripts]#
删除bond0
ifconfig bond0 down
rmmod bonding
18. 通过ifconfig命令结果找到ip地址
ifconfig |sed -rn 's/.*inet (.*) netmask.*/\1/p'
19. 使用脚本判断 你主机所在网络内在线的主机IP有哪些? ping通则在线
for i in {1..255};do { if ping -c 1 -W 1 10.0.0.$i &> /dev/null ;then echo 10.0.0.$i is up ;fi;}& done
20. 使用while read line和/etc/passwd,计算用户id总和。
while read line ;do id_num=$(echo $line| cut -d: -f3); let sum+=id_num;done < /etc/passwd ;echo $sum