一、前言

当谈到Linux中的定时任务时,有两种主要的方法:Cron和systemd定时器。而在平时使用中,我们常常会使用Cron来进行一些数据备份及巡检工作。下面主要从以下方面来介绍一下Cron定时任务:

  • 什么是Cron
  • 安装Cron
  • Cron表达式
  • 编辑Cron任务
  • 查看Cron任务
  • Cron任务排查思路
  • Cron任务注意事项

二、Cron

2.1 什么是Cron

Cron是一个在Unix和类Unix操作系统中广泛使用的定时任务工具。它允许用户在预定的时间间隔内自动运行命令或脚本。

2.2 安装Cronie

"cronie"是指Cronie软件包,它是cron系统的一个实现。一般情况下,Cronie都自带,无须自行安装。可以通过以下命令进行查看是否安装,一般安装的都存在版本回显信息

$ rpm -qa cronie
cronie-1.4.11-23.el7.x86_64

当然你也可以查看显示 "cronie" 软件包安装后所涉及的文件和目录的完整路径

$ rpm -ql cronie
/etc/cron.d
/etc/cron.d/0hourly
/etc/cron.deny
/etc/pam.d/crond
/etc/sysconfig/crond
/usr/bin/crontab
/usr/lib/systemd/system/crond.service
/usr/sbin/crond
/usr/share/doc/cronie-1.4.11
/usr/share/doc/cronie-1.4.11/AUTHORS
/usr/share/doc/cronie-1.4.11/COPYING
/usr/share/doc/cronie-1.4.11/ChangeLog
/usr/share/doc/cronie-1.4.11/INSTALL
/usr/share/doc/cronie-1.4.11/README
/usr/share/man/man1/crontab.1.gz
/usr/share/man/man5/crontab.5.gz
/usr/share/man/man8/cron.8.gz
/usr/share/man/man8/crond.8.gz
/var/spool/cron

上面文件目录说明:

  • /etc/cron.d: 这是一个目录,其中可以放置系统中其他软件包提供的Cron任务配置文件。这些文件允许您将额外的Cron任务添加到系统中。
  • /etc/cron.d/0hourly: 这是一个文件,可能是一个特定任务的Cron配置文件。文件名中的 "0hourly" 表示可能是一个每小时运行的Cron任务。
  • /etc/cron.deny: 这是一个文件,用于列出不允许使用Cron的用户。如果您不希望某些用户能够创建Cron任务,可以在这个文件中列出用户名。
  • /etc/pam.d/crond: 这是PAM(Pluggable Authentication Modules)配置文件,用于配置Cron的身份验证设置。
  • /etc/sysconfig/crond: 这是Cron的系统配置文件,用于设置Cron服务的一些参数。
  • /usr/bin/crontab: 这是用于编辑用户Cron任务的命令行工具。
  • /usr/lib/systemd/system/crond.service: 这是Cron服务的systemd单元文件,用于管理Cron服务的启动和停止。
  • /usr/sbin/crond: 这是Cron守护进程,负责运行Cron任务。
  • /usr/share/doc/cronie-1.4.11: 这个目录包含Cronie软件包的文档。
  • /usr/share/man: 这个目录包含关于Cron和Crontab的手册页面(man页)。
  • /var/spool/cron: 这是存储用户Cron任务的目录。每个用户的Cron任务会在这个目录下以文件的形式存储

如果已经卸载了,可以进行安装:

1、下载相关包

$ wget http://www.rpmfind.net/linux/centos/7.9.2009/os/x86_64/Packages/cronie-1.4.11-23.el7.x86_64.rpm
$ wget http://www.rpmfind.net/linux/centos/7.9.2009/os/x86_64/Packages/crontabs-1.11-6.20121102git.el7.noarch.rpm
$ wget http://www.rpmfind.net/linux/centos/7.9.2009/os/x86_64/Packages/cronie-anacron-1.4.11-23.el7.x86_64.rpm

2、按顺序进行安装

$ rpm -ivh cronie-1.4.11-23.el7.x86_64.rpm --nodeps
$ rpm -ivh crontabs-1.11-6.20121102git.el7.noarch.rpm
$ rpm -ivh cronie-anacron-1.4.11-23.el7.x86_64.rpm

3、启动

$ systemctl start crond

2.3 Cron表达式

Cron表达式是一种用于定义任务执行时间和频率的格式。它由五个时间字段组成:分钟、小时、日期、月份和星期几。每个字段可以是一个特定的值、范围、逗号分隔的列表,或者使用星号(*)表示匹配所有值。

