目录
1.while循环
while 循环是 Linux shell 编程中的一种常用的循环结构,它可以根据一个条件或者一个文件的内容来重复执行一段代码。while 循环的语法有以下几种形式:
#根据条件判断
while CONDITION; do
循环体
done
#逐行处理文件
while read line; do
循环体
done < /etc/passwd
##逐行处理/etc/passwd文件中的每一行,赋值给变量line
#无限循环
while true; do
循环体
done
1.2利用逐行处理计算passwd id总和
while read line
do
current_uid=$(echo $line | awk -F: '{print $3}')
##current_uid=$(echo $line | cut -d ":" -f 3) #也可以用这个
total_uid=$((total_uid + current_uid))
done < "/etc/passwd"
2.数组
declare [选项] 变量名
选项:
-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示已定义的所有函数名及其内容
-F 仅显示已定义的所有函数名
-x 声明或显示环境变量和函数,相当于export
-l 声明变量为小写字母 declare -l var=UPPER
-u 声明变量为大写字母 declare -u var=lower
2.1索引数组
索引数组:数组中各个元素所对应的索引值为数字,从 0 开始。可以直接赋值或使用 declare -a 命令定义。例如:
#直接定义数组
ARRY_NAME=(luo lll ccc)
[20:38:53root@localhost bin]# echo ${ARRY_NAME[*]}
luo lll ccc #查看数组内的全部内容
[20:39:08root@localhost bin]# echo ${ARRY_NAME[1]}
lll #查看单一数组
#declare -a ARRY_NAME #定义索引数组
[20:37:24root@localhost bin]# ARRY_NAME[0]=wang
[20:37:59root@localhost bin]# ARRY_NAME[1]=lll
[20:38:05root@localhost bin]# ARRY_NAME[2]=ccc
[20:38:09root@localhost bin]# echo ${ARRY_NAME[*]}
wang lll ccc
2.2关联数组
关联数组:数组中各个元素所对应的索引值为字符串,可以自定义索引名。必须使用 declare -A 命令声明数组:
[20:42:35root@localhost bin]# declare -A ARRY_AA #声明关联数组
[20:42:48root@localhost bin]# ARRY_AA[aaa]=1
[20:43:19root@localhost bin]# ARRY_AA[lll]=2
[20:43:24root@localhost bin]# ARRY_AA[ccc]=3
[20:43:29root@localhost bin]# echo ${#ARRY_AA[*]}
3 #查看数组内容个数
[20:44:29root@localhost bin]# echo ${!ARRY_AA[*]}
ccc lll aaa #查看所有关联数组的下标
2.3字符串处理
基于偏移量取字符串:使用 $ {var:offset:length} 的格式,可以从变量 var 中提取指定位置和长度的子字符串。例如:
[20:44:39root@localhost bin]# luomu="luomuxiaomidi"
[20:46:33root@localhost bin]# echo ${luomu:3:4}
muxi #切片,跳过三个取四个
[20:47:05root@localhost bin]# echo ${luomu: -3}
idi #切片,取后三个
[20:47:08root@localhost bin]# echo ${luomu:3:-4}
muxiao
#切片跳过前3和后四个,取中间
2.4求10个随机数的最大值与最小值
#!/bin/bash
declare -i maxnum=0
declare -i minnum=0
for i in {0..9};do
myrandom=$RANDOM
#先赋值一个随机数
[ $i -eq 0 ] && minnum=$myrandom
#先定义第一个随机数
nums[$i]=${myrandom}
#记录每一个随机数
if [ $myrandom -ge $maxnum ];then
#判断随机数是否大于最大值,大于赋值到最大值
maxnum=$myrandom
fi
if [ $minnum -ge $myrandom ];then
#先那定义的初始值比较得到最小值,在通过循环得到的值比较,最小值大于随机数,就定义随机数为最小值
minnum=$myrandom
fi
done
echo "数字:${nums[*]}"
echo "最大值:$maxnum"
echo "最小值:$minnum"
#打印出来
3.函数递归调用,实现阶乘算法
#!/bin/bash
factorial () {
if [[ $1 -eq 0 || $1 -eq 1 ]]; then
#定义0和1的阶乘,和定义了阶乘的结尾
echo 1
else
temp=$(factorial $[ $1 - 1 ])
#递归调用函数,算出$1-1的阶乘
echo $(( $1 * $temp ))
#最终由1的阶乘依次成于$1
fi
}
read -p "请输入一个正整数: " num
result=$(factorial $num)
echo "$num 的阶乘是 $result"
4.进程和线程的区别
进程和线程是操作系统中的两个重要概念。进程是程序执行时的一个实例,它拥有独立的内存空间和系统资源,是系统资源分配的基本单位。线程是进程中的一个执行单元,是CPU调度的基本单位,它与同一进程中的其他线程共享进程的内存空间和系统资源。进程和线程的主要区别包括以下几点:
1.资源使用:进程拥有独立的内存空间和文件描述等系统资源,而线程共享父进程的所有资源。
2.调度和切换:进程切换时需要保存当前状态,加载新的进程,这个过程相对较慢;线程切换时只需保存线程上下文信息即可,进度比进程切换快。
3.并发能力:多进程可以充分利用多核CPU进行并发处理,而多线程则依赖于单个CPU的多个执行单元(如超线程或多核)进行并发执行。
4.安全性:由于线程共享同一进程的资源,因此线程之间的访问需要进行协调和同步,否则会出现竞争条件和死锁的问题。
4.1进程概念
进程是操作系统中的一个重要概念,它是程序执行时的一个实例,拥有独立的内存空间和系统资源,是系统资源分配的基本单位。进程由程序段、数据段和进程控制块三部分组成。其中,程序段是能被进程调度程序调度到 CPU 执行的程序代码段;数据段则是进程对应的程序加工处理的原始数据,也可以是程序执行时产生的中间或最终结果;进程控制块(PCB)则是进程的核心数据结构,用于描述进程的状态信息、控制和管理信息、资源分配清单和处理机相关信息等。PCB 是操作系统管理进程的重要手段,是操作系统进行资源分配和调度的基本单元
5.OOM
OOM 即 Out Of Memory,“内存用完了”,在情况在java程序中比较常见。系统会选一个进程将之杀死,
在日志messages中看到类似下面的提示
Jul 10 10:20:30 kernel: Out of memory: Kill process 9527 (java) score 88 or sacrifice child
原因:
给应用分配内存太少:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。
应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。
使用的解决办法:
1,限制java进程的max heap,并且降低java程序的worker数量,从而降低内存使用
2,给系统增加swap空间
说明:
Linux默认是允许memory overcommit的,只要你来申请内存我就给你,寄希望于进程实际上用不到那
么多内存,但万一用到那么多了呢?Linux设计了一个OOM killer机制挑选一个进程出来杀死,以腾出部
分内存,如果还不够就继续。也可通过设置内核参数 vm.panic_on_oom 使得发生OOM时自动重启系
统。这都是有风险的机制,重启有可能造成业务中断,杀死进程也有可能导致业务中断。所以Linux 2.6
之后允许通过内核参数 vm.overcommit_memory 禁止memory overcommit
vm.overcommit_memory 接受三种取值:
0 – Heuristic overcommit handling. 这是缺省值,它允许overcommit,但过于明目张胆的
overcommit会被拒绝,比如malloc一次性申请的内存大小就超过了系统总内存。Heuristic的意思是“试探式的”,内核利用某种算法猜测你的内存申请是否合理,它认为不合理就会拒绝overcommit。
1 – Always overcommit. 允许overcommit,对内存申请来者不拒。内核执行无内存过量使用处理。使用这个设置会增大内存超载的可能性,但也可以增强大量使用内存任务的性能。
2 – Don’t overcommit. 禁止overcommit。 内存拒绝等于或者大于总可用 swap 大小以及overcommit_ratio 指定的物理 RAM 比例的内存请求。如果希望减小内存过度使用的风险,这个设置就是最好的
设置内核参数:
vm.overcommit_ratio = 90
#默认为 50,为物理内存分配时的比例
#只有当 vm.overcommit_memory = 2 的时候才会生效
/proc/sys/vm/panic_on_oom
#是一个内核参数,它控制当系统内存不足时,内核是否会触发 panic
/proc/sys/vm/overcommit_memory
#是一个内核参数,它影响内核允许分配的虚拟内存量。它的值可以是0、1、2
6.进程管理
Linux系统中,进程有5种状态:TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_STOPPED和TASK_TRACED
6.1 ps
用于显示当前进程的状态。常用参数有 -ef 和 -aux
常见的状态字符有 D、R、S、T、W、X、Z、<、N、L 和 +
其中,R 表示可执行状态,S 表示可中断的睡眠状态,D 表示不可中断的睡眠状态,T 表示暂停状态或跟踪状态1
[23:38:25root@localhost ~]# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 172252 4848 ? Ss 14:02 0:01 /usr/lib/systemd/systemd --switched-root --syst
root 2 0.0 0.0 0 0 ? S 14:02 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 14:02 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< 14:02 0:00 [rcu_par_gp]
root 6 0.0 0.0 0 0 ? I< 14:02 0:00 [kworker/0:0H-events_highpri]
root 9 0.0 0.0 0 0 ? I< 14:02 0:00 [mm_percpu_wq]
root 10 0.0 0.0 0 0 ? S 14:02 0:00 [ksoftirqd/0]
root 11 0.0 0.0 0 0 ? R 14:02 0:01 [rcu_sched]
root 12 0.0 0.0 0 0 ? S 14:02 0:00 [migration/0]
用户名 进程id 进程占用cpu百分比 进程占用内存百分比 进程使用的虚拟内存 进程占用固定内存量 进程允许的终端 进程状态 进程启动时间 实际使用cpu时间 命令的名称和参数
6.2 top
top:用于显示当前正在运行的进程。常用参数有 -p 和 -b。其中,-p 用于查看指定的某一个进程,-b 用于让 top 命令执行一次后结果保存到文件中
top - 23:49:22 up 9:46, 2 users, load average: 0.17, 0.06, 0.01
Tasks: 203 total, 2 running, 201 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1790.2 total, 916.8 free, 621.8 used, 251.6 buff/cache
MiB Swap: 2048.0 total, 2011.9 free, 36.1 used. 1023.5 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12183 root 20 0 6155672 478400 18896 S 0.3 26.1 0:45.61 java
1 root 20 0 172252 4848 3548 S 0.0 0.3 0:01.65 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp
6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H-events_highpri
9 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq
10 root 20 0 0 0 0 S 0.0 0.0 0:00.23 ksoftirqd/0
11 root 20 0 0 0 0 I 0.0 0.0 0:01.40 rcu_sched
12 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
6.2.1top显示信息详解
top - 23:49:22 up 9:46, 2 users, load average: 0.17, 0.06, 0.01
内容 | 含义 |
---|---|
14:49:28 | 表示当前时间 |
up 9:46 | 系统远行时间,格式为时:分 |
2 users | 当前登陆用户数 |
load average: 0.17, 0.06, 0.01 | 系统负载,即任务队列的平均长度。 三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值 |
Tasks: 203 total, 2 running, 201 sleeping, 0 stopped, 0 zombie
内容 | 含义 |
---|---|
Tasks: 203 total | 进程总数 |
2 running | 正在运行的进程数 |
201 sleeping | 睡眠的进程数 |
0 stopped | 停止的进程数 |
0 zombie | 僵尸进程数 |
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
内容 | 含义 |
---|---|
0.0%us | 用户空间占用CPU百分比 |
0.0%sy | 内核空间占用CPU百分比 |
0.0%ni | 用户进程空间内改变过优先级的进程占用CPU百分比 |
100.0%id | 空闲CPU百分比 |
0.0%wa | 等待输入输出的CPU时间百分比 |
0.0%hi | 硬中断(Hardware IRQ)占用CPU的百分比 |
0.0%si | 软中断(Software Interrupts)占用CPU的百分比 |
0.0 st | 用于有虚拟cpu的情况,用来指示被虚拟机偷掉的cpu时间 |
MiB Mem : 1790.2 total, 916.8 free, 621.8 used, 251.6 buff/cache
内容 | 含义 |
---|---|
1790.2 total | 物理内存总量 |
916.8 free | 使用的物理内存总量 |
621.8 free | 空闲内存总量 |
251.6 buffers | 用作内核缓存的内存量 |
MiB Swap: 2048.0 total, 2011.9 free, 36.1 used. 1023.5 avail Mem
内容 | 含义 |
---|---|
2048.0 total total | 交换区总量 |
36.1 used | 使用的交换区总量 |
2011.9 free | 空闲交换区总量 |
1023.5 cached | 缓冲的交换区总量 |
进程信息
内容 | 含义 |
---|---|
PID | 进程id |
USER | 进程所有者的用户名 |
PR | 优先级 |
NI | nice值。负值表示高优先级,正值表示低优先级 |
VIRT | 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES |
RES | 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA |
SHR | 共享内存大小,单位kb |
S | 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程 |
%CPU | 上次更新到现在的CPU时间占用百分比 |
%MEM | 进程使用的物理内存百分比 |
TIME+ | 进程使用的CPU时间总计,单位1/100秒 |
COMMAND | 命令名/命令行 |
6.3 pstree
linux最小化默认不安装
yum -y install psmisc
[00:05:28root@localhost ~]# pstree #树状显示进程
systemd─┬─NetworkManager───2*[{NetworkManager}]
├─VGAuthService
├─auditd───{auditd}
├─automount───5*[{automount}]
├─crond
├─dbus-daemon
├─login───bash
├─polkitd───5*[{polkitd}]
├─rsyslogd───2*[{rsyslogd}]
├─sshd───sshd───sshd───bash───pstree
├─sssd─┬─sssd_be
│ └─sssd_nss
├─systemd───(sd-pam)
├─systemd-journal
├─systemd-logind
├─systemd-udevd
├─vmtoolsd───2*[{vmtoolsd}]
└─wrapper-linux-x─┬─java───29*[{java}]
└─{wrapper-linux-x}
[00:05:32root@localhost ~]# pstree -p #显示pid和线程子进程
systemd(1)─┬─NetworkManager(834)─┬─{NetworkManager}(867)
│ └─{NetworkManager}(871)
├─VGAuthService(836)
├─auditd(796)───{auditd}(797)
├─automount(941)─┬─{automount}(945)
│ ├─{automount}(946)
│ ├─{automount}(947)
│ ├─{automount}(962)
│ └─{automount}(968)
├─crond(950)
├─dbus-daemon(831)
├─login(956)───bash(1418)
├─polkitd(829)─┬─{polkitd}(866)
│ ├─{polkitd}(870)
│ ├─{polkitd}(879)
│ ├─{polkitd}(880)
│ └─{polkitd}(916)
7.IPC通信和RPC
IPC(进程间通信)和RPC(远程过程调用)都是用于进程间通信的方式。IPC是指在同一台计算机上的进程之间进行通信的方式,而RPC是指在不同计算机上的进程之间进行通信的方式.
7.1IPC
IPC通信方式包括管道、命名管道、消息队列、信号量、共享内存等213. 管道是速度较慢、容量有限、只有父子进程能通讯的方式;命名管道FIFO是任何进程间都能通讯,但速度较慢的方式;消息队列容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题;信号量不能传递复杂消息,只能用来同步,需要配合共享内存实现进程间数据传输.
7.2PRC
RPC通信方式是一种隐藏了过程调用时实际通信细节的IPC方法. 客户端将调用一个本地方法,而这个本地方法则是负责透明的与远程服务端进行过程间通信. RPC的主要核心作用是RPC的服务函数寻址、数据的序列化和反序列化、网络传输和协议
8.秒杀高并发问题
mkfifo是Linux中的一个命令,可以创建FIFO(命名管道),通过FIFO可以实现进程间通信。cat命令则可以读取FIFO中的数据。秒杀是一种高并发场景,如果不做任何处理,系统可能会宕掉。使用消息队列可以将需要处理的消息全部放入其中,系统按照最大处理能力,去获取消息进行消费,这样就可以将一瞬间过来的请求,分散到一段时间内进行处理,避免了系统的崩
8.1消息队列
借鉴
原文:https://www.cnblogs.com/ffdsj/p/12369951.html
不使用消息队列:
1.耦合度高:如果您的系统中各个模块之间的耦合度较高,那么当您需要更改其中一个模块时,可能会影响到其他模块的正常运行。
2.可拓展性差:如果您的系统需要处理大量的请求,那么在没有消息队列的情况下,可能会导致系统崩溃或响应时间变慢。
3.无法异步处理:如果您的系统需要处理一些不需要即时返回结果的操作,那么在没有消息队列的情况下,可能会导致请求的响应时间变慢。
4.无法削峰:如果您的系统需要处理突发的高并发请求,那么在没有消息队列的情况下,可能会导致系统崩溃或响应时间变慢。
1.当我们不使用消息队列的时候,所有用户的请求都会直接落到服务器上,然后通过数据库或者缓存相应,假如在高并发的环境下,如果没有缓存或者数据库承受不了那么大的压力的话,就会造成响应速度缓慢,甚至造成数据库宕机。因此这时候如果使用消息队列,用户发送的请求数据发送给了消息队列之后就可以立即返回,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库。由于消息队列服务器的处理速度大于数据库,因此响应速度大幅度提高
2.另外消息队列还具有一定的削峰的作用——通过异步处理,将短时间内高并发产生的事务消息存储在消息队列当中,从而削平高峰期的并发事务。比如一些电商网站的秒杀和促销活动都是用消息队列来缓解对系统的冲击,当然这时用户请求的压力也就变成了消息队列的压力。
消息队列是一种用于解耦、异步和削峰的通信方式,它可以将不同模块之间的耦合度降低,从而提高系统的可拓展性。消息队列的主要优点是解耦,它可以将不同模块之间的耦合度降低,从而提高系统的可拓展性。消息队列还可以实现异步处理、流量削峰、消息通讯、日志处理等功能。但是,引入消息队列也会增加系统的复杂性,需要额外的组件和配置,对开发者和运维人员的要求较高。因此,在使用消息队列时,需要权衡其优缺点,合理设计和配置,以满足系统的需求
当然消息队列也不是没有缺点的:
1.系统可用性降低:引入消息队列会增加系统的复杂性,需要额外的组件和配置,对开发者和运维人员的要求较高。如果消息队列出现故障,整个系统可能会崩溃。
2.系统复杂度提高:引入消息队列会增加系统的复杂性,需要额外的配置和管理。例如,需要考虑消息重复消费、消息丢失、消息传递顺序等问题。
3.一致性问题:如果消息队列中的消息被重复消费或丢失,可能会导致系统数据不一致
9.总结rocky 启动流程,grub工作流程
9.1 Centos6启动流程
1.计算机开启后,BIOS自动执行POST
2.BIOS会寻找可启动设备,通常会先寻找硬盘、光驱和USB设备
3.当BIOS找到可启动设备后,将引导扇区(boot sector)加载到内存中,并将控制权交给引导扇区程序
4.引导扇区程序会加载GRUB(Grand Unified Bootloader)引导程序。GRUB是CentOS 6默认的引导程序
5.GRUB会显示启动菜单,让用户选择要启动的操作系统
6.用户选择了操作系统或内核后,GRUB会加载内核文件和启动选项,并将控制权交给内核
7.内核会初始化硬件、加载驱动程序、挂载文件系统等操作
8.内核完成初始化后,会运行/sbin/init程序,此时系统进入用户空间
9./sbin/init程序会根据配置文件/etc/inittab启动各种服务,并设置系统运行级别
9.2Rocky 7 及以上
1.UEFI或者BIOS初始化,
2.选择设备启动
3. 引导装载程序, centos7是grub2,加载装载程序的配置文件:/etc/grub.d/,/etc/default/grub,/boot/grub2/grub.cfg
4. 加载initramfs驱动模块(可以实现根文件系统的挂载)
5. 加载虚拟根中的内核
6. 虚拟根的内核初始化,Centos7使用systemd代替init,第一个进程
7. 执行initrd.target 所有单元,包括挂载 /etc/fstab
8. 从initramfs根文件系统切换到磁盘根目录
9. systemd执行默认target配置,配置文件/etc/systemd/system/default.target
10. systemd执行sysinit.target初始化系统及basic.target准备操作系统
11. systemd启动multi-user.target 下的本机与服务器服务
12. systemd执行multi-user.target 下的/etc/rc.d/rc.local
13. systemd执行multi-user.target下的getty.target及登录服务
启动流程图:
9.3 grub工作流程
1.当系统启动时,如果要加载GRUB所在的磁盘时,会读取这个磁盘的MBR,同时会加载stage1。
2.stage1会尝试读取后扇区的stage1_5阶段,stage1_5阶段会帮助stage1中的bootloader识别stage2所在的分区上的文件系统,然后加载stage2所在的磁盘分区,这个分区不但有stage2阶段,还有内核和ramdisk等。
3.stage2的主要功能是提供菜单、加载用户选择的内核或操作系统、为菜单提供保护机制等。