Linux运维工程师笔试题第二十二套

  1. 篮子里有100个苹果,将这些苹果进行编号,从0开始到99。现在将这些苹果分成4份,第一份20个,第二份30个,第三份38个,最后一份12个,要求是苹果的编号不能连续。

【思路】通过构造性方法分配苹果,确保每份内部无连续编号:
第一份(20 个苹果):选取前 20 个奇数(1, 3, 5, …, 39)。奇数之间相差 2,无连续编号。
第二份(30 个苹果):选取剩余的奇数(41, 43, …, 99)。 同样无连续编号。
第三份(38 个苹果):选取前 38 个偶数(0, 2, 4, …, 74)。这些苹果之间相差 2,无连续编号。
第四份(12 个苹果):选取后 12 个偶数(76, 78, …, 98)。同样无连续编号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 生成各分组的苹果编号
group1 = list(range(1, 40, 2)) # 第一份:20 个奇数(1, 3, ..., 39)
group2 = list(range(41, 100, 2)) # 第二份:30 个奇数(41, 43, ..., 99)
group3 = list(range(0, 75, 2)) # 第三份:38 个偶数(0, 2, ..., 74)
group4 = list(range(76, 99, 2)) # 第四份:12 个偶数(76, 78, ..., 98)

# 验证各分组数量是否正确
assert len(group1) == 20, "第一份数量错误"
assert len(group2) == 30, "第二份数量错误"
assert len(group3) == 38, "第三份数量错误"
assert len(group4) == 12, "第四份数量错误"

# 验证各分组内部无连续编号
def has_consecutive(numbers):
sorted_numbers = sorted(numbers)
for i in range(1, len(sorted_numbers)):
if sorted_numbers[i] - sorted_numbers[i-1] == 1:
return True
return False

for group in [group1, group2, group3, group4]:
assert not has_consecutive(group), "存在连续编号"

# 验证所有苹果编号被唯一分配
all_apples = set(range(100))
assigned = set(group1 + group2 + group3 + group4)
assert all_apples == assigned, "苹果编号未全部分配或重复"

# 输出结果
print("分组结果:")
print(f"第一份: {group1}")
print(f"第二份: {group2}")
print(f"第三份: {group3}")
print(f"第四份: {group4}")
  1. 编写一个函数,在字符串数组中查找最长的公共前缀字符串。 如果没有公共前缀,则返回空字符串” “。
    输入:strs = [“present”,”promotion”,”protect”]
    输出:”pr”
    输入:strs = [“al”,”trace”,”mtr”]
    输出:” “

【思路】
先确定拿到的strs里最少的单词的长度,然后就拿第一个单词的第一个字母开始对比,如果跟第二个单词的第一个字母相同,再比较第三个单词的第一个字母,如果三个都相同,则比较第二个字母。一直到不相同结束。

【代码】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def longest_common_prefix(strs):
if not strs:
return ""

# 找到最短的字符串长度
min_length = min(len(s) for s in strs)

prefix = ""
for i in range(min_length):
char = strs[0][i]
if all(s[i] == char for s in strs): # 判断是否所有字符串的当前位置字符相同,这里如果都相同,就是返回都是Ture,外面再套了一层all
prefix += char
else:
break

return prefix

# 测试示例
strs1 = ["present", "promotion", "protect"]
print(longest_common_prefix(strs1)) # 输出: "pr"

strs2 = ["al", "trace", "mtr"]
print(longest_common_prefix(strs2)) # 输出: ""

