树莓派安装了内网穿透npc之后,每隔一段时间后 CPU 占用率总会暴涨,重启 npc 之后,就会恢复正常。但手动重启也太麻烦了,所以我们使用 Linux crontab 来实现定时重启。我希望每隔8小时,重启一次 npc 容器,下面我们来看下我们需要怎么做吧
一、定时重启
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
一行,#
表示这个文件被注视掉了,我们去掉 #
使配置生效
编辑之后我们保存退出,然后重新启动日志服务
1 | systemctl restart rsyslog |
至此配置完成,以后crontab生成的日志文件就会输出到/var/log/cron.log中,查看日志文件:
1 | cat /var/log/cron.log |
二、Cron 表达式
Cron 表达式,是应用在 Unix 和类 Unix 操作系统之中,让脚本、任务定时进行周期性重复的执行。Cron 表达式有丰富的表达能力,能够适应各种时间表达需求
1. 基本语法
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 | 0 0 0/8 * * * # 从每天0点开始 每隔8小时执行一次 |
三、常见问题
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 日志定时任务有没有正常执行
3. 定时任务执行时间不对
如果你发现你的定时任务执行时间和你本地时间对不上,这个时候可以在控制台输入 date
查看下你树莓派的时间
1 | root@raspberrypi:~ # date |
如果显示出来的时间和你本地时间不对,这个时候我们就需要修改树莓派的时区了,首先在控制台输入以下指令
1 | sudo dpkg-reconfigure tzdata |
选择Asia
选择Shanghai
然后再在控制台输入 date
查看下本地时间
1 | root@raspberrypi:~ # date |