Linux,第四篇
自定义写出10个定时任务
备份配置文件
以/etc为例,其他配置文件同理
实现案例
每周日的工作日1:30,将/etc备份至/backup目录中,保存的文件名格式为“etcbak-yyyy-mm-dd-HH.tar.xz”,其中日期是前一天时间
#脚本路经名称为/root/backup_etc.sh
#!/bin/bash
#获取前一日时间
Yesterday_time(){
Yesterday=$(date "+%Y-%d-%H-%M" -d "-1 days")
}
#打包压缩备份
backup(){
tar Jcvf /backup/etcbak-$Yesterday.tar.gz /etc &> /dev/null
}
main(){
Yesterday_time
backup
}
main
#crontab -e 配置写法
30 1 * * 0 /root/backup_etc.sh
直接运行脚本结果
[root@localhost backup]# pwd
/backup
[root@localhost backup]# date
Mon Aug 7 17:34:38 CST 2023
[root@localhost backup]# bash /root/backup_etc.sh
[root@localhost backup]# ls
etcbak-2023-06-17-34.tar.gz
每2小时记录系统内存使用情况
以内存为例,cpu等资源同理
实现案例
#脚本路经名称为/root/MEM.sh
#!/bin/bash
MEM(){
date >> /tmp/meminfo.txt
cat /proc/meminfo|grep -e ^M -e ^S >> /tmp/meminfo.txt
}
MEM
#crontab -e 配置写法
0 */2 * * * /root/MEM.sh
每两小时取出当前系统/proc/meminfo文件中以S或M开头的信息追加至/tmp/meminfo.txt文件中
直接运行脚本结果
[root@localhost tmp]# pwd
/tmp
[root@localhost tmp]# bash /root/MEM.sh
[root@localhost tmp]# ls
meminfo.txt vmware-root_655-4021587944
[root@localhost tmp]# cat meminfo.txt
Mon Aug 7 17:43:51 CST 2023
MemTotal: 1838424 kB
MemFree: 1087620 kB
MemAvailable: 1434736 kB
SwapCached: 0 kB
Mlocked: 0 kB
SwapTotal: 2097148 kB
SwapFree: 2097148 kB
Mapped: 26156 kB
Shmem: 9736 kB
Slab: 87040 kB
SReclaimable: 40420 kB
SUnreclaim: 46620 kB
定时巡检硬盘空间,并告警
实现案例
工作日时间,每10分钟执行一次磁盘空间检查,一旦发现任何分区利用率高于80%,就执行wall警报
#脚本路经名称为/root/disk_warning.sh
#!/bin/bash
disk_warning(){
df_data=$(df|awk '{print $5$6}'|tail -n+2)
for i in $df_data;
do
{
value=`echo $i | cut -d% -f1`
Partition=`echo $i | cut -d% -f2`
[ $value -ge 80 ]&& wall "Partition utilization rate above $value%,$Partition"
}
done
}
disk_warning
#crontab -e 配置写法
*/10 * * * 1-5 /root/MEM.sh
直接运行脚本结果
[root@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 886M 0 886M 0% /dev
tmpfs 898M 0 898M 0% /dev/shm
tmpfs 898M 9.6M 889M 2% /run
tmpfs 898M 0 898M 0% /sys/fs/cgroup
/dev/mapper/centos-root 47G 1.8G 46G 4% /
/dev/sda1 1014M 151M 864M 15% /boot
tmpfs 180M 0 180M 0% /run/user/0
tmpfs 1.0M 1.0M 0 100% /mnt/ramdisk
tmpfs 5.0M 4.0M 1.0M 80% /mnt/ramdisk2
[root@localhost ~]# bash /root/disk_warning.sh
[root@localhost ~]#
Broadcast message from root@localhost.localdomain (pts/0) (Mon Aug 7 18:45:38 2023):
Partition utilization rate above 100%,/mnt/ramdisk
Broadcast message from root@localhost.localdomain (pts/0) (Mon Aug 7 18:45:38 2023):
Partition utilization rate above 80%,/mnt/ramdisk2
想到再做,时间不是很充裕
图文并茂说明Linux进程和内存概念
什么是进程
Process: 运行中的程序的一个副本,是被载入内存的一个指令集合,是资源分配的单位
- 进程ID(Process ID,PID)号码被用来标记各个进程
- UID、GID、和SELinux语境决定对文件系统的存取和访问权限
- 通常从执行进程的用户来继承
- 存在生命周期
进程创建:
- init:第一个进程,从 CentOS7 以后为systemd
- 进程:都由其父进程创建,fork(),父子关系,CoW:Copy On Write
进程
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。
进程的组成
进程一般由程序、数据集合和进程控制块三部分组成。
程序用于描述进程要完成的功能,是控制进程执行的指令集;
数据集合是程序在执行时所需要的数据和工作区;
程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的唯一标
志。
进程具有的特征:
动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;
并发性:任何进程都可以同其他进程一起并发执行;
独立性:进程是系统进行资源分配和调度的一个独立单位;
结构性:进程由程序、数据和进程控制块三部分组成。
内存:物理地址空间和虚拟地址空间
MMU:Memory Management Unit 负责虚拟地址转换为物理地址
程序在访问一个内存地址指向的内存时,CPU不是直接把这个地址送到内存总线上,而是被送到MMU
(Memory Management Unit),然后把这个内存地址映射到实际的物理内存地址上,然后通过总线再去
访问内存,程序操作的地址称为虚拟内存地址
TLB:Translation Lookaside Buffer 翻译后备缓冲区,用于保存虚拟地址和物理地址映射关系的缓存
进程运行与资源调度
进程使用内存问题
内存泄漏:Memory Leak
指程序中用malloc或new申请了一块内存,但是没有用free或delete将内存释放,导致这块内存一直处
于占用状态
内存溢出:Memory Overflow
指程序申请了10M的空间,但是在这个空间写入10M以上字节的数据,就是溢出,类似红杏出墙(N50学炳
语录)
内存不足: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
当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个
error,因为这个问题已经严重到不足以被应用处理)。
原因:
- 给应用分配内存太少:比如虚拟机本身可使用的内存(一般通过启动时的VM参数指定)太少。
- 应用用的太多,并且用完没释放,浪费了。此时就会造成内存泄露或者内存溢出。
使用的解决办法:
- 限制java进程的max heap,并且降低java程序的worker数量,从而降低内存使用
- 给系统增加swap空间
设置内核参数(不推荐),不允许内存申请过量:
echo 2 > /proc/sys/vm/overcommit_memory
echo 80 > /proc/sys/vm/overcommit_ratio
echo 2 > /proc/sys/vm/panic_on_oom
进程状态
进程的基本状态
- 创建状态:进程在创建时需要申请一个空白PCB(process control block进程控制块),向其中填写
控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调
度运行,把此时进程所处状态称为创建状态 - 就绪状态:进程已准备好,已分配到所需资源,只要分配到CPU就能够立即运行
- 执行状态:进程处于就绪状态被调度后,进程进入执行状态
- 阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受
到阻塞。在满足请求时进入就绪状态等待系统调用 - 终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行
状态之间转换六种情况
运行——>就绪:1,主要是进程占用CPU的时间过长,而系统分配给该进程占用CPU的时间是有限的;
2,在采用抢先式优先级调度算法的系统中,当有更高优先级的进程要运行时,该进程就被迫让出CPU,
该进程便由执行状态转变为就绪状态
就绪——>运行:运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配CPU
运行——>阻塞:正在执行的进程因发生某等待事件而无法执行,则进程由执行状态变为阻塞状态,如发
生了I/O请求
阻塞——>就绪:进程所等待的事件已经发生,就进入就绪队列
以下两种状态是不可能发生的:
阻塞——>运行:即使给阻塞进程分配CPU,也无法执行,操作系统在进行调度时不会从阻塞队列进行挑
选,而是从就绪队列中选取
就绪——>阻塞:就绪态根本就没有执行,谈不上进入阻塞态
进程更多的状态:
- 运行态:running
- 就绪态:ready
- 睡眠态:分为两种,可中断:interruptable,不可中断:uninterruptable
- 停止态:stopped,暂停于内存,但不会被调度,除非手动启动
- 僵死态:zombie,僵尸态,结束进程,父进程结束前,子进程不关闭,杀死父进程可以关闭僵死
态的子进程
图文并茂说明Linux启动流程
centos 7启动流程
-
UEFi或BIOS初始化,运行POST开机自检
-
选择启动设备
-
引导装载程序,centos 7是grub2,加载装载程序的配置文件
/etc/grub.d/ /etc/default/grub /boot/grub2/grub.cfg
-
加载initramfs驱动模块
-
加载内核选项
-
内核初始化,centos 7使用systemd代替init
-
执行initrd.garget所有单元,包括挂载 /etc/fstab
-
从initramfs根文件系统切换到磁盘根目录
-
systemd执行默认target配置,配置文件/etc/systemd/system/default.target
-
systemd执行sysinit.target初始化系统及basic.target准备操作系统
-
systemd启动multi-user.target下的本机与服务器服务
-
systemd执行multi-user.target下的/etc/rc.d/rc.local
-
systemd执行multi-user.target下的getty.target及登录服务
-
systemd执行graphical需要的服务
自定义一个systemd服务定时去其他服务器上检查/tmp/下文件的个数,如果发现数量有变化就记录变化情况到文件中
#!/bin/bash
#文件路径为/root/check_tmp_file.sh
#从文件中读取IP地址池
ip_list=($(cat /tmp/tmp_ip.txt))
#保存服务启动时 /tmp 目录文件名,按照每个ip独立存储目标主机文件内容
function firstime_data(){
for ip in ${ip_list[@]}; do
if [[ ! -f /tmp/tmp_ip-orig-file-$ip ]];then
ssh root@$ip "find /tmp -type f" > /tmp/tmp_ip-orig-file-$ip 2> /dev/null
fi
done
}
#定时扫描目标主机 /tmp 目录,并将差异情况保存到日志文件
function check_file(){
for ip in ${ip_list[@]}; do
ssh root@$ip "find /tmp -type f" > /tmp/tmp_ip-orig-file-$ip 2> /dev/null
echo `date +"%F %T"` [INFO] Start to check /tmp directory file number on $ip ... >> /tmp/tmp_ip-orig-file-$ip-`date +"%F"`.log
awk '{if(ARGIND==1) {val[$0]} \
else{ if($0 in val) { delete val[$0]} \
else {val2[$0]}}}\
END{for(i in val) {if(i!="") print "删除文件:"i};\
for(j in val2){if(j !="") print "新增文件:"j}}'\
/tmp/tmp_ip-orig-file-$ip /tmp/tmp-check-file-$ip >> /tmp/change_log_$ip-`date +"%F"`.log
echo -e `date +"%F %T"` [INFO] Check /tmp directory file number end ..."\n" >> /tmp/change_log_$ip-`date +"%F"`.log
done
}
function main(){
firstime_data
check_file
}
main
chmod +x check_tmp_file.sh
在 /usr/lib/systemd/system/ 下边创建服务文件
cat /etc/systemd/system/checktmp.service
[Unit]
Description=Check /tmp directory file for changes
[Service]
Type=Simple
TimeoutStartSec=0
ExecStart=/bin/sh -c "while true; do /root/check_tmp_file.sh; sleep 7200; done"
ExecStop=/bin/kill -s QUIT ${MAINPID}
[Install]
WantedBy=multi-user.target
设置开机启动并立即生效checktmp服务
systemctl daemon-reload
systemctl enable --now checktmp
写Linux内核编译安装
1.下载linux内核
https://www.kernel.org/
2.将下载的内核包上传到linux
3.安装编译时所用到的工具包
yum -y install gcc make ncurses-devel flex bison openssl-devel
elfutils-libelf-devel bc perl
4.解压内核包到/usr/local/src目录
tar xf linux-5.18.9.tar.xz -C /usr/local/src
cd /usr/local/src/linux-5.18.9
#配置内核,拷贝当前内核的配置文件,然后使用 menuconfig 命令来做任何必要的更改
cp /boot/config-$(uname -r) .config
#选择启用或者禁用一些模块。如果你不知道该如何选择的话,默认退出即可
make menuconfig
#编译内核,-j后面代表CPU核数,根据你机器的核数决定,数字越大编译速度越快
make -j 8
#安装,安装过程分为两部分,首先对内核模块进行安装,这个过程会将刚刚编译内核模块时生成的内核模块复制到/lib/modules/5.14.17/目录下,其中5.14.17为对应的内核版本。
make modules_install
make install
#重启操作系统
reboot
总结5个自我觉得比较有用的awk的使用场景
awk基本结构:
awk 'BEGIN{print} pattern{commands} END{print}' file
#1.查询登录不成功的主机及次数
lastb | head -n -2 | awk '{print $3}' | sort | uniq -c |sort -nr
#2.查看磁盘使用率大于等于80%的
df | awk -F "[[:space:]]+|%" 'NR>1{if($5>=80)print $7,$5"%"}'
#3.取出用户和组
awk -F":" '{print $1,$5}' /etc/passwd
#4.求文件每列的最大值
awk 'BEGIN{max = 0} {if ($1>max) max=$1 fi} END{print "Max=",max}' abc.txt
#5.按需要的格式输出内存使用情况
free -m|awk '/^Mem/{printf"已使用内存:%sm\n当前空闲内存:%sm\n内存使用率:%.2f%\n",$3,$4,$3/$2*100}'
在什么情况下用awk处理文本效率最高
范例:在循环运算中,awk效率最高
[root@localhost ~]# time(awk -v num=0 'BEGIN{for(i=1;i<=1000000;i++){ num+=i};print num}')
500000500000
real 0m0.052s
user 0m0.051s
sys 0m0.000s
[root@localhost ~]# time( num=0;for((i=1;i<=1000000;i++)) ;do let num=$((num + i)) ;done ;echo $num)
500000500000
real 0m6.324s
user 0m5.916s
sys 0m0.397s
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异