下面进行示例说明:

  • * * * * *:每分钟都运行
  • 0 * * * *:每小时的第0分钟运行
  • 0 2 * * *:每天凌晨2点运行
  • 0 2 * * 1:每周一的凌晨2点运行

2.4 编辑Cron任务

编辑Cron任务有两种方法:一种是直接使用crontab -e命令进行修改,另一种是在定时任务保存目录文件中进行修改

方法一

1、使用以下命令编辑用户的cron任务:

$ crontab -e

2、在编辑器中添加任务。每一行表示一个任务,格式为Cron表达式,后面跟着要执行的命令。比如在每天凌晨2点运行 /usr/bin/test.sh 脚本。

0 2 * * * /usr/bin/test.sh

3、保存并退出编辑器。Cron将按照配置的时间表自动执行任务。

方法二

1、进入定时任务保存目录

$ cd /var/spool/cron

2、里面存放定时任务,直接使用vim进行修改即可

$ vim root

说明:我这里已经存在定时任务了,直接修改即可

2.5 查看Cron任务

查看Cron任务有两种方法:一种是直接使用crontab -l命令进行修改,另一种是在定时任务保存目录文件中进行查看

方法一

1、使用以下命令编辑用户的cron任务:

$ crontab -l

方法二

1、进入定时任务保存目录

$ cd /var/spool/cron

2、里面存放定时任务,直接使用vim进行修改即可

$ cat root

说明:我这里已经存在定时任务了,直接查看即可

2.6 Cron任务排查思路

当我们设置完Cron任务可能会遇到执行失败的情况,一般有以下思路进行排查:

1、手动执行定时任务的脚本内容,观察是否可以手动执行成功

说明:一般老手都是先手动执行成功后,再上定时任务

2、查看cron服务日志,进而准确判断问题原因

$ tail -f  /var/log/cron

2.7 Cron任务注意事项

1、如果一个定时脚本产生了大量输出,但是不需要看到命令的输出,通过 & > /dev/null,你可以使命令在后台静默运行,而无需产生可见的输出,比如:

0 2 * * * /usr/bin/test.sh &  >  /dev/null

2、关闭邮件服务

$ systemctl stop postfix

说明:如果不关闭,会持续输出内容到/var/spool/postfix/maildrop/目录下面

3、定时任务一般跑的备份脚本,需要及时清理备份内容,比如只保留三天的备份内容

$ find /data -type  -f  -mtime +3 | xargs rm 

三、定时任务案例

3.1 同步时间

1、每2分钟同步下系统的时间

[root@k8s-node01 ~]# crontab -e
*/2 * * * * /sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1

2、手动修改错误时间,用于测试

[root@k8s-node01 ~]# date -s "2019-10-22"

3、查看定时任务运行日志(只能提示是否运行了,但是无法告诉我们是否运行成功)

[root@k8s-node01 ~]# tail -f /var/log/cron
...
...
...
Oct 22 00:02:01 k8s-node01 CROND[1695]: (root) CMD (/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1)

4、验证时间

[root@k8s-node01 ~]# date
Thu Oct 26 16:19:39 CST 2023

3.2 备份

每天凌晨1点定时备份/etc/到/backup/下面

1、编写压缩脚本

[root@k8s-node01 ~]# mkdir -p /scripts/
[root@k8s-node01 ~]# vi /scripts/backup-etc.sh
#!/bin/bash
mkdir -p /backup/
tar zcf /backup/etc-`date +%F_%w`.tar.gz /etc/

2、添加定时任务,执行脚本

[root@k8s-node01 ~]# crontab -e
00 01 * * * /bin/sh /scripts/backup-etc.sh >/dev/null 2>&1

3.3 系统巡检

1、编写系统巡检脚本

[root@k8s-node01 ~]# vim system_info.sh
#!/bin/bash
#author: zq
#desc: 系统巡检脚本
#version: v1.0

#0、创建备份目录
mkdir -p /backup/

#1、输出基本信息
hostname=`hostname`
ip=`hostname -I`

echo '---------------------------------------'
echo "主机名:${hostname} IP地址:${ip}"
echo -e '---------------------------------------\n\n'

#2、负载信息
load1=`uptime | awk -F '[ ,]+' '{print $(NF-2)}'`
load5=`uptime | awk -F '[ ,]+' '{print $(NF-1)}'`
load15=`uptime | awk -F '[ ,]+' '{print $NF}'`
echo '---------------------------------------'
echo '系统负载信息'
echo "最近1分钟负载:${load1}"
echo "最近5分钟负载:${load5}"
echo "最近15分钟负载:${load15}"
echo -e '---------------------------------------\n\n'

