1. 1. 一、定时重启
    1. 1.1. 1. 控制台输入以下指令
    2. 1.2. 2. 开启 cron 日志
  2. 2. 二、Cron 表达式
    1. 2.1. 1. 基本语法
    2. 2.2. 2. 语法shuom
    3. 2.3. 3. 符号说明
    4. 2.4. 4. 常见示例(6位示例)
  3. 3. 三、常见问题
    1. 3.1. 1. cron 表达式不生效
    2. 3.2. 2. 查看 cron 日志
    3. 3.3. 3. 定时任务执行时间不对

树莓派安装了内网穿透npc之后,每隔一段时间后 CPU 占用率总会暴涨,重启 npc 之后,就会恢复正常。但手动重启也太麻烦了,所以我们使用 Linux crontab 来实现定时重启。我希望每隔8小时,重启一次 npc 容器,下面我们来看下我们需要怎么做吧

image-20210731104042132

一、定时重启

1. 控制台输入以下指令

1
crontab -e

回车,然后如果你是第一次使用 crontab 定时指令,这个时候会要求你先选择编辑器,因为是在树莓派上,这里我们推荐 nano ,也可以选择 vim,看你习惯用什么。选择之后会进入文本编辑模式,我们在最后加入以下内容

1
0 0,8,16 * * * docker restart npc

这个指令分为两部分:0 0,8,16 * * * 是定时器,docker restart npc 是要执行的指令,定时器部分需要符合 cron 表达式,具体的表达式规则我们在第二部分讲解,我们先了解我这里写的表达式规则表达的i意思是 在每天的0点8点16点执行一次 docker restart npc 指令。编辑完成之后我们保存退出,定时任务就编写好了。

2. 开启 cron 日志

以上部分定时重启,我们就搞定了,但是我们要如何确定我们的重启任务执行了,这个时候就需要查看 cron 的执行日志了,默认情况下 cron 日志是关闭状态的,我们需要打开

1
nano /etc/rsyslog.conf

命令行输入以上指令,编辑 rsyslog.conf 文件,在文件中找到 \#cron.* /var/log/cron.log 一行,# 表示这个文件被注视掉了,我们去掉 # 使配置生效

image-20210731170640384

编辑之后我们保存退出,然后重新启动日志服务

1
systemctl restart rsyslog

至此配置完成,以后crontab生成的日志文件就会输出到/var/log/cron.log中,查看日志文件:

1
cat /var/log/cron.log

二、Cron 表达式

Cron 表达式,是应用在 Unix 和类 Unix 操作系统之中,让脚本、任务定时进行周期性重复的执行。Cron 表达式有丰富的表达能力,能够适应各种时间表达需求

1. 基本语法

cron 语法示例

2. 语法shuom

共 7 位,最后一位可选,可以不写,至少 6 位,从左到右各位置分别是:

位置 意义 取值 支持的符号
1 0-59 , - * /
2 0-59 , - * /
3 0-23 , - * /
4 1-31 , - * ? / L W C
5 1-12 或 JAN - DEC , - * /
6 1-7 或 MON - SAT , - * ? / L C #
7 空或 1970-2099 , - * /

注:Cron 表达式对日期英文缩写、特殊字符大小写不敏感。

3. 符号说明

符号 名称 功能
* 星号 表示重复对应位置上的周期,比如在第四位上表示每日
, 逗号 代表一个列表值,表示多个指定时间,如周位上SAT,SUN表示每周六周日
? 问号 无意义,占位符,只能在日、周位上
- 减号 表示一个范围,如时位上 20-22表示 20、21、22点
/ 斜杠 a/b 可以表示以 a 为起点步长为 b 的时间序列,如日位上10/10表示10日20日30日
L Last 月份最后一天或星期六,周位上 6L 表示月份的最后一个周五
W Weekday 后边最近的工作日,3W 3日如是周五,则在6日(周一)执行
# 井号 a#b 表示当月第 b 个星期 a,如 6#1 当月第一个星期五
C Calendar 关联的“日历”的计算结果

