亲自面试版运维面试题(按需更新)

一、Linux

1、cpu使用率跟负载的区别

CPU使用率:

表示CPU在特定时间间隔内的繁忙程度百分比

统计的是CPU时间片的使用情况

100%表示所有CPU核心都在满负荷工作

CPU负载:

表示系统平均负载,即单位时间内系统中处于运行状态和不可中断状态的进程平均数

统计的是等待CPU资源的进程数量

通常显示为三个值:1分钟、5分钟、15分钟的平均负载

对于多核CPU,负载值÷CPU核心数 = 相对负载

关键区别:

使用率是"当前有多忙",负载是"有多少任务在排队"

低使用率高负载:可能I/O阻塞导致进程排队

高使用率低负载:CPU密集型任务但队列不长

2、什么情况会导致CPU使用率或负载高

CPU使用率高的情况:

CPU密集型应用(科学计算、视频编码)

无限循环或递归调用

大量小文件处理(频繁系统调用)

垃圾回收频繁(Java/Python等)

锁竞争激烈(线程等待后集中执行)

配置不当(线程池过大)

负载高但CPU使用率不高的情况:

I/O密集型操作(磁盘读写瓶颈)

大量进程等待I/O(不可中断状态)

内存不足导致频繁swap

网络拥堵导致进程阻塞

锁竞争导致进程排队

3、kill -9 跟 kill -15 的区别

kill -15(SIGTERM):

优雅终止信号,允许程序进行清理工作

程序可以捕获此信号,执行关闭前的清理操作(如保存数据、关闭连接)

是默认的kill信号

kill -9(SIGKILL):

强制终止信号,无法被捕获或忽略

立即终止进程,不进行任何清理

可能导致资源泄漏或数据损坏

使用建议:

先使用 kill -15 或 kill [PID]

等待几秒后再考虑 kill -9

系统服务应正确处理SIGTERM信号

4、inode空间是什么

inode(索引节点):

文件系统数据结构,存储文件的元数据(不包括文件名和文件内容)

包含:权限、所有者、大小、时间戳、数据块位置等

inode空间:

文件系统分配的inode总数,创建文件系统时确定

每个文件或目录占用一个inode

inode耗尽:即使磁盘有空间也无法创建新文件

检查命令:

df -i # 查看inode使用情况

inode耗尽常见原因:

大量小文件(日志、缓存文件)

未清理的临时文件

Docker/容器产生大量层文件

邮件系统产生大量小邮件

5、TCP三次握手

TCP三次握手 是 TCP/IP 协议中,客户端和服务器在开始传输应用数据之前,必须完成的一个建立可靠双向通信信道的过程。这个过程通过三次报文交换来完成,因此得名。

核心目的:同步双方的初始序列号,这是TCP实现可靠性、流量控制和有序传输的基础。

复制代码
详细流程:如何工作?
假设客户端(Client)想要主动连接服务器(Server)。

第一次握手 (SYN):
发起方:客户端
动作:客户端发送一个TCP报文,其中:
标志位 SYN=1:表示这是一个"同步"报文,请求建立连接。
序列号 seq = x:客户端随机生成一个初始序列号(ISN)。
状态变化:客户端进入 SYN_SENT 状态。

第二次握手 (SYN + ACK):
发起方:服务器
动作:服务器收到SYN报文后,如果同意连接,则回复一个报文,其中:
标志位 SYN=1,ACK=1:SYN=1 表示这也是一个同步报文;ACK=1 表示确认字段有效。
序列号 seq = y:服务器随机生成自己的初始序列号。
确认号 ack = x + 1:确认客户端的序列号,意思是"我收到了你的序列号x,期待你下次发送从x+1开始的数据"。
状态变化:服务器进入 SYN_RCVD 状态。

第三次握手 (ACK):
发起方:客户端
动作:客户端收到服务器的SYN-ACK报文后,必须再次确认。发送一个报文,其中:
标志位 ACK=1:纯确认报文。
序列号 seq = x + 1:因为第一次握手的SYN消耗了一个序列号,所以这里从x+1开始。
确认号 ack = y + 1:确认服务器的序列号,意思是"我收到了你的序列号y,期待你下次发送从y+1开始的数据"。
状态变化:客户端进入 ESTABLISHED 状态。服务器收到这个ACK后,也进入 ESTABLISHED 状态。

至此,连接建立成功,双方可以开始传输应用数据。

可以用一个生活中的比喻:
客户:"你好,我想和你通话。"(SYN)
客服:"收到,我准备好了,你也能听到我吗?"(SYN + ACK)
客户:"能听到,我们开始吧。"(ACK)
------ 正式通话开始。

关键问题:为什么是三次?不是两次或四次?

这是面试中最常被追问的深层原理问题。

为什么不是两次?

核心原因:防止已失效的连接请求报文突然又传送到服务器,导致错误。

场景:客户端发送了一个SYN报文,由于网络拥塞迟迟未到。客户端超时重发了一个SYN并成功建立连接、传输数据、关闭连接。此时,第一个迟到的SYN 终于到达了服务器。如果只是两次握手(服务器回复SYN-ACK后连接就建立),服务器会以为客户端又发起新连接,从而一直保持这个"幽灵连接",浪费服务器资源。第三次握手让客户端有机会告诉服务器:"你刚才同意的那个请求,我(在有效期内)确认了",如果是过期的请求,客户端不会发出第三次ACK,服务器收不到确认就会关闭这个半连接。

为什么不是四次?

三次已经足以完成 双方初始序列号的同步与确认。在第二次握手时,服务器已经将 ACK(确认客户端的SYN)和 SYN(自己的同步请求)合并到了一个报文里发送,效率最高。再增加一次握手只是冗余,没有必要。

二、脚本相关

