LinuxGod.net
Linux大神网——精选每一篇高品质的技术干货
  1. 首页
  2. 开源快讯
  3. 正文

回到Linux基础系列之回到Shell系列文章大纲

2023年2月23日 396点热度

回到Linux基础系列文章大纲

回到Shell系列文章大纲

systemdtimer:代替cron和at的定时任务cron和systemdtimer实现定时任务的比较

Linux环境下,cron是使用最广泛的定时任务工具,但它有一些不便捷的地方。例如它默认:

由于cron不原生支持以上功能,所以当有以上相关需求时,只能在要调度的命令层次上找寻解决方案。

systemd系统中包含了timer计时器组件,timer可以完全取代cron+at,它具有以下特点:

可对定时任务做资源限制可取代cron和at工具,且支持比cron愈发灵活丰富的定时规则不会重复执行定时任务集成到journal日志,便捷调试任务,便捷查看任务调度情况…

但systemdtimer相比cron也有不足支持:

systemdtimer入门示例:每3秒运行一次

使用systemdtimer定时任务时,须要同时编撰两个文件:

这两个文件名称一般保持一致(不仅后缀部份),它们可以置于:

比如:

shell

1
2
3
4
5
6
7
8

/usr/lib/systemd/system/foo.service
/usr/lib/systemd/system/foo.timer

/etc/systemd/system/foo.service
/etc/systemd/system/foo.timer

~/.config/systemd/user/foo.timer
~/.config/systemd/user/foo.service

假定定义一个每3秒执行一次的任务,该任务用于测量页面是否正常,对应命令为curl-s-o/dev/null-w'%{http_code}'#39;,其结果为访问页面时响应的HTTP状态码。

先编撰对应服务配置文件:

shell

1
2
3
4
5
6

$ cat /usr/lib/systemd/system/page_test.service
[Unit]
Description = "test page: https://www.junmajinlong.com"

[Service]
ExecStart = /usr/bin/curl -s -o /dev/null -w '%{http_code}' 'https://www.junmajinlong.com'

由于命令每次调用都只执行一次且快速退出,所以Service中使用了默认的Type=simple。其实linux makefile,也可以使用Type=oneshot。

reduce任务没执行_linux计划任务没执行_魔兽世界dk任务完成后没任务

再编撰定时器配置文件:

shell

1
2
3
4
5
6
7
8
9
10
11
12

$ cat /usr/lib/systemd/system/page_test.timer
[Unit]
Description = "test page: https://www.junmajinlong.com every 3 seconds"

[Timer]
OnActiveSec = 1s
OnUnitInactiveSec = 3s
AccuracySec = 1us
RandomizedDelaySec = 0

[Install]
WantedBy = timers.target

再执行如下命令即可让定时器生效:

shell

1
2

systemctl daemon-reload
systemctl start page_test.timer # 启动定时器

其实,还支持如下命令来管理定时器:

shell

1
2
3
4
5
6

systemctl status xxx.timer
systemctl stop xxx.timer
systemctl restart xxx.timer

# 和WantedBy的值有关,若WantedBy=timers.target,则本命令多余
systemctl enable xxx.timer

回头来剖析一下定时器配置文件中涉及到的指令。

首先是该文件[Install]段中的最后一行WantedBy=timers.target,它表示在开机时会手动启动该定时器,之所以会开机手动执行这种timers定时计划,是由于在basic.target中定义了timer.target依赖。

shell

1
2
3

$ systemctl list-dependencies --reverse timers.target | head -2
timers.target
● └─basic.target

再看Timer段中定义定时器属性的指令。

OnActiveSec表示从该定时器启动(即systemctlstartxxx.timer)以后,多长时间触发定时器对应的任务,即执行对应的Service服务。本例是启动定时器后一秒,开始第一次执行任务单元page_test.service。

OnUnitInactiveSec表示从上一次任务单元退出后,多长时间再度触发定时器对应的任务。诸如在本例中,表示的涵义是每次page_test.service执行完成(即页面测量完成后退出)后3秒,再度触发该任务。

剩余两个指令AccuracySec和RandomizedDelaySec,稍后再详尽解释。由于在解释它们之前,须要学会观察定时任务的执行情况。

观察定时任务的执行时间点

使用systemctllist-timers可以列举当前早已生效的定时器(即假如不停止它,则迟早会触发对应的定时任务)。它会根据上次要执行的时间点先后进行排序,最快要执行的任务在最上面。

shell

1
2
3
4

$ systemctl list-timers --no-pager
NEXT LEFT LAST PASSED UNIT ACTIVATES
Sat 2020-07-04 18:43:34 CST 20s ago Sat 2020-07-04 18:43:34 CST 20s ago page_test.timer page_test.service
Sun 2020-07-05 07:03:39 CST 12h left Fri 2020-07-03 17:27:44 CST 1 day 1h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service

