1. 使用while read line和/etc/passwd,计算用户id总和。
#!/bin/bash
sum=0
while IFS=: read -r s1 s2 s3 s4 s5 s6 s7 ; do
sum=$((sum + s3))
done < /etc/passwd
echo "用户ID总和为: $sum"
2. 总结索引数组和关联数组,字符串处理,高级变量使用及示例。
索引数组
索引数组是shell脚本中用于存储多个值的变量。数组的每个元素都有一个唯一的索引,默认情况下,索引从0开始。
示例:
# 声明并初始化索引数组
arr=(test1 test2 test3)
# 访问数组元素
echo ${arr[0]} # 输出:test1
echo ${arr[1]} # 输出:test2
# 获取数组长度
echo ${#arr[@]} # 输出:3
# 遍历数组
for i in "${!arr[*]}"; do
echo "Index: $i"
done
关联数组
关联数组(也称为哈希或字典)允许我们使用任意字符串作为索引来存储值。在Bash 4.0及更高版本中支持关联数组。
示例:
# 声明关联数组
declare -A person
# 为关联数组赋值
person["name"]="John"
person["age"]=30
person["city"]="New York"
# 访问关联数组元素
echo ${person["name"]} # 输出:John
# 遍历关联数组
for key in "${!person[@]}"; do
echo "Key: $key, Value: ${person[$key]}"
done
字符串处理
Shell脚本提供了许多用于处理字符串的内置操作。
示例:
# 字符串长度
str="Hello, World!"
echo ${#str} # 输出:13
# 字符串截取
echo ${str:0:5} # 输出:Hello
# 字符串替换
echo ${str/World/Planet} # 输出:Hello, Planet!
# 查找子字符串位置
pos=$(expr index "$str" "World")
echo $pos # 输出:7
高级变量使用
Shell脚本中的变量可以执行更复杂的操作,例如命令替换和算术扩展。
示例:
# 命令替换
files=$(ls -l)
echo "$files"
# 算术扩展
num1=10
num2=20
sum=$((num1 + num2))
echo $sum # 输出:30
# 间接引用
indirect="var_name"
var_name="Hello"
echo "${!indirect}" # 输出:Hello
3. 求10个随机数的最大值与最小值。
#!/bin/bash
# 初始化最大值和最小值为第一个随机数
min=$RANDOM
max=$RANDOM
# 生成并检查剩余的9个随机数
for i in {1..9}
do
number=$RANDOM
if [ $number -gt $max ]; then
max=$number
fi
if [ $number -lt $min ]; then
min=$number
fi
done
echo "最大值是: $max"
echo "最小值是: $min"
4. 使用递归调用,完成阶乘算法实现。
#!/bin/bash
# 定义阶乘函数
factorial() {
local n=$1
if [ $n -eq 0 ]; then
echo 1
else
local sub_factorial=$(factorial $((n-1)))
echo $((n * sub_factorial))
fi
}
# 读取用户输入
read -p "请输入一个整数来计算阶乘: " num
# 调用阶乘函数并输出结果
result=$(factorial $num)
echo "$num的阶乘是: $result"
5. 解析进程和线程的区别?
- 进程是操作系统分配资源的最小单位
- 线程是程序执行的CPU调度的最小单位
- 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
- 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见;
- 调度和切换:线程上下文切换比进程上下文切换要快得多。
6. 解析进程的结构。
进程一般由程序、数据集合和进程控制块三部分组成。
- 程序用于描述进程要完成的功能,是控制进程执行的指令集;
- 数据集合是程序在执行时所需要的数据和工作区;
- 程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的唯一标志。
7. 结合进程管理命令,说明进程各种状态。
- 创建状态:进程在创建时需要申请一个空白PCB(process control block进程控制块),向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把此时进程所处状态称为创建状态
- 就绪状态:进程已准备好,已分配到所需资源,只要分配到CPU就能够立即运行
- 执行状态:进程处于就绪状态被调度后,进程进入执行状态
- 阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用
- 终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行
常用的进程管理命令
ps命令:用于查看进程的快照,即当前时间点的进程状态。通过ps命令,我们可以获取到每个进程的PID(进程标识号)、状态等信息。状态字段通常会显示进程当前的状态,如R(运行)、S(休眠)、T(停止)等。
格式:ps [OPTION]
选项 | 命令 |
---|---|
ps -a | 列出所有运行中/激活进程 |
ps -l | 查看自己的进程 |
ps aux | 查看系统所有进程 |
ps aux | grep threadx | 查看特定的进程 |
**pstree命令:**可以用来显示进程的父子关系,以树形结构显示
格式:pstree [OPTION] [ PID | USER ]
常用选项:
选项 | 说明 |
---|---|
-p | 显示PID |
-T | 不显示线程thread,默认显示线程 |
-u | 显示用户切换 |
-H pid | 高亮显示指定进程及其前辈进程 |
8. 说明IPC通信和RPC通信实现的方式。
IPC(进程间通信)
IPC用于在同一台计算机上运行的进程之间的通信。它允许数据交换和同步操作。常见的IPC机制包括:
- 管道(Pipes):允许在父子进程间或兄弟进程间进行单向数据流传输。
- 命名管道(Named Pipes):类似于管道,但可以在任意两个进程间通信,不限于有亲缘关系的进程。
- 消息队列(Message Queues):允许一个或多个进程写入或读取数据块,这些数据块按照先进先出的顺序排列。
- 信号量(Semaphores):用于同步,确保多个进程可以安全地访问共享资源。
- 共享内存(Shared Memory):允许多个进程访问同一块内存空间,是最快的一种IPC方式,因为数据不需要在客户机和服务器之间复制。
- 套接字(Sockets):虽然通常用于网络通信,但套接字也可以用于同一台机器上的进程间通信。
RPC(远程过程调用)
RPC用于在不同计算机上的进程之间的通信。RPC的目标是使远程函数调用像本地函数调用一样直观。RPC的实现通常包括以下组件:
- 客户端(Client):调用远程函数的进程。
- 服务器(Server):提供远程函数的进程。
- 存根(Stub):在客户端,存根负责将调用信息(如函数名、参数)打包并发送到服务器端。在服务器端,存根负责解包调用信息并执行本地函数调用。
- 绑定(Binding):将RPC函数映射到具体的网络地址和端口。
- 通信协议:客户端和服务器之间的通信协议,如TCP或UDP。
- 消息传递:客户端和服务器之间的消息传递机制,可以是基于TCP或UDP的。
9. 总结Linux,前台和后台作业的区别,并说明如何在前台和后台中进行状态转换。
Linux前台和后台作业的区别:
前台作业(Foreground Job)
- 控制终端:前台作业直接与终端关联,会占用终端的标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr)。
- 用户交互:用户可以直接与前台作业交互,输入数据或接收输出信息。
- 控制键:可以通过控制键如Ctrl+C中断前台作业。
- 作业控制:可以使用作业控制命令如Ctrl+Z将前台作业挂起(暂停)并放入后台。
- 终端依赖:关闭终端会发送SIGHUP信号给前台作业,通常会导致前台作业终止。
后台作业(Background Job)
-
控制终端:后台作业不占用终端的标准输入、输出和错误输出,可以在用户不直接交互的情况下运行。
-
用户交互:用户不能直接与后台作业交互,后台作业的输出会直接显示在终端上,可能会打断用户的输入。
-
控制键:后台作业不会响应控制键如Ctrl+C,但可以使用其他命令来控制后台作业,如kill命令发送信号给后台作业。
-
作业控制:可以将前台作业放入后台,使其成为后台作业,使用命令如command &或bg。
-
终端依赖:后台作业不会因为终端关闭而自动终止,除非它们收到SIGHUP信号。
状态转换
将前台进程发送到后台:
- 使用&符号:在命令末尾加上&,例如command &。
- 使用Ctrl+Z:先运行一个前台进程,然后按下Ctrl+Z将其挂起并放入后台。
将后台进程带到前台:
- 使用fg命令:默认将最后一个放入后台的进程带到前台,或指定作业号,例如fg %job_number。
列出后台作业:
- 使用jobs命令:查看所有后台作业及其作业号。
继续运行后台进程:
- 使用bg命令:继续运行一个被暂停的后台进程,例如bg %job_number。
终止后台进程:
- 使用kill命令:发送信号给后台进程以终止它,例如kill %job_number。
10. 总结内核设计流派及特点。
常见的内核设计流派主要有以下几种:
单内核(Monolithic Kernel):
- 特点:单内核设计将所有的系统服务(如进程管理、文件系统、设备驱动、内存管理等)和内核代码集成在一个单一的内核空间中。
- 优点:性能高,因为系统服务直接在内核空间中运行,减少了用户空间和内核空间之间的切换。
- 缺点:安全性较低,一个服务的失败可能影响整个系统;可扩展性较差,添加或更新服务可能需要重新编译整个内核。
- 代表:Linux、传统的UNIX系统(如System V、BSD)
微内核(Microkernel):
- 特点:微内核设计将基本的系统服务(如进程和通信管理)保留在内核中,而将其他服务(如文件系统、设备驱动)移到用户空间中。
- 优点:提高了系统的可靠性和安全性,因为用户空间中的服务崩溃不会直接影响内核;具有良好的可扩展性。
- 缺点:性能可能较低,因为用户空间和内核空间之间的通信开销较大。
- 代表:MINIX、QNX、L4微内核系列
混合内核(Hybrid Kernel):
-
特点:混合内核结合了单内核和微内核的特点,将一些核心服务保留在内核空间中以提高性能,同时将一些非核心服务移到用户空间中以增强安全性和可维护性。
-
优点:既提高了性能,又保持了较高的安全性和可维护性。
-
缺点:设计复杂,需要在性能和安全性之间做出权衡。
-
代表:Windows NT系列、macOS(XNU)
外核(Exokernel):
- 特点:外核设计允许应用程序直接访问物理资源,内核只提供最基本的安全性和资源分配服务。
- 优点:极高的灵活性和定制性,可以针对特定应用程序优化资源使用。
- 缺点:编程复杂,需要用户程序处理更多的底层细节。
- 代表:Cambridge Exokernel
模块化内核(Modular Kernel):
-
特点:模块化内核允许在系统运行时动态地加载和卸载内核模块,从而在不重启系统的情况下增加或删除功能。
-
优点:灵活性高,可以根据需要动态地扩展内核功能。
-
缺点:可能会增加系统的复杂性,模块间的兼容性也可能是一个问题。
-
代表:Linux(作为一个可选特性)
11. 总结rocky 启动流程,grub工作流程
12. 手写chkconfig服务脚本,可以实现服务的开始,停止,重启。
#!/bin/bash
# chkconfig: 2345 95 05
# description: My Custom Service
SERVICE_NAME=my_service
# 服务启动命令
start() {
echo "Starting $SERVICE_NAME service..."
/usr/bin/my_service --start
}
# 服务停止命令
stop() {
echo "Stopping $SERVICE_NAME service..."
/usr/bin/my_service --stop
}
# 服务重启命令
restart() {
echo "Restarting $SERVICE_NAME service..."
/usr/bin/my_service --restart
}
# 服务状态查询命令
status() {
echo "Checking $SERVICE_NAME service status..."
/usr/bin/my_service --status
}
# 根据输入参数调用相应函数
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
;;
esac
exit 0
13. 总结systemd服务配置文件
配置文件说明
[Unit] 部分
- Description: 服务的简短描述。
- After: 指定此服务应在哪些服务启动之后启动。
- Before: 指定此服务应在哪些服务启动之前启动。
- Wants: 弱依赖关系,表示如果某个服务启动,这个服务也应该启动。
- Requires: 强依赖关系,表示这个服务依赖于其他服务。
[Service] 部分
- Type: 服务类型,可以是 simple, forking, oneshot, notify, idle 等。
- ExecStart: 启动服务的命令。
- ExecStop: 停止服务的命令。
- ExecReload: 重载服务的命令。
- PIDFile: 服务的主进程 ID 文件路径。
- User 和 Group: 运行服务的用户和组。
- Restart: 定义何时重启服务,可以是 always, on-success, on-failure, on-abnormal, on-abort, on-watchdog 等。
- RestartSec: 定义重启服务前等待的秒数。
[Install] 部分
- WantedBy: 指定此服务应该由哪个目标(target)激活。常见的有 multi-user.target, graphical.target 等。
- Alias: 为服务提供一个别名。
14. 总结system启动流程
BIOS/UEFI自检(POST):
- 计算机执行加电自检(POST),检查硬件配置和功能。
- BIOS/UEFI从CMOS中读取启动顺序。
加载引导加载程序(Boot Loader):
-
BIOS/UEFI按照启动顺序尝试加载引导加载程序。
-
引导加载程序提供选择启动哪个Linux内核的界面。
-
引导加载程序加载选定的内核和initramfs到内存中。
内核初始化:
- 内核解压缩并开始执行。
- 内核初始化硬件,设置内存管理,加载驱动程序。
- 内核挂载根文件系统。
启动Systemd:
- 内核启动Systemd,Systemd成为PID 1进程。
- Systemd读取其配置文件,开始系统初始化。
Systemd基本配置:
- Systemd设置默认目标(target),通常是multi-user.target。
- Systemd设置主机名、启动交换分区、设置权限等。
Systemd启动服务:
- Systemd按照依赖关系顺序启动单元(units),包括服务(services)、挂载点(mounts)、设备(devices)等。
- Systemd启用通过systemctl enable命令标记为启动的服务。
用户空间初始化:
- Systemd启动用户空间的初始化脚本和服务。
- Systemd设置系统时钟、网络配置、文件系统检查等。
用户登录:
- 用户可以通过命令行或图形界面登录系统。
15. 总结awk工作原理,awk命令,选项,示例。
awk工作原理总结
awk是一个强大的文本分析工具,主要用于模式扫描和文本/数据提取。其工作原理可以概括为:awk会逐行读取输入文件或标准输入的内容,并将每行内容分割为若干个字段,然后根据指定的模式进行匹配,并执行相应的操作。这些操作可以是输出指定的字段、执行数学运算、比较和测试等。awk强大的地方在于它支持用户自定义函数和进行复杂的文本处理。
awk命令和选项
格式:
awk [options] 'pattern { action }' file...
常用选项:
-F fs:指定输入字段分隔符,默认为空格。
-v var=value:为awk程序分配一个变量。
-f scripfile:从指定的文件中读取awk脚本。
-m n:对awk进行n位数的内存分配。
–:在处理完命令行参数后,不再将命令行参数视为awk的选项。
16. 总结awk的数组,函数。
AWK 数组
数组定义:
- AWK 中的数组是关联数组,它们不需要预定义大小,并且可以包含任意数量的元素。
- 数组索引可以是数字或字符串。
数组赋值:
- 可以通过索引给数组元素赋值,例如:array[“index”] = value。
- AWK 也支持一次性给多个数组元素赋值,例如:array[“index1”, “index2”] = value1, value2。
遍历数组:
- 使用 for 循环可以遍历数组,例如:for (index in array) { print array[index] }。
- 这将遍历数组中的所有索引,并打印对应的值。
删除数组元素:
- 可以使用 delete 关键字删除数组元素,例如:delete array[“index”]。
多维数组:
- AWK 支持模拟多维数组,通过使用逗号分隔的索引来创建数组的数组。
AWK 函数
内置函数:
- AWK 提供了一系列内置函数,用于执行数学、字符串操作和其他实用功能。
- 例如,length() 函数返回字符串的长度,rand() 函数返回一个随机数。
用户定义函数:
- 用户可以定义自己的函数,使用 function 关键字,
函数调用: - 函数可以通过其名称和参数列表来调用,例如:result = myfunction(arg1, arg2)。
局部变量和全局变量:
- 在函数内部声明的变量默认是局部的,不会影响 AWK 的全局变量。
- 如果需要在函数中使用全局变量,可以使用 global 关键字。
递归调用:
- AWK 支持函数的递归调用,允许函数调用自身。
17. 总结ca管理相关的工具,根据使用场景总结示例。
18. 总结对称加密和非对称加密算法和用openssl签发证书步骤
对称加密算法:
- 密钥生成:使用密钥生成算法(如AES)生成密钥。
- 加密:使用生成的密钥对数据进行加密。
- 解密:使用相同的密钥对加密的数据进行解密。
- 缺点:密钥的传输和存储存在安全风险。
非对称加密算法:
- 密钥对生成:使用非对称加密算法生成一对密钥:公钥和私钥。
- 加密:使用公钥对数据进行加密。
- 解密:使用私钥对加密的数据进行解密。
- 缺点:密钥长,算法复杂,加密解密效率低下