1、shell脚本的/bin/bash和/bin/sh的区别

sh (Bourne Shell):原始的Unix shell,由Stephen Bourne开发,功能较为基础

bash (Bourne Again Shell):sh的增强版,兼容sh并添加了大量新功能

使用 #!/bin/sh 当:

需要最大兼容性(跨Unix系统)

脚本只使用POSIX标准特性

追求更快的执行速度(dash通常比bash快)

使用 #!/bin/bash 当:

需要使用bash特有功能

脚本只在Linux系统运行

需要更丰富的编程特性

2、shell脚本如何统计数组的长度,如何截取数组

统计

复制代码
array=("apple" "banana" "cherry" "date")

# 方法1:使用 ${#array[@]}
echo "元素个数: ${#array[@]}"  # 输出: 4

# 方法2:使用 ${#array[*]}
echo "元素个数: ${#array[*]}"  # 输出: 4

# 统计单个元素的长度
echo "第一个元素长度: ${#array[0]}"  # 输出: 5

截取

复制代码
array=("a" "b" "c" "d" "e" "f" "g")

# 基本切片:${array[@]:起始位置:长度}
echo "${array[@]:2:3}"    # 输出: c d e
# 等价于 array[2]到array[4],共3个元素

# 从指定位置到末尾
echo "${array[@]:3}"      # 输出: d e f g

# 从末尾开始(使用负数索引)- 需要bash 4.2+
echo "${array[@]:(-3):2}" # 输出: e f(倒数第3个开始,取2个)
echo "${array[@]: -3:2}"  # 注意空格:-3前要有空格

# 保存切片到新数组
new_array=("${array[@]:1:4}")
echo "新数组: ${new_array[@]}"  # 输出: b c d e

3、python中列表和元组的区别

定义

复制代码
# 列表 - 方括号
my_list = [1, 2, 3, 'hello']
empty_list = []
list_from_range = list(range(5))  # [0, 1, 2, 3, 4]

# 元组 - 圆括号(括号可以省略)
my_tuple = (1, 2, 3, 'hello')
single_tuple = (5,)  # 单元素元组必须有逗号!
no_parens = 1, 2, 3  # 也是元组
empty_tuple = ()
tuple_from_list = tuple([1, 2, 3])  # (1, 2, 3)

可变性 - 最关键区别

复制代码
# 列表 - 可以修改
my_list = [1, 2, 3]
my_list[0] = 10       # ✅ 修改元素
my_list.append(4)     # ✅ 添加元素
my_list.remove(2)     # ✅ 删除元素
my_list.extend([5,6]) # ✅ 扩展列表
del my_list[1]        # ✅ 删除指定元素

# 元组 - 不可修改
my_tuple = (1, 2, 3)
my_tuple[0] = 10      # ❌ TypeError
my_tuple.append(4)    # ❌ AttributeError
del my_tuple[1]       # ❌ TypeError

需要修改数据? → 用列表

数据固定不变? → 用元组

需要字典键或集合元素? → 用元组

关注性能? → 用元组

初学者不确定? → 先用列表,有需要再转为元组

三、k8s&docker

1、Deployment、StatefulSet的区别

Deployment:

用于无状态应用

Pod完全相同的副本,可随意创建、删除、替换

随机名称和唯一标识

适用于Web服务器、API服务等

支持滚动更新、回滚

StatefulSet:

用于有状态应用

Pod有稳定的、唯一的网络标识和持久存储

有序的部署、扩展、删除(顺序保证)

每个Pod有稳定的主机名:[statefulset名称]-[序号]

适用于数据库、消息队列等需要稳定标识的应用

2、Docker中PID 1进程隔离技术

实现原理:

(1)Linux命名空间(Namespaces)

PID命名空间:每个容器有自己的PID编号体系

容器内的进程看不到主机或其他容器的进程

PID 1只在各自的PID命名空间内有效

(2)控制组(Cgroups)

资源隔离和限制(CPU、内存、I/O等)

防止容器内进程占用过多主机资源

(3)联合文件系统(UnionFS)

提供独立的文件系统视图

每个容器有自己的根文件系统

PID命名空间具体工作方式:

容器启动时,Docker创建新的PID命名空间

容器内第一个进程成为该命名空间的PID 1

主机上该进程有真实的PID(如PID 1000)

信号传播:主机向容器PID 1发信号,会被正确传递

重要性:

容器内PID 1进程需要正确处理信号(如SIGTERM)

僵尸进程回收:PID 1进程需要负责回收子进程

使用docker run --init可添加轻量级init进程

3、docker查看容器cpu内存使用的命令

docker stats - 实时监控

docker top - 查看进程详情

相关推荐
BullSmall2 小时前
ELK 单机版日志系统【一键自动化部署脚本 + 完整配套配置】
运维·elk·自动化
Linux蓝魔2 小时前
内网搭建阿里源的centos7系统源arm和x86
linux·运维·服务器
fo安方2 小时前
软考~系统规划与管理师考试——真题篇——章节——第5章 应用系统规划——解析版
java·运维·网络
tianyuanwo2 小时前
Jenkins Job管理实战指南:增删改查与批量操作技巧
运维·jenkins
螺旋小蜗3 小时前
docker-compose文件属性(3)顶部元素networks
运维·docker·容器
Q16849645153 小时前
红帽Linux-文件权限管理
linux·运维·服务器
不当菜虚困3 小时前
centos7虚拟机配置网络
运维·服务器·网络
fiveym3 小时前
CI/CD 核心原则 + 制品管理全解析:落地要求 + 存储方案
linux·运维·ci/cd
小北方城市网3 小时前
Spring Security 认证授权实战(JWT 版):从基础配置到权限精细化控制
java·运维·python·微服务·排序算法·数据库架构