#3、内存和swap
mem_total=`free -m | awk 'NR==2{print $2}'`
mem_used=`free -m | awk 'NR==2{print $3}'`
mem_used_percent=`free -m | awk 'NR==2{print $3/$2*100"%"}'`

swap_total=`free -m | awk 'NR==3{print $2}'`
swap_used=`free -m | awk 'NR==3{print $3}'`
swap_used_percent=`free -m | awk 'NR==3{print $3/$2*100"%"}'`

echo '---------------------------------------'
echo "内存和swap信息"
echo "总计内存大小:${mem_total}MB"
echo "使用的内存:${mem_used}MB"
echo "内存的使用率:${mem_used_percent}"

echo "总计swap大小:${swap_total}MB"
echo "使用的swap:${swap_used}MB"
echo "swap的使用率:${swap_used_percent}"
echo -e '---------------------------------------\n\n'

#4、磁盘
export LANG=en_US.UTF-8
disk_count=`fdisk -l 2>/dev/null | grep '/dev/sd[a-z]:' | wc -l`
root_total_size=`df -h | awk '$NF=="/"{print $2}'`
root_used_percent=`df -h | awk '$NF=="/"{print $5}'`

echo '---------------------------------------'
echo '磁盘信息'
echo "硬盘数量:${disk_count}"
echo "根分区大小:${root_total_size}"
echo "根分区使用率:${root_used_percent}"
echo -e '---------------------------------------\n\n'

#5、进程信息
proc_total=`top -bn1 |awk 'NR==2{print $2}'`
proc_running=`top -bn1 |awk 'NR==2{print $4}'`
proc_stopped=`top -bn1 |awk 'NR==2{print $(NF-3)}'`
proc_zombine=`top -bn1 |awk 'NR==2{print $(NF-1)}'`

echo '---------------------------------------'
echo '进程信息'
echo "进程总数:${proc_total}"
echo "运行中的进程数:${proc_running}"
echo "挂起的进程数:${proc_stopped}"
echo "僵尸进程数:${proc_zombine}"
echo '---------------------------------------'

2、添加定时任务,指定每天凌晨1点执行系统检查脚本

[root@k8s-node01 ~]# crontab -e
00 01 * * * sh /root/system_info.sh > /backup/result-`date +%F`.txt 2>&1

3、163邮箱开启POP3/SMTP服务

登录163邮箱,点击【设置】-【POP3/SMTP/IMAP】

image-20231026185916513

点击【开启】

image-20231026190124203

发送短信,开启【POP3/SMTP/IMAP服务】可获取授权码OVBLHWCGDNNMKMPR

4、发送邮件

配置linux mail.rc 配置发件人信息

#未加密的发送方式通过25端口,会被公有云封掉
[root@k8s-node01 ~]# cat >>/etc/mail.rc <<EOF
set from=xiaozhang_vip123@163.com
set smtp=smtps://smtp.163.com:465
set smtp-auth-user=xiaozhang_vip123@163.com
set smtp-auth-password=OVBLHWCGDNNMKMPR
set smtp-auth=login
EOF

#加密的方式465端口
[root@k8s-node01 ~]# cat >>/etc/mail.rc <<EOF
set nss-config-dir=/etc/pki/nssdb/
set smtp-user-starttls
set ssl-verify=ignore
set from=xiaozhang_vip123@163.com
set smtp=smtps://smtp.163.com:465
set smtp-auth-user=xiaozhang_vip123@163.com
set smtp-auth-password=OVBLHWCGDNNMKMPR
set smtp-auth=login
EOF

发送邮件给1904763431@qq.com,并指定附件为/etc/hosts

[root@k8s-node01 nssdb]# mail -s '每日巡检结果' -a /backup/result-`date +%F`.txt 1904763431@qq.com
[root@k8s-node01 ~]# Error in certificate: Peer's certificate issuer is not recognized.

如果不想输出Error in certificate: Peer's certificate issuer is not recognized.内容,可以输入以下命令

[root@k8s-node01 ~]# echo -n | openssl s_client -connect smtp.163.com:465 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /etc/pki/nssdb/163.crt
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = GeoTrust RSA CN CA G2
verify return:1
depth=0 C = CN, ST = zhejiang, L = hangzhou, O = "NetEase (Hangzhou) Network Co., Ltd", CN = *.163.com
verify return:1
DONE
[root@k8s-node01 ~]# certutil -A -n "GeoTrust SSL CA" -t "C,," -d /etc/pki/nssdb/ -i /etc/pki/nssdb/163.crt
[root@k8s-node01 ~]# certutil -A -n "GeoTrust Global CA" -t "C,," -d /etc/pki/nssdb/ -i /etc/pki/nssdb/163.crt
[root@k8s-node01 ~]# certutil -L -d /etc/pki/nssdb/

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