strs3 = []
print(longest_common_prefix(strs3)) # 输出: ""
  1. 给定一个整数x,如果x是回文整数,则返回true。 当一个整数向后读取与向前读取相同时,它就是一个回文。例如,121是回文,而123不是。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def is_palindrome(x):
    # 将整数转换为字符串
    str_x = str(x)

    # 比较原字符串和反转后的字符串是否相同
    return str_x == str_x[::-1]

    # 测试示例
    print(is_palindrome(121)) # 输出: True
    print(is_palindrome(-121)) # 输出: False
    print(is_palindrome(123)) # 输出: False
    print(is_palindrome(1221)) # 输出: True
  2. 在一个整型数组中, 找到两个index,其对应的两个数相加为给出的目标数字。 你可以假设每个输入都有且仅有一个解。给定一个整数数组nums和一个整数目标值target,返回两个数字的索引,使它们相加到目标值。
    您可以假设每个输入都只有一个答案,但是不能两次使用同一元素。可以按任何顺序返回答案。
    示范
    输入:nums = [3,2,4], target = 6
    输出:[1,2]
    输入:nums = [1,2,9], target = 10
    输出:[0,2]

【思路】先拿到nums里每一个元素的index和对应的值,然后用目标数target逐一减去每一个元素,看剩下的值是否在,因为是要求返回两个数字的索引,所以存在就拿到另一个值的index,如果不存在就返回空就得了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def two_sum(nums, target):
num_dict = {} # 创建一个字典

for index, num in enumerate(nums): # 逐一获得目标数组的值num和索引i
complement = target - num # 然后就是目标值-目标数组的值num,看剩余的的值是否在

if complement in num_dict:
return [num_dict[complement], index]

num_dict[num] = index

# 题目假设一定有解,所以这里不会到达
return []

# 示例
nums = [2, 7, 11, 15]
target = 26
print(two_sum(nums, target)) # 输出: [2, 3]
  1. select * from A where exists (select * from B where A.id=B.id);select * from A where A.id in (select id from B);如果A表有100条数据,B表有10000条,请问哪个sql语句执行效率高?
    【答案】EXISTS 可以利用索引快速查找并提前终止,减少不必要的扫描。IN 需要生成并存储较大的结果集,可能导致内存开销和性能下降。所以,EXISTS 语句的执行效率更高。

  2. 简述CGROUP如何限制进程cpu使用
    【答案】首先需要在系统中创建一个CGroup,并为其配置相应的资源限制。这通常涉及到创建目录结构和设置文件。例如,在 /sys/fs/cgroup/cpu/ 下创建一个名为 my_cgroup 的CGroup:mkdir /sys/fs/cgroup/cpu/my_cgroup

然后,设置CPU份额。CGroup提供了两种方式来限制CPU使用:CPU份额(CPU shares)和CPU配额(CPU quotas)。CPU份额决定了各个任务之间的相对优先级。例如,如果两个任务A和B的CPU份额分别是1024和512,那么任务A将获得大约两倍于任务B的CPU时间。

设置CPU份额:echo 1024 > /sys/fs/cgroup/cpu/my_cgroup/cpu.shares

CPU配额允许你精确地限制任务在一定时间内能够使用的CPU时间。例如,你可以设置一个任务在一个周期内最多只能使用50%的CPU时间。

1
2
echo 50000 > /sys/fs/cgroup/cpu/my_cgroup/cpu.cfs_quota_us
echo 100000 > /sys/fs/cgroup/cpu/my_cgroup/cpu.cfs_period_us

这里,cpu.cfs_quota_us 表示在一个周期内允许的最大CPU时间(单位是微秒),而 cpu.cfs_period_us 表示周期的长度(单位也是微秒)。上面的例子表示在一个周期(100000微秒,即0.1秒)内,最多使用50000微秒(即0.05秒)的CPU时间。

最后,将特定的进程添加到CGroup中,以便它们受到资源限制的影响。例如,将PID为1234的进程添加到 my_cgroup 中:echo 1234 > /sys/fs/cgroup/cpu/my_cgroup/tasks

