Linux命令 Systemd中Service Timer单元介绍


原文链接: Linux命令 Systemd中Service Timer单元介绍

Systemd中Service单元介绍

Systemd是一个系统管理守护进程、工具和库的集合,用于取代System V初始进程,集中管理和配置类UNIX系统,可见它非常的强大。

Systemd分为多个单元(unit)如服务(.service),挂载点(.mount),套接口(.socket)和设备(.device)等,这里记录使用最多的服务(service)文件的编写。用户自定义的一般存放在/etc/systemd/sytem/文件夹下,还有另外的文件夹类debian系列的如下。

DirectoryDescription
/lib/systemd/system/系统自带的或者程序自带安装的单元存放在此
/etc/systemd/system/用户自定义的,此文件夹优先级最高,可以覆盖上面文件夹的内容

下面是系统安装openssh-server后,在/lib/systemd/system/ssh.service下的服务。

[Unit]
Description=OpenBSD Secure Shell server
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run

[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify

[Install]
WantedBy=multi-user.target
Alias=sshd.service

如上所示一般每个Unit都有各个块(section)组成,由[]包裹就是块名。下面的就是配置,直到另一个块开始为止。

[Unit] section

[Unit]一般是第一个块文件配置,配置各种元数据(metadata)和其他单元的关系

OptionDescription
Description=这个单元的描述字符串
Documentation=文档链接
Requires=运行这个单元所需要的依赖单元,否则启动失败
Wants=和上面Requires相似,但是非强限制。如果列出在此的单元没有启动,本单元也还是能启动持续运行
BindsTo=和上面Requires相似,区别是列出在此的单元终止了,本单元也会停止
Before=在此列出的单元,只有在本单元启动后才会启动。但不是依赖关系,如需依赖配置上述Requires命令
After=在启动本单元之前,先要启动在此列出的单元。但不是依赖关系,如需依赖配置上述Requires命令
Conflicts=在此列出的单元,不能和本单元同时运行,和Requires相反
OnFailure=在此列出的单元将会在本单元失败后激活

还有很多的如Condition...Assert...配置详情可以查看手册man 5 systemd.unit

[Install] section

[Install]一般是最后一个块文件配置,这个是可选项,也就是说可以不配置。只有在开机启动激活(enable)时触发。

OptionDescription
WantedBy=指定该单元如何开机启动(enable),依赖在此列出的单元,有点类似[Unit]块中的Wants,不同的是它会创建软链接到.wants文件夹,如上sshd如果被enable,该单元会创建一个软链接到/etc/systemd/system/multi-user.target.wants文件夹下,如果文件夹不存在则创建文件夹再软链接。
RequiredBy=和上面WantedBy类似,但如果在此列出的单元没有激活,本单元会激活失败,同样在.requires文件夹下创建软链接。
Alias=设置改单元的别名,可以给systemctl使用,例如上面sshd的开机启动可以使用 systemctl enable ssh.servicesystemctl enable sshd.service是一样的
Also=列在此的单元,会随着本单元一起激活。

[Service] section

以上[Unit],[Install]一般是通用的,[Service]是单独的服务配置一般在[Unit][Install]之间,只用来配置服务(.service)。

其中Type=选项指定此服务的类型,Systemd通过此类型管理服务。默认Typesimple其他如下。

  • simple 默认选项,以ExecStart设置的指令运行程序。
  • forking 程序从ExecStartfork一个子进程,之后父进程退出。
  • oneshot 一次性进程和simple类似但直到程序运行退出systemd才会开始下一个单元,如果没有设置simpleExecStart默认为oneshot
  • dbus 通过D-Bus启动,等待D-Bus返回名称后systemd才会启动下一个单元
  • notify 通过sd_notify()发送一个消息通知后,systemd才会启动下一个单元
  • idle 所有其他单元任务执行完毕后才会启动此单元

OptionDescription
Type=simpleforkingoneshotdbusnotifyidle
ExecStart=指定启用某个程序或者脚本的命令,如果在命令之前加-指定脚本运行非零退出也不标记faild,必须使用绝对路径
ExecStartPre=启动程序之前执行的命令,可以指定多条。前面加-非零退出也继续执行
ExecStartPost=启动程序后执行的命令。
ExecStop=指定systemctl stop unit-name时运行的命令,如不指定执行stop时直接发送kill信号
ExecReload=指定systemctl reload unit-name时运行的命令如更新配置文件
Restart=当服务进程正常退出、异常退出、被杀死、超时的时候, 是否重新启动该服务。该值可以是 alwayson-successon-failureon-abnormalon-abort,或者 on-watchdog,如on-failure表示仅在服务进程异常退出时重启, 所谓"异常退出"是指: 退出码不为"0"
RestartSec=重启间隔时间
TimeoutStartSec=配置等待启动的时间。如果守护程序服务未在配置的时间内发出启动完成信号,则该服务将被视为失败,并将再次关闭。
RemainAfterExit=一般与Type=onshot使用,当设置为yes时,服务即使退出也为active状态,默认为no
Environment=指定环境变量
EnvironmentFile=指定环境变量文件

更具体可参考systemd.service(5)

实例

如下一个最简单启动脚本的例子,依赖是network-online.target

[Unit]
Description=My Miscellaneous Service
Requires=network-online.target
After=network-online.target

[Service]
Type=simple
User=anonymous
WorkingDirectory=/home/anonymous
ExecStart=some_can_execute --option=123
Restart=on-failure

[Install]
WantedBy=multi-user.target

上一篇讲了systemd 中的service单元,这次记录一下 timer 单元。timer 必须依赖 service 单元来配置,可以用来做替代 crontab 的选择。

timer单元以.timer结尾,中间包含[Timer]块如下面所示是 Ubuntu下的apt-daily.timer,该目录下也存在一个apt-daily.service服务文件配合一起使用。

[Unit]
Description=Daily apt activities

[Timer]
OnCalendar=*-*-* 6,18:00
RandomizedDelaySec=12h
AccuracySec=1h
Persistent=true

[Install]
WantedBy=timers.target

上面的[Timer]块代表每天上午6点和下午6点都运行 apt 脚本,具体[Timer]块可配置以下参数

单调定时器(Monotonic timer)

OptionDescription
OnActiveSec=相对计时器开始后多少时间执行,格式如2h、2s、2w、2d
OnBootSec=相对系统启动后多少时间执行
OnStartupSec=相对 systemd 启动多少时间后执行
OnUnitActiveSec=每隔多少时间再次运行一次
OnUnitInactiveSec=服务在最后一次停止后,隔多久再执行一次

可以两个参数一起使用,如下每周开机15分钟后执行 foo

[Unit]
Description=Run foo weekly and on boot

[Timer]
OnBootSec=15min
OnUnitActiveSec=1w 

[Install]
WantedBy=timers.target

实时定时器(Realtime timer)

OptionDescription
OnCalendar=相对系统时间指定特定时刻运行,它接受如2h、2s 的格式也可以是 星期 年-月-日 时:分:秒的格式,..指定区间,*代表所有的。可参考systemd.time(7)
Persistent=是一个布尔值,默认为 no,当使用 OnCalendar 的设置时,指定该功能要不要持续进行。如断电恢复后是不是要执行上次没执行的
AccuracySec=设置定时器的触发精度。默认值是一分钟。定时器并不必然在所设置的精准时间点上启动匹配单元, 而是在所设置的精准时间点为起点的一小段时间窗口范围内的某个时间点上启动匹配单元, 这个时间窗口的起点由 OnCalendar=, OnActiveSec=, OnBootSec=, OnStartupSec=, OnUnitActiveSec= or OnUnitInactiveSec= 决定, 而这个时间窗口的长度则由该指令决定。
RandomizedDelaySec=将此单元的定时器随机延迟一小段时间, 这一小段时间的长度介于零到该指令设置的时间长度之间, 以均匀概率分布。

如下是每月的1到4号12点周一和周二运行 foo,格式如OnCalendar=*-*-* 4:00:00代表每天4点

[Unit]
Description=Run foo weekly

[Timer]
OnCalendar=Mon,Tue *-*-01..04 12:00:00
Persistent=true

[Install]
WantedBy=timers.target

所有timer单元可以像service一样使用systemctl status|enable|disable name.timer查看信息,可以使用systemctl list-timers列出运行中的 timer,加--all参数列出包含未激活的。

ubuntu➜  ~  ᐅ  sudo systemctl list-timers --all
NEXT                         LEFT     LAST                         PASSED       UNIT                         ACTIVATES
Thu 2018-08-16 06:52:42 CST  7h left  Wed 2018-08-15 06:22:54 CST  17h ago      apt-daily-upgrade.timer      apt-daily-upgrade.service
Thu 2018-08-16 09:48:35 CST  10h left Wed 2018-08-15 20:15:54 CST  3h 10min ago apt-daily.timer              apt-daily.service
Thu 2018-08-16 21:34:50 CST  22h left Wed 2018-08-15 21:34:50 CST  1h 51min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
n/a                          n/a      n/a                          n/a          snapd.refresh.timer
n/a                          n/a      n/a                          n/a          snapd.snap-repair.timer      snapd.snap-repair.service
n/a                          n/a      n/a                          n/a          ureadahead-stop.timer        ureadahead-stop.service

6 timers listed.
`