GeoTrust SSL CA                                              C,,
[root@k8s-node01 ~]# cd /etc/pki/nssdb/
[root@k8s-node01 nssdb]# certutil -A -n "GeoTrust SSL CA - G3" -t "Pu,Pu,Pu" -d ./ -i 163.crt
Notice: Trust flag u is set automatically if the private key is present.

再次进行尝试

[root@k8s-node01 nssdb]# mail -s '每日巡检结果' -a /backup/result-`date +%F`.txt 1904763431@qq.com

5、将输出内容转换成表格格式

备份脚本

[root@k8s-node01 ~]# cp system_info.sh system_info_pro.sh

修改脚本为.csv格式(以逗号相隔)

[root@k8s-node01 ~]# vim system_info_pro.sh
#!/bin/bash
#author: zq
#desc: 系统巡检脚本
#version: v1.0

#0、创建备份目录
mkdir -p /backup/

#1、输出基本信息
hostname=`hostname`
ip=`hostname -I`

echo "主机名,${hostname}"
echo "IP地址,${ip}"

#2、负载信息
load1=`uptime | awk -F '[ ,]+' '{print $(NF-2)}'`
load5=`uptime | awk -F '[ ,]+' '{print $(NF-1)}'`
load15=`uptime | awk -F '[ ,]+' '{print $NF}'`
echo "系统负载信息,"
echo "最近1分钟负载,${load1}"
echo "最近5分钟负载,${load5}"
echo "最近15分钟负载,${load15}"

#3、内存和swap
mem_total=`free -m | awk 'NR==2{print $2}'`
mem_used=`free -m | awk 'NR==2{print $3}'`
mem_used_percent=`free -m | awk 'NR==2{print $3/$2*100"%"}'`

swap_total=`free -m | awk 'NR==3{print $2}'`
swap_used=`free -m | awk 'NR==3{print $3}'`
swap_used_percent=`free -m | awk 'NR==3{print $3/$2*100"%"}'`

echo "内存和swap信息,"
echo "总计内存大小,${mem_total}MB"
echo "使用的内存,${mem_used}MB"
echo "内存的使用率,${mem_used_percent}"

echo "总计swap大小,${swap_total}MB"
echo "使用的swap,${swap_used}MB"
echo "swap的使用率,${swap_used_percent}"

#4、磁盘
export LANG=en_US.UTF-8
disk_count=`fdisk -l 2>/dev/null | grep '/dev/sd[a-z]:' | wc -l`
root_total_size=`df -h | awk '$NF=="/"{print $2}'`
root_used_percent=`df -h | awk '$NF=="/"{print $5}'`

echo "磁盘信息,"
echo "硬盘数量,${disk_count}"
echo "根分区大小,${root_total_size}"
echo "根分区使用率,${root_used_percent}"

#5、进程信息
proc_total=`top -bn1 |awk 'NR==2{print $2}'`
proc_running=`top -bn1 |awk 'NR==2{print $4}'`
proc_stopped=`top -bn1 |awk 'NR==2{print $(NF-3)}'`
proc_zombine=`top -bn1 |awk 'NR==2{print $(NF-1)}'`

echo "进程信息,"
echo "进程总数,${proc_total}"
echo "运行中的进程数,${proc_running}"
echo "挂起的进程数,${proc_stopped}"
echo "僵尸进程数,${proc_zombine}"

替换脚本中的变量

[root@k8s-node01 ~]# sh system_info_pro.sh > /backup/result-`date +%F`.csv
[root@k8s-node01 ~]# cat  /backup/result-2023-10-26.csv
主机名,k8s-node01
IP地址,192.168.1.42
系统负载信息,
最近1分钟负载,0.00
最近5分钟负载,0.01
最近15分钟负载,0.03
内存和swap信息,
总计内存大小,7963MB
使用的内存,368MB
内存的使用率,4.63393%
总计swap大小,4095MB
使用的swap,0MB
swap的使用率,0%
磁盘信息,
硬盘数量,2
根分区大小,35G
根分区使用率,19%
进程信息,
进程总数,133
运行中的进程数,1
挂起的进程数,0
僵尸进程数,0

效果演示(默认无模式),需要手动进行调整

image-20231026224954286