现在可以通过读取相关文件来监控CGroup的状态和统计信息。cat /sys/fs/cgroup/cpu/my_cgroup/cpuacct.usage

  1. http 301 500和502 含义
    【答案】

    1
    2
    3
    HTTP 301 Moved Permanently(永久重定向),此时客户端会缓存新 URL。而302(临时重定向),客户端不会缓存新 URL。
    HTTP 500 Internal Server Error(服务器内部错误),直接去后端服务器上看问题吧,通常由代码缺陷、配置错误或依赖服务故障引起。
    HTTP 502 Bad Gateway(错误网关),即作为网关或代理的服务器(如 Nginx、反向代理)从上游服务器(后端服务)收到无效响应。有可能是反向代理的nginx挂了,或者是后端服务超时了。
  2. 如何限制单个容器的最大磁盘占用?
    【答案】

    1
    2
    3
    4
    docker create \
    --name my_container \
    --storage-opt size=10G \
    your_image
  3. A和B两台服务器,如何让A可以访问B的ssh,B不能访问A的ssh服务
    【答案】这里主要是“B不能访问A的ssh服务”,iptables配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 假设 A 的 IP 是 192.168.1.100,
    # 需要在B侧配置
    sudo iptables -A INPUT -p tcp --dport 22 -s 192.168.1.100 -j DROP
    解释:
    -A INPUT:添加到输入链。
    -p tcp --dport 22:针对 SSH 的 TCP 22 端口。
    -s 192.168.1.100:指定源 IP 为 A 的地址。
    -j DROP:丢弃该流量(即拒绝连接)。

    sudo service iptables save #保存

    如果需要 完全禁止 B 访问 A 的所有服务,而不仅仅是 SSH,则在A侧配置:sudo iptables -A INPUT -s B的IP地址 -j DROP

  1. 谈谈DNS 两种方式
    【答案】

    1
    2
    3
    4
    5
    6
    递归 DNS(Recursive DNS)
    递归 DNS 服务器负责为客户端解析域名,递归查询整个 DNS 层级(根服务器 → 顶级域服务器 → 权威服务器),直到获取最终的 IP 地址。
    特点:客户端视角:客户端只需向递归 DNS 发起请求,无需关心 DNS 查询过程。缓存优化:递归 DNS 通常会缓存结果,减少重复查询。
    权威 DNS(Authoritative DNS)
    权威 DNS 服务器负责管理特定域名的解析数据(如 example.com 的 A 记录、CNAME 记录等),直接返回域名对应的 IP 地址。
    特点:层级关系:每个域名需配置一个或多个权威服务器(主服务器 + 从服务器)。数据源:解析数据存储在区域文件(Zone File)中。
  2. 谈谈bind高可用机制
    【答案】

    1
    2
    3
    4
    主从服务器(Primary/Secondary):通过主服务器(Primary)和从服务器(Secondary)的协作,确保在主服务器故障时,从服务器仍能提供解析服务。
    负载均衡 + VIP(Virtual IP):通过虚拟 IP(VIP)和负载均衡器(如 HAProxy)将流量分发到多个 BIND 实例,实现无缝故障转移。
    DNSSEC + 区域签名:通过 DNSSEC(DNS Security Extensions)对区域数据进行签名,确保数据完整性和防篡改。
    自动故障切换(Keepalived + VRRP):使用 Keepalived 实现主备服务器的自动切换,当主服务器宕机时,VIP 自动转移到备用服务器。
  3. mysql主从同步的全同步复制和半同步复制是啥?
    【答案】

    1
    2
    3
    mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。
    全同步复制:主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。
    半同步复制:和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。
  4. free -m 这个命令的输出是啥意思?
    【答案】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    total:总内存大小(单位:MB)。used + free + buff/cache ≈ total,这是正常现象。
    used:已使用的内存大小(包括缓存和缓冲区)。used 为 0 时,表示物理内存足够,无需使用交换分区。used 明显大于 0,说明物理内存不足,系统开始使用磁盘作为虚拟内存(性能可能下降)。
    free:完全空闲的内存大小(未被使用)。
    shared:共享内存大小(通常由多个进程共享的内存区域)。
    buff/cache:内核缓存和缓冲区占用的内存大小(这部分可以被快速释放以供应用程序使用)。
    available:可用内存大小(预估当前系统可分配的内存,比 free + buff/cache 更合理)。如果 available 接近 0,可能需要优化内存使用或增加内存。
    Mem:物理内存(RAM)的统计信息。
    Swap:交换分区(Swap)的统计信息。

    结合 watch 命令实时监控内存:watch -n 1 free -m
感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------