注:

  • 周位上给定值后,在日位上要用 ?
  • “L” 和 “W” 可在日位中联合使用,LW 表示这个月最后一周的工作日
  • “W” 字符指定的最近工作日是不能跨月
  • W 字符串只能指定单一日期,而不能指定日期范围
  • 日位建议最大值为 28 ,因为 2 月有时候是 28 天

在 linux 里,cron 表达式只支持5位,分别是

1
2
3
4
5
6
7
8
# Example of job definition:
# .---------------- 分钟 (0 - 59) 第一部分 0 表示 0分钟
# | .------------- 小时 (0 - 23) 第二部分 0,8,16 表示 0点 8点 16点
# | | .---------- 天 (1 - 31) 第三部分是天 * 表示每一天
# | | | .------- 月 (1 - 12) 第四部分是月 * 表示每一月
# | | | | .---- 周 (0 - 6) (Sunday=0 or 7) 第五部分是周 * 表示每一周
# | | | | |
# * * * * * user-name command to be executed

4. 常见示例(6位示例)

1
2
3
4
5
6
7
0 0 0/8 * * * # 从每天0点开始 每隔8小时执行一次
0 0 0,8,16 * * * # 每天 0点 8点 16点执行一次
0 3/5 * * * ? # ? 号没有意义占位符 从每小时的第3分钟开始 每隔 5 分钟执行一次
0 30 5 * * ? # 每天5:30执行一次
0 18 18 ? * 5 # 每周五 18:18执行一次
1 1 8-23 * * * # 每天 8点到23点之间,每小时的1分一秒执行一次
1 1 8-22/3 ? * 1-5 # 每周一到周五的8点到22点之间,每小时的一分一秒执行一次

三、常见问题

1. cron 表达式不生效

  • 完整的 cron 表达式有 7 部分,但树莓派(linux)上只支持5部分,分别是

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # Example of job definition:
    # .---------------- 分钟 (0 - 59) 第一部分 0 表示 0分钟
    # | .------------- 小时 (0 - 23) 第二部分 0,8,16 表示 0点 8点 16点
    # | | .---------- 天 (1 - 31) 第三部分是天 * 表示每一天
    # | | | .------- 月 (1 - 12) 第四部分是月 * 表示每一月
    # | | | | .---- 周 (0 - 6) (Sunday=0 or 7) 第五部分是周 * 表示每一周
    # | | | | |
    # * * * * * user-name command to be executed
    0 0,8,16 * * *

    所以不生效首先检查下 cron 表达式

  • 树莓派支持的表达式也有限,笔者第一次编写的每隔8小时执行一次的指令是这个样子的 0 0/8 * * * 但是没有生效,这个表达式的第二部分意思是,从每天的 0 点开始,每隔8小时执行一次,但是编写好了,并没有正常执行,怀疑是树莓派不支持 / 规则,幸好 cron 表达式非常灵活,所以笔者第二次将表达式改成了 0 0,8,16 * * * 所以如果你和笔者遇到了同样的问题,不妨换一种形式写表达式

2. 查看 cron 日志

我们虽然开启了 cron 日志,但是我们定时任务写的是,每天 0点 8点 16点执行任务,这想确认定时任务有没有起作用,得等的累死,所以我们可以稍微修改一下表达式,假设你现在的时间是 17:27 ,那么我们可以把定时指令修改为 30,32,34 * * * * docker restart npc ,它表达的意思是每小时的30分32分34分执行一次指令,所以我们就可以在 17:35 的时候,查看 cron 日志定时任务有没有正常执行

image-20210731173503025

3. 定时任务执行时间不对

如果你发现你的定时任务执行时间和你本地时间对不上,这个时候可以在控制台输入 date 查看下你树莓派的时间

1
2
root@raspberrypi:~ # date
2021年 07月 31日 星期六 17:32:39 CST

如果显示出来的时间和你本地时间不对,这个时候我们就需要修改树莓派的时区了,首先在控制台输入以下指令

1
sudo dpkg-reconfigure tzdata

选择Asia

img

选择Shanghai

img

然后再在控制台输入 date 查看下本地时间

1
2
root@raspberrypi:~ # date
2021年 07月 31日 星期六 17:32:39 CST