1. 自定义写出几个定时任务的示例。
2. 图文并茂说明Linux进程和内存概念。
3. 图文并茂说明Linux启动流程。
4. 自定义一个systemd服务定时去其他服务器上检查/tmp/下文件的个数,如果发现数量有变化就记录变化情况到文件中。
5. 写Linux内核编译安装博客。
6. 总结5个自我觉得比较有用的awk的使用场景,比如在什么情况下用awk处理文本效率最高,发散题,至少写1个。
一、定时任务
格式如下图所示:
每分钟执行一次/app/bin/test.sh
* * * * * /app/bin/test.sh
11月每天的6-12点之间每隔2小时执行/app/bin/test.sh
* 6~12/2 * 11 * /app/bin/test.sh
每周的工作日1:30,将/etc备份至/backup目录中,保存的文件名称格式为“etcbak-yyyy-mm-dd-HH.tar.xz” ,其中日期是前一天的时间
30 1 1~5 * * tar -Jcvf /backup/etcbak-`date -d '-1 day' +%Y-%m-%d-%H`.tar.xz /etc
每两小时取出当前系统/proc/meminfo文件中以S或M开头的信息追加至/tmp/meminfo.txt文件中
* */2 * * * cat /prco/meminfo | grep "^[SM]" >> /tmp/meminfo.txt
每月1、10、22日的4 : 45执行/app/bin/test.sh
45 4 1,10,22 * * /app/bin/test.sh
每周六、周日的1 : 10执行/app/bin/test.sh
10 1 * * 0,6 /app/bin/test.sh
晚上11点到早上7点之间,每隔一小时执行/app/bin/test.sh
* 23~7/1 * * * /app/bin/test.sh
每月四号和每周一到周三11点重启服务器
0 11 4 * 1-3 reboot
二. 图文并茂说明Linux进程和内存概念。
进程的含义:进程是运行中程序的一个副本,是被载入内存的一个指令集合,是资源分配的单位。担当分配系统资源(CPU时间,内存)的实体。
- 进程ID(Process ID,PID)号码被用来标记各个进程。
- UID、GID和SELinux语境决定对文件系统的存取和访问权限。
- 通常从执行进程的用户来继承。
- 存在生命周期。
进程创建:
- init: 第一个进程,从CentOS 7以后为systemd。
- 进程:都由其父进程创建,fork(),父子关系。
描述进程-PCB:PCB(process control block),进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。Linux操作系统下的PCB是:task_struct, 这是Linux内核的一种数据结构,它会被装载到RAM(内存)中。
Linux进程使用 struct task_struct 来描述(include/linux/sched.h), 如下:
struct task_struct {
/*
* offsets of these are hardcoded elsewhere - touch with care
*/
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
unsigned long flags; /* per process flags, defined below */
int sigpending;
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead
0-0xFFFFFFFF for kernel-thread
*/
struct exec_domain *exec_domain;
volatile long need_resched;
unsigned long ptrace;
int lock_depth; /* Lock depth */
/*
* offset 32 begins here on 32-bit platforms. We keep
* all fields in a single cacheline that are needed for
* the goodness() loop in schedule().
*/
long counter;
long nice;
unsigned long policy;
struct mm_struct *mm;
int processor;
...
}
Linux把所有的进程使用双向链表连接起来, 如下图
Linux内核为了加快获取当前进程的的task_struct结构, 使用了一个技巧, 就是把task_struct放置在内核栈的栈底, 这样就可以通过 esp寄存器 快速获取到当前运行进程的task_struct结构. 如下图:
取当前运行进程的task_struct代码如下:
static inline struct task_struct * get_current(void)
{
struct task_struct *current;
__asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
return current;
}
进程描述符的state字段用于保存进程的当前状态, 进程的状态有以下几种:
- TASK_RUNNING (运行) – 进程处于可执行状态, 在这个状态下的进程要么正在被CPU执行, 要么在等待执行(CPU被其他进程占用的情况下).
- TASK_INTERRUPTIBLE (可中断等待) – 进程处于等待状态, 其在等待某些条件成立或者接收到某些信号, 进程会被唤醒变为运行状态.
- TASK_UNINTERRUPTIBLE (不可中断等待) – 进程处于等待状态, 其在等待某些条件成立, 进程会被唤醒变为运行状态, 但不能被信号唤醒.
- TASK_TRACED (被追踪) – 进程处于被追踪状态, 例如通过ptrace命令对进程进行调试.
- TASK_STOPPED (停止) – 进程处于停止状态, 进程不能被执行. 一般接收到SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU信号进程会变成TASK_STOPPED状态.
三、图文并茂说明Linux启动流程
CentOS6启动流程
(1) 加载BIOS的硬件信息,获取第一个启动设备
(2) 读取第一个启动设备MBR的引导加载程序(grub)的启动信息
(3) 加载核心操作系统的核心信息,核心开始解压缩,并尝试驱动所有的硬件设备
(4) 核心执行init程序,并获取默认的运行信息
(5)init程序执行/etc/rc.d/rc.sysinit文件,重新挂载根文件系统
(6)启动核心的外挂模块
(7)init执行运行的各个批处理文件(scripts)
(8) init执行/etc/rc.d/rc.local
(9)执行/bin/login程序,等待用户登录
(10)登录之后开始以Shell控制主机
CentOS7以后启动流程
(1) UEFi或BIOS初始化,运行POST开机自检
(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及登录服务
(14)systemd执行graphical需要的服务
四、自定义一个systemd服务定时去其他服务器上检查/tmp/下文件的个数,如果发现数量有变化就记录变化情况到文件中。
vim /lib/systemd/system/find.service
[Unit]
Description=find
[Service]
TimeoutStartSec=0
ExecStart=/bin/sh -c "ssh root@192.168.50.131 find /tmp/ -mtime 2 |wc -l >> log.txt" #基于key验证
ExecStop=/bin/kill sh
[Install]
Wantedby=multi-user.target
[root@centos8 ~]#systemctl daemon-reload
[root@centos8 ~]#systemctl enable --now find.service
五. 写Linux内核编译安装博客。
#下载linux内核
https://www.kernel.org/
#将下载的内核包上传到linux,可以通过scp或者xshell工具
#安装编译时所用到的工具包
yum -y install gcc make ncurses-devel flex bison openssl-devel
elfutils-libelf-devel bc perl
#解压内核包到/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处理文本效率最高,发散题,至少写1个。
取ss.log日志中连接数最多的前3个IP
[root@centos ~]#awk -F" +|:" 'printf $(NF-2)' ss.log | sort | uniq -c | sort -nr | head -3
解决Dos攻击生成案例:监控当某个IP并发连接数超过100时,即调用防火墙命令封掉对应的IP,监控频率为每隔5分钟。
[root@centos ~]#ss -nt | awk -F" +|:" 'NR!=1{ip[$(NF-2)]++}END{for (i in ip){if(ip[i]>100){system(""iptables -A INPUT -s "i" -j REJECT)}}}'