其中:

其实里面的含意都比较清晰,并且想要理解透彻,还真不容易。

不过,还有其它观察定时任务执行情况的方法。因为systemdservice默认集成了journald日志系统,命令的标准输出和标准错误就会输出到journal日志中。

例如,可以使用systemctlstatusxxx.service观察定时器对应任务的执行状况,即每次执行任务的时间点以及定时任务执行过程中的标准输出、标准错误信息。

shell

1
2
3
4
5
6
7
8
9
10

$ systemctl status page_test.service   # 注意是.service不是.timer
● page_test.service - "test page: https://www.junmajinlong.com"
Loaded: loaded
Active: inactive (dead) since Sat 2020-07-04 18:36:56 CST; 2s ago
Process: 22316 ExecStart=/usr/bin/curl ... (code=exited, status=0/SUCCESS)
Main PID: 22316 (code=exited, status=0/SUCCESS)

Jul 04 18:36:54 host.junmajinlong.com systemd[1]: Started "test page:....
Jul 04 18:36:56 host.junmajinlong.com curl[22316]: 200
Hint: Some lines were ellipsized, use -l to show in full.

里面的结果表明,近来一次test_page定时任务是在18:36:54开始执行的,18:36:56执行完成并返回执行结果,即HTTP响应状态码200,这个200是来自于curl的输出。

还可以使用journalctl工具来查看定时任务的日志信息:

shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 查看指定服务的所有journal日志信息
# xxx.service是定时任务的名称
journalctl -u xxx.service

# 实时监控尾部日志,类似tail -f
journalctl -f -u xxx.service

# 显示指定时间段内的日志
# --since:从指定时间点内开始的日志
# --until:到指定时间点为止的日志
journalctl -u xxx.service --since="2020-07-04 19:06:23"
journalctl -u xxx.service --since="60s ago"
journalctl -u xxx.service --since="1min ago"
journalctl -u page_test.service --since="-60s"

比如:

shell

1
2
3
4
5
6
7

$ journalctl -u page_test.service --since="-30s"
-- Logs begin at Tue 2020-06-30 14:34:48 CST, end at Sat 2020-07-04 19:13:57 CST. --
Jul 04 19:13:32 host.junmajinlong.com curl[23592]: 200
Jul 04 19:13:35 host.junmajinlong.com systemd[1]: Started "test page: https://www.junmajinlong.com".
Jul 04 19:13:43 host.junmajinlong.com curl[23602]: 200
Jul 04 19:13:46 host.junmajinlong.com systemd[1]: Started "test page: https://www.junmajinlong.com".
Jul 04 19:13:57 host.junmajinlong.com curl[23605]: 200

从结果可以看出linux计划任务没执行,在19:13:35、19:13:46都执行了page_test任务。

精确触发任务:理解AccuracySec和RandomizedDelaySec

AccuracySec表示任务延后执行的延后范围,即从每次指定要执行任务的精确时间点到延后时间段内的一个随机时间点启动任务。使用这些延后,主要是为了防止systemd频繁触发定时器风波进而频繁唤起CPU,进而让一定时间段内附近的定时任务可以集中在这个时间段内启动。

比如:

Code

1
2
3
4
5
6

# 定时器启动后,再过10分钟第一次触发定时任务
OnActiveSec=10m
# 每次执行完任务后,再过15分钟后再次触发定时任务
OnUnitInactiveSec=15m
# 触发事件后,允许推迟0-10分钟再执行被触发的任务
AccuracySec=10m

所以,以上指令的疗效是:

AccuracySec的默认值为1分钟,所以假如不定义AccuracySec的话,就算用户期盼的是每秒触发一次定时任务,但事实却是会在1s-61s时间段内的一个随机时间点触发一次定时任务。(可以自己去观察一下定时任务执行情况)

然而,触发定时任务的时间点并不表示这是执行任务的时间点。触发了定时任务,还须要依照RandomizedDelaySec的值来决定何时执行定时任务。

RandomizedDelaySec指定触发定时任务后还需延后一个指定范围内的随机时长才执行任务。该指令默认值为0,表示触发后立刻执行任务。

使用RandomizedDelaySec,主要是为了在一个时间范围内分散大量被同时触发的定时任务,进而防止这种定时任务集中在同一时间点执行而CPU争抢。

可见linux手机,AccuracySec和RandomizedDelaySec的目的是相反的:

按照以上描述,假如用户想要让定时任务十分精确度地执行,须要将它们设置的足够小。诸如:

Code

1
2

AccuracySec = 1ms        # 定时器到点就触发定时任务
RandomizedDelaySec = 0 # 定时任务一触发就立刻执行任务

systemdtimer支持的单调定时规则

