1、自定义写出10个定时任务的示例:
1.1 每隔5分钟检查一次磁盘占用率
[21:16:16 root@rocky scripts]$ cat while_diskcheck.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-17
#FileName: while_diskcheck.sh
#Description: 定时检查磁盘并发送报警邮件
#***********************************************************
WARNING=80
while :;do
df -h|grep '^/dev'|sed -rn 's/.* ([0-9]+)%.*/\1/p'|while read line;do
if [ $line -gt $WARNING ];then
echo Disk will be full from `hostname -I`|mail -s "disk warning" lgq6579@163.com
fi
done
sleep 5m
done
[21:21:04 root@rocky data]$ crontab -l
*/5 * * * * sh /data/scripts/while_diskcheck.sh &> /data/log/disk_check-`date +\%F_\%T`.log
1.2 每周工作日00:30备份/data/scripts目录到/backup目录,保存的文件名称格式为“scripts-yyyy-mm-dd-
HH.tar.xz”,其中日期是前一天的时间
[21:33:06 root@rocky scripts]$ cat backup.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-03
#FileName: backup.sh
#Description: 定时备份
#***********************************************************
COLOR='echo -e \E[1;35m'
END='\E[0m'
${COLOR}"Backup is staring!"${END}
tar zcf /backup/scripts-`date -d '-1 day' +%Y-%m-%d-%H`.tar.gz /data/scripts
${COLOR}"Backup is finished!"${END}
[21:33:10 root@rocky scripts]$ crontab -l
10 0 * * * 3 sh /data/scripts/backup.sh &> /data/log/backup.log
1.3 每隔两个月的每隔10天扫描一下网段在线状态
[21:37:07 root@rocky scripts]$ cat for_scan_host.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-17
#FileName: for_scan_host.sh
#Description: 扫描一个网段:10.0.0.0/24,判断此网段
# 中主机在线状态,将在线的主机IP打印出来
#***********************************************************
NET=10.0.0
for i in {1..254};do
{
if ping -c1 -W1 $NET.$i &> /dev/null;then
echo $NET.$i is up >> /data/log/scan_host.log
fi
}&
done
[21:42:07 root@rocky scripts]$ crontab -l
* * */10 */2 * sh /data/scripts/for_scan_host.sh
1.4 8月每周的1,3,5的8-18点每隔2小时扫描一下本机的端口开启情况
[22:28:08 root@rocky scripts]$ cat scan_host_port.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-17
#FileName: scan_host_port.sh
#Description: 扫描某主机的端口开启情况
#***********************************************************
i=1
HOST=`ip addr show eth0|sed -rn '3s/[^0-9]+([0-9.]+).*/\1/p'`
while i <= 65535;do
if nc -z $HOST $i &> /dev/null;then
echo $i|tee -a /data/log/port.txt
fi
done
[22:17:58 root@rocky log]$ crontab -l
0 8-18/2 * 8 1-6/2 sh /data/scripts/scan_host_port.sh &> /data/log/scan_port.log
1.5 工作日每两小时取出当前系统/proc/meminfo文件中以S或M开头的信息追加至/tmp/meminfo.txt文件中
[22:42:06 root@rocky scripts]$ cat meminfo.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-22
#FileName: meminfo.sh
#Description: 提取系统/proc/meminfo文件以S或M开头的行
#***********************************************************
cat /proc/meminfo |grep "^[SM]" >> /tmp/meminfo.txt
[22:45:15 root@rocky log]$ crontab -l
0 */2 * * 1-5 sh /data/scripts/meminfo.sh &> /data/log/meminfo.log
1.6 工作日9-16点每隔3小时实时查看网卡流量
[15:05:06 root@rocky scripts]$ cat /data/scripts/scan_eth.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-23
#FileName: scan_eth.sh
#Description: 实时查看网卡流量
#***********************************************************
NIC=$1
echo -e " In ------ Out"
i=1
while ((i<=10)); do
OLD_IN=$(grep $NIC /proc/net/dev|awk '{print $2}')
OLD_OUT=$(grep $NIC /proc/net/dev|awk '{print $10}')
sleep 10
NEW_IN=$(grep $NIC /proc/net/dev|awk '{print $2}')
NEW_OUT=$(grep $NIC /proc/net/dev|awk '{print $10}')
IN=$(printf "%.2f%s" "$((($NEW_IN-$OLD_IN)/1024))" "KB/s")
OUT=$(printf "%.2f%s" "$((($NEW_OUT-$OLD_OUT)/1024))" "KB/s")
echo "$IN $OUT"
sleep 1
let i++
done
[15:04:57 root@rocky scripts]# crontab -l
0 9-16/3 * * 1-5 sh /data/scripts/scan_eth.sh &> /data/log/scan_eth.log
1.7 每十分钟检查将连接数超过100个以上的IP放入黑名单拒绝访问
[23:02:15 root@rocky scripts]$ cat deny_dos.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-24
#FileName: deny_dos.sh
#Description: 将连接数超过100次以上的IP放入黑名单拒绝其访问
#***********************************************************
LINK=100
while :;do
ss -nt|awk -F" +|:" '/^ESTAB/{print $(NF-2)}'|sort|uniq -c|while read count ip;do
if [ $count -gt $LINK ];then
iptables -A INPUT -s $ip -j REJECT
fi
done
done
[23:00:59 root@rocky scripts]$ chmod +x deny_dos.sh
[23:02:10 root@rocky scripts]$ crontab -l
*/10 * * * * /data/scripts/deny_dos.sh
1.8、工作日每天的11点和17点查看服务器各个利用率
[18:19:33 root@rocky scripts]$ cat used.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-25
#FileName: used.sh
#Description: 显示服务器利用率
#***********************************************************
#!/bin/bash
function cpu(){
util=$(vmstat | awk 'NR==3{print $13+$14}')
iowait=$(vmstat | awk 'NR==3{print $16}')
echo "CPU -使用率:${util}% ,等待磁盘IO相应使用率:${iowait}:${iowait}%"
}
function memory (){
total=`free -m |awk 'NR==2{printf "%.1f",$2/1024}'`
used=`free -m |awk 'NR==2{printf "%.1f",($2-$NF)/1024}'`
available=`free -m |awk 'NR==2{printf "%.1f",$NF/1024}'`
echo "内存 - 总大小: ${total}G , 使用: ${used}G , 剩余: ${available}G"
}
disk(){
fs=$(df -h |awk '/^\/dev/{print $1}')
for p in $fs; do
mounted=$(df -h |awk '$1=="'$p'"{print $NF}')
size=$(df -h |awk '$1=="'$p'"{print $2}')
used=$(df -h |awk '$1=="'$p'"{print $3}')
used_percent=$(df -h |awk '$1=="'$p'"{print $5}')
echo "硬盘 - 挂载点: $mounted , 总大小: $size , 使用: $used , 使用率: $used_percent"
done
}
function tcp_status() {
summary=$(ss -antp |awk 'NR!=1{status[$1]++}END{for(i in status) printf i":"status[i]" "}')
echo "TCP连接状态 - $summary"
}
cpu
memory
disk
tcp_status
[18:19:37 root@rocky scripts]$ sh used.sh
CPU -使用率:1% ,等待磁盘IO相应使用率:0:0%
内存 - 总大小: 1.7G , 使用: 0.4G , 剩余: 1.3G
硬盘 - 挂载点: / , 总大小: 70G , 使用: 13G , 使用率: 19%
硬盘 - 挂载点: /boot , 总大小: 1014M , 使用: 212M , 使用率: 21%
硬盘 - 挂载点: /home , 总大小: 127G , 使用: 939M , 使用率: 1%
TCP连接状态 - LISTEN:5 ESTAB:2
[18:26:22 root@rocky scripts]$ crontab -l
0 11,17 * * 1-5 sh /data/scripts/used.sh &> /data/log/used.log
1.9、工作日每天8-18点每隔半小时查看占用CPU 内存过高的进程
[19:10:08 root@rocky scripts]$ cat cpu_mem_top10.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-25
#FileName: cpu_mem_top10.sh
#Description: 查找cpu内存过高的进程
#***********************************************************
echo "-------------------CUP占用前10排序--------------------------------"
ps -eo user,pid,pcpu,pmem,args --sort=-pcpu |head -n 10
echo "-------------------内存占用前10排序--------------------------------"
ps -eo user,pid,pcpu,pmem,args --sort=-pmem |head -n 10
##定时任务
[19:11:35 root@rocky scripts]# crontab -l
*/30 8-18 * * 1-5 sh /data/scripts/cpu_mem_top10.sh &> /data/log/cpu_mem_top10.log
1.10 定时任务汇总输出
[19:16:18 root@rocky scripts]$ crontab -l
*/5 * * * * sh /data/scripts/while_diskcheck.sh &> /data/log/disk_check-`date +\%F_\%T`.log
30 0 * * * 1-5 sh /data/scripts/backup.sh &> /data/log/backup.log
* * */10 */2 * sh /data/scripts/for_scan_host.sh
0 8-18/2 * 8 1-6/2 sh /data/scripts/scan_host_port.sh &> /data/log/scan_port.log
0 */2 * * 1-5 sh /data/scripts/meminfo.sh &> /data/log/meminfo.log
0 9-16/3 * * 1-5 sh /data/scripts/scan_eth.sh &> /data/log/scan_eth.log
*/10 * * * * /data/scripts/deny_dos.sh
0 11,17 * * 1-5 sh /data/scripts/used.sh &> /data/log/used.log
*/30 8-18 * * 1-5 sh /data/scripts/cpu_mem_top10.sh &> /data/log/cpu_mem_top10.log
2 图文并茂说明Linux进程和内存概念
进程(process)是个可执行的实例。
进程一般由程序、数据集合和进程控制块三部分组成。
- 程序是用于描述进程要完成的功能,是控制进程执行的指令集
- 数据集合是程序在执行时所需要的数据和工作区
- 程序控制块(Program Control Block,PCB)包含进程的描述信息和控制信息,是进程存在的唯一标识。
每个进程都有一个创建自己的进程,即父进程。如果子进程的父进程终止,则子进程就会变成“孤儿”,初始进程init进程随即将其收养。
2.1 进程虚拟内存(用户空间)布局
每个进程所分配的内存有很多部分组成,通常称之为段(segment)
- 代码段:用来存放可执行文件的操作指令,代码段需要防止在运行实被非法修改,所以只有读权限。
- 数据段:用来存放可执行文件中以初始化全局变量,换句话就是存放程序静态分配的变量和全局变量
BSS
段:包含了程序中未初始化的全局变量,在内存中BSS
段全部置零。- 堆(heap):存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上;当利用free等函数释放内存时,被释放的内存从堆中被剔除。
- 栈(stack):用户存放程序临时创建的局部变量,也就是函数中定义的变量。在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。栈是先进先出的特点。
内核管理5个部分的方式是,将这些内存区域抽象成vm_area_struct
的内存管理对象。用来描述进程地址空间的基本管理单元,一个进程往往有多个vm_area_struct
来描述它的用户空间虚拟地址
2.2 内核空间
- 直接映射区:直接映射物理地址
- 动态内存映射区:
vmalloc Region
由vmlloc
内核参数来分配。分配的地址则限于vmalloc_start
与vmalloc_end
之间.每一块vmalloc
分配的内核虚拟内存都对应一个vm_struct
结构体,不同的内核空间虚拟地址之间有4k
大小的防越界空闲区间隔区。 - 永久内存映射区
- 固定内存映射区
3 图文并茂说明Linux启动流程
3.1 centos6启动流程
简述流程:
POST
:加电自检,确定启动设备,移交控制权给bootloader
。GRUB
引导阶段:分为stage1
、stage1.5
、stage2
三个阶段,stage1
:找到MBR前446字节,将MBR加载到内存1.5 stage
:MBR之后的空间,让stage1
中的bootloader
能识别stage2
所在的分区上的文件系统stage2
:解析加载到内存的/boot/grub/grub.conf
文件;加载内核文件/boot/vmlinuz-VERSION-release
到内存;另外通过/boot/initramfs-$(uname -r).img
文件建立临时伪根文件系统。
- 内核引导阶段:调用临时伪根文件系统中的init,加载驱动,然后切换至真正的根文件系统,协助呼叫进程
/sbin/init
程序。 - init初始化阶段:
/sbin/init
程序会读取/etc/inittab
文件确认运行级别,然后执行系统初始化脚本/etc/tc.sysinit
,与此同时还会根据运行级别执行对应的/etc/rc.d/rc#.d/
目录下的系统服务。还会加载/etc/rc.local
用户自定义服务。 - 启动登录终端
3.2 centos7以后版本启动流程
- UEFI或BIOS初始化,运行
POST
开机自检 - 选择启动设备
- 引导装载程序, centos7是
grub2
,加载装载程序的配置文件:
/etc/grub.d/
/etc/default/grub
/boot/grub2/grub.cfg
- 加载
initramfs
驱动模块(实现根文件系统的挂载) - 加载内核选项
- 内核初始化,centos7使用
systemd
代替init
(第一个进程) - 执行
initrd.target
所有单元,包括挂载/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
需要的服务(有图形界面时)
4 自定义一个systemd服务定时去其他服务器上检查/tmp/下文件的个数,如果发现数量有变化就记录变化情况到文件中。
4.1 shell脚本
[15:36:07 root@rocky scripts]$ cat system.sh
#!/bin/bash
#
#***********************************************************
#Author: yanli
#Date: 2022-08-27
#FileName: system.sh
#Description:
#***********************************************************
USER=root
PASS=lgq123456**
IP=10.0.0.4
expect -c "
spawn ssh $USER@$IP
expect {
\"(yes/no)\" {send \"yes\r\"; exp_continue}
\"password:\" {send \"$PASS\r\"; exp_continue}
\"$USER@*\" {send \"ls -lR /tmp/| grep '^-' | wc -l |xargs -I num sh -c 'echo $(date "+%Y-%m-%d %H:%M:%S") num >> /data/stat.txt'\r exit\r\"; exp_continue}
}"
expect -c "
spawn scp -r $USER@$IP:/data/stat.txt /data/log/
expect {
\"*assword\" {set timeout 10; send \"$PASS\r\"; exp_continue;}
\"yes/no\" {send \"yes\r\";}
}"
line_num=$(cat /data/log/stat.txt|wc -l)
if [ $line_num -eq 1 ];then
break
else
now_time=$(awk 'END{print $1,$2}' /data/log/stat.txt)
now_num=$(awk 'END{print $3}' /data/log/stat.txt)
before_time=$(tail -n2 /data/log/stat.txt|head -n1|awk '{print $1,$2}'|awk '{print $1,$2}')
before_num=$(tail -n2 /data/log/stat.txt|head -n1|awk '{print $3}')
add_num=$(($now_num-$before_num))
if [ $add_num -eq 0 ];then
break
elif [ $add_num -gt 0 ];then
echo "$before_time -- $now_time 10.0.0.4:/tmp/ add $add_num file" >> /data/log/tmp_stat.txt
else
echo "$before_time -- $now_time 10.0.0.4:/tmp/ reduce $add_num file" >> /data/log/tmp_stat.txt
fi
fi
4.2 创建service文件
[15:38:44 root@rocky system]$ cat chenkfile.service
[Unit]
Description=check host file service
[Service]
ExecStart=/bin/bash /data/scripts/system.sh
[Install]
WantedBy=multi-user.target
启动服务
[15:41:30 root@rocky system]$ systemctl start chenkfile
[15:41:54 root@rocky system]$ systemctl status chenkfile
● chenkfile.service - check host file service
Loaded: loaded (/etc/systemd/system/chenkfile.service; disabled; vendor preset: disabled)
Active: active (running) since Sat 2022-08-27 16:41:54 CST; 3s ago
Main PID: 2864487 (bash)
Tasks: 4 (limit: 11217)
Memory: 2.4M
CGroup: /system.slice/chenkfile.service
├─2864487 /bin/bash /data/scripts/system.sh
├─2864536 expect -c spawn ssh root@10.0.0.4 expect { "(yes/no)" {send "yes\r"; exp_continue} >
└─2864537 ssh root@10.0.0.4
Aug 27 15:41:54 rocky.lgq.com systemd[1]: Started check host file service.
Aug 27 15:41:54 rocky.lgq.com bash[2864536]: spawn ssh root@10.0.0.4
Aug 27 15:41:54 rocky.lgq.com bash[2864536]: [26B blob data]
Aug 27 15:41:55 rocky.lgq.com bash[2864536]: Last login: Sat Aug 27 16:40:12 2022 from 10.0.0.3
4.3 创建timer服务文件
[15:48:14 root@rocky system]$ cat checkfile.timer
[Unit]
Description=run system.sh every 1h
[Timer]
OnUnitActiveSec=3600s
Unit=checkfile.service
[Install]
WantedBy=multi-user.target
启动服务
[15:48:50 root@rocky system]$ systemctl start checkfile.timer
[15:49:18 root@rocky system]$ systemctl status checkfile.timer
● checkfile.timer - run system.sh every 1h
Loaded: loaded (/etc/systemd/system/checkfile.timer; disabled; vendor preset: disabled)
Active: active (elapsed) since Sat 2022-08-27 16:48:00 CST; 14s ago
Trigger: n/a
Aug 27 15:48:00 rocky.lgq.com systemd[1]: Started run system.sh every 1h.
4.4 测试结果
[22:22:34 root@rocky scripts]# cat ../log/tmp_stat.txt
2022-08-27 16:17:22 -- 2022-08-27 16:57:20 10.0.0.4:/tmp/ add 1 file
2022-08-27 16:57:25 -- 2022-08-27 17:57:24 10.0.0.4:/tmp/ nothing has changed
5 inux内核编译安装
5.1 下载所需的内核并解压
[22:20:30 root@rocky ~]$ mkdir app
[22:20:45 root@rocky ~]$ cd app/
[22:23:04 root@rocky app]$ rz -E
[22:22:15 root@rocky app]$ tar -xvf linux-5.10.10.tar.gz
[22:24:20 root@rocky app]$ cd linux-5.10.10
[17:08:26 root@rocky linux-5.10.10]$ ls
arch COPYING Documentation include Kbuild lib Makefile README security usr
block CREDITS drivers init Kconfig LICENSES mm samples sound virt
certs crypto fs ipc kernel MAINTAINERS net scripts tools
5.2 修改内核编译config文件
1.复制当前系统的配置文件到当前目录
[17:10:38 root@rocky linux-5.10.10]$ cp /boot/config-4.18.0-348.el8.0.2.x86_64 ./config
2.修改配置文件
[17:11:15 root@rocky linux-5.10.10]$ vi .config
将.config
文件中的CONFIG_SYSTEM_TRUSTED_KEYS
和CONFIG_DEBUG_INFO_BTF
两行注释掉
3.安装编译所需的依赖
[17:15:22 root@rocky linux-5.10.10]$ yum -y install ncurses-devel gcc-c++ make openssl-devel bison flex elfutils-libelf-devel
4.运行menuconfig程序,选择需要的编译参数
[17:20:22 root@rocky linux-5.10.10]$ make menuconfig
5.编译内核
#-j后面加核数,根据自己机器来定,很耗时
[17:28:08 root@rocky linux-5.10.10]$ make -j2
##没有具体的报错信息就是这一步编译成功了
#上一步执行成功的,接着下一步编译
[18:28:08 root@rocky linux-5.10.10]$ make modules
CALL scripts/checksyscalls.sh
CALL scripts/atomic/check-atomics.sh
DESCEND objtool
CHK include/generated/compile.h
CHK kernel/kheaders_data.tar.xz
[18:28:08 root@rocky linux-5.10.10]$ make modules_install
[18:28:08 root@rocky linux-5.10.10]$ make install
sh ./arch/x86/boot/install.sh 5.10.10 arch/x86/boot/bzImage \
System.map "/boot"
## 查看现在系统可用的内核版本
[18:37:33 root@rocky linux-5.10.10]$ grubby --info=ALL | grep ^kernel
kernel="/boot/vmlinuz-5.10.10"
kernel="/boot/vmlinuz-4.18.0-348.el8.0.2.x86_64"
kernel="/boot/vmlinuz-0-rescue-5198327be2114b879a6445337167e207"
- 重启查看是否安装上了
6 总结5个自我觉得比较有用的awk的使用场景,比如在什么情况下用awk处理文本效率最高,发散题,至少写1个。
6.1 在进行大量计算时使用awk效率高
- 示例:利用
awk
、shell
、bc
分别计算,可以看出awk
的运行时间大大低于其他两种
[12:01:20 root@rocky ~]$ time(awk 'BEGIN{i=1;sum=0;while(i<=1000000){sum+=i;i++};print sum}')
500000500000
real 0m0.100s
user 0m0.038s
sys 0m0.000s
[12:01:46 root@rocky ~]$ time(sum=0;for((i=1;i<=1000000;i++));do let sum+=i;done;echo $sum)
500000500000
real 0m5.318s
user 0m2.551s
sys 0m0.034s
[12:02:01 root@rocky ~]$ time(seq -s+ 1000000|bc)
500000500000
real 0m0.539s
user 0m0.221s
sys 0m0.011s
6.2 取出IP地址
[11:09:45 root@rocky ~]$ ifconfig eth0|awk '/netmask/{print $2}'
10.0.0.3
6.3 取出磁盘利用率
[11:06:54 root@rocky ~]$ df|awk -F" +|%" '/^\/dev\//{print $5}'
19
21
1
6.4 监控当某个IP并发连接数超过100时,即调用防火墙命令封掉对应的IP
[17:13:14 root@rocky ~]$ ss -nt|awk -F"[ :]+" '/^ESTAB/{ip[$(NF-2)]++}END{for(i in ip){if(ip[i]>100){system("iptables -A INPUT -s 'i' -j REJECT")}}}'
6.5 统计/etc/fstab文件中每个文件系统类型出现的次数
[16:37:23 root@ubuntu2004 ~]$ awk '!/^#/{file[$3]++}END{for(i in file){print file[i],i}}' /etc/fstab|sort -nr
2 ext4
1 swap
6.6 统计每个用户使用的内存大小
[22:28:44 root@rocky ~]$ ps aux|awk 'NR!=1{a[$1]+=$6}END{for(i in a){print i ":" a[i]"KB"}}'
dbus:5760KB
polkitd:24100KB
libstor+:1976KB
postfix:20732KB
root:4448636KB