不仅前面介绍的两个OnxxxSec类定时规则外,systemdtimer还支持几种其它的定时器规则。

定时器指令涵义

OnBootSec

从开机启动后,即从内核开始运行算起,多长时间触发定时器对应任务

OnStartupSec

从systemd启动后,即内核启动init进程算起,多长时间触发定时器对应任务

OnActiveSec

从该定时器启动后,多长时间触发定时器对应的任务

OnUnitInactiveSec

从下次任务单元退出后,多长时间再度触发定时器对应的任务

OnUnitActiveSec

从先前触发的任务开始执行(状态达到active)算起,多长时间再度触发定时器对应的任务

注:(1)当Service文件中Type=oneshot,这类任务不会出现active状态,除非配置了RemainAfterExit指令(参考mansystemd.service)

(2)这个定时器用的不如OnUnitInactiveSec多,由于这个定时器是以启动时间为基准的,有可能上次触发任务时,先前任务还没有执行完成,systemd会忽视上次任务

其中OnBootSec和OnStartupSec比较特殊,由于定时器自身的启动比这两个时间点要晚,假如定时器配置文件中以这两个指令为定时任务的触发基准,可能会出现超期现象。例如某定时器设置OnBootSec=1s,但倘若从启动内核到启动定时器早已过了2s,这么这个定时任务就超期了。好在,systemd会对这两个特殊的指令特殊对待,倘若这类定时任务超期了,将立刻执行定时任务实现补救。

但对其它三个指令定义的定时器,超期了就超期了,不会再尝试去补救。

也就是说,虽然过了有效期,这两类定时任务还是有效的,而其它定时任务则失效。

事实上,这几个定时器指令都是单调定时器,即:这种任务的触发时机,总是以某个时间点为基准单调降低的。

更为灵活的定时规则:OnCalendar

cron定时任务支持*****来定义定时任务,这5个位置分别表示分时日月周。

后面早已介绍的systemdtimer的定时规则早已就能实现只执行一次和每隔多久执行一次的定时规则。下边要介绍的OnCalendar基于月历的定时规则完全可以胜任cron的定时规则。

比如:

Code

1

OnCalendar = Thu,Fri 2012-*-1,5 11:12:13

这表示2012年每位月的1或5号的11点12分13秒,同时要求是周六或周日。

OnCalendar支持的时间格式很灵活,所以下边介绍它的内容也稍多,请渐渐享用。

systemdtimer可辨识的时间单位包括以下几种:

月的单位:months,month,M年的单位(一年以365.25天算):years,year,y

多个时间单位可结合使用,且时间的出现次序无关。

比如下边的时间单位都是有效的:

Code

1
2
3
4
5
6

2 h              --> 2小时
2hours --> 2小时
48hr --> 48小时
1y 12month --> 1年12个月,即2年
55s500ms --> 55秒+500毫秒
300ms20s 5day --> 5天+20秒+300毫秒,顺序无关

在定时器里,就会常常用到表示某年某月某天、某时某分某秒的时间戳格式。systemd内部的标准时间戳格式为:

Code

1
2

Fri 2012-11-23 11:12:13
Fri 2012-11-23 11:12:13 UTC

对于时区而言,假如要客场区,则必须只能加UTC三个字符,否则只能省略,此时表示本地时区(注:此处叙述是不对的,由于还支持其他更复杂的格式,但时区相关的内容太多,这儿略去)。

最上面的周几可以省略,如非须要周几符号,强烈建议省略它。但若果不省略,则必须只能使用三字母表示法或中文全称,即合理的周几符号包括:

Code

1
2
3
4
5
6
7

Monday      Mon
Tuesday Tue
Wednesday Wed
Thursday Thu
Friday Fri
Saturday Sat
Sunday Sun

年-月-日与时:分:秒两者可省其二,但不可全国。若省后者,则表示使用当前日期,若省前者则表示使用00:00:00。

时:分:秒可以省略:秒,相当于使用:00。

年-月-日中的年可以省略为2位数字表示,相当于20xx,但强烈建议不要使用这些方法。

倘若指定的礼拜与年-月-日(虽然此部份已被省略)与实际不相符,这么该时间戳无效。

还可以使用一些时间戳关键字:now,today,yesterday,tomorrow。

还可以使用一些相对时间表示法:时长加上+前缀或则'left'后缀(注意有空格),表示借此时间为基准向未来前进指定的时长,时长加上-前缀或则'ago'后缀(注意有空格)linux计划任务没执行,表示借此时间为基准向过去倒退指定的时长。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: linux定时器 linux系统 shell systemd 定时器
最后更新:2023年2月23日

Linux大神网

每日更新,欢迎收藏♥ 不积跬步无以至千里,加油,共勉。

点赞
< 上一篇
下一篇 >

Linux大神网

每日更新,欢迎收藏♥
不积跬步无以至千里,加油,共勉。

最新 热点 随机
最新 热点 随机
Linux操作系统不仅仅端口-u:仅显示监听套接字(protocol) (知识点)Linux文件权限详解:执行权限 VMware过期Linux系统CentOS7下载安装1.77下载地址 红旗linux操作系统v11.0-红旗操作系统操作系统吗? 5yw红软基地驱动完美支持windows、mac、linux系统 轻松安装ZeroMQ:Ubuntu系统必备的解决方案 怎么在Win7系统虚拟机上安装LinuxUbuntu的技巧?在这里 Linux必备!安装RAR解压器,轻松解压文件! 虚拟机linux系统下载 什么是linuxLinux(/托瓦兹)的Linux内核 文件永久删除还能找回来吗?关于Win和Mac系统的恢复方法 Ubuntu16.04怎样安装系统更新和应用更新16.04 网卡 centos 启动 Linux选择选择时各企业所参考的依据:以下内容和Centos Linux内核内存检测工具系列中的一篇,配置以及典型应用 虚拟机安装Ubuntu操作系统-Ubuntu空间20G镜像下载 0渗透操作0x02绕过disable_functions插件(组图) 【好玩的网络-第2.5期】分配IP有哪些骚操作?小白保姆级教程 Windows远程连接工具、Ubuntu系统的安装软件及系统 Linux一模一样远程连接编辑的操作图是什么? DRAM中的虚拟地址空间的缓存简化内存管理(组图) 2.5创建和配置虚拟机2.5.1创建虚拟机双击桌面的VMwarePlayer
Linux文件路径查询方法,轻松获取文件位置Linux移植6410:从零开始的挑战!linux php安装 快速掌握Linux下PHP安装,轻松入门流行技术linux patch 文件 解决LinuxPatch文件10大疑难杂症,轻松应对!Ubuntu系统更改IP地址的简易教程,跟随以下步骤即可搞定!高效搭建Linux Android开发环境,轻松提升开发体验轻松掌握:如何查询Linux内核版本?Linux安装Matlab指南,快速掌握安装步骤Ubuntu 16安装网卡驱动教程,轻松解决网络连接问题Linux启动时,不使用图形界面可能更有效率!移植Linux,手机变身“大杀器”!详解8大关键操作Linux更高效,掌握启动终端快捷键!纯Python库实现上面介绍的HTML转换为PDF的软件Fedora 13服务器配置指南:9个实用技巧全解析9种方法轻松获取Linux版本,快速掌握系统信息!博客韦东山freeRTOS系列教程:入门文档教程+进阶视频教程轻松掌握linux ldd命令的技巧,成为高效开发者与管理员Linux VPS安全检测,保障服务器稳定运行!Linux下高效开发必备:配置Tomcat和JDK分析Linux中的I2C驱动程序框架核心结构(i2c-bus结构)
红旗linux操作系统v11.0-红旗操作系统操作系统吗? 普联技术有限公司程序的安装包使用方法通过-LINK 轻松掌握Linux目录权限777提升技巧 《深入linux设备驱动程序内核机制》(1)_社会万象_光明网(图) 如何在Linux上安装Diablo3操作系统Diablo3 更新原压缩包中的文件这五个是独立的命令,压缩解压都要用到 Linux内核开发者开发出kmemleak功能的原理是什么?怎么找到 【讲堂】分为文件指向同一个硬连接的应用 (编程)编程的更进一步更进一步.1--2 Linux一模一样远程连接编辑的操作图是什么? 娃白天睡觉不太踏实,搞一个局域网实时监控,怎么办? 服务器环境安装,linux服务器php环境一键安装(组图) php入门到就业线上直播课:linux同步时间的设置 关闭虚拟机的防火墙:验证进程(上) U盘安装linux系统解决方法:确保Linux下采用dd命令 计算机操作系统全新版装系统盘点、理念与系统的优缺点 Ubuntu这款这款.10版本镜像文件下载地址获取地址! Linux系统的启动过程,来说一说启动顺序详解 1.安装JDK安装目录要求安装和配置是否成功 告诉我们哪个Linux发行版对游戏支持的**..
标签聚合
软件 linux系统 sudo 虚拟机 linux服务器 linux脚本 电脑 命令 命令模式 文件目录
书籍
课程
技术群
技术干货大合集↓
  • 2023年3月 / 114篇
  • 2023年2月 / 84篇
  • 2023年1月 / 161篇
  • 2022年12月 / 187篇
  • 2022年11月 / 76篇
友情链接:

Linux书籍 | Linux命令 | Linux系统 | RHCE红帽认证 | Linux软件 | Linux教程 | CentOS系统 | Linux内核 | Linux服务器 | Linux大神 | IT资源

COPYRIGHT © 2023 linuxgod.net ALL RIGHTS RESERVED.