Linux 服务管理

服务定义

可以将守护进程(Daemon)和服务(Service)视为同一个东西的不同称呼。

服务是常驻内存中的进程,通常负责提供系统功能以服务用户的各项任务。

一般来说,守护进程类型的程序会在文件名末尾加上 d

Init 脚本管理

SysV(System V)的 init 脚本程序处理方式为:将第一个启动的程序称为 init,然后由 init 去启动其他系统所需服务。

init 的管理机制特性

  • 服务管理方式

    所有服务启动的 bash 脚本均放在 /etc/init.d/ 下面,用统一方式进行处理:

    • 启动/etc/init.d/daemon start
    • 关闭/etc/init.d/daemon stop
    • 重新启动/etc/init.d/daemon restart
    • 状态查询/etc/init.d/daemon status
  • 服务启动分类

    依据服务是独立启动还是被总管程序管理,可分为两大类:

    • 独立启动模式(Stand Alone):服务独立启动,常驻于内存中,反应速度快。
    • 总管程序管理(Super Daemon):由常驻于内存的 xinetd 或 inetd 程序来管理。当用户请求某些功能时,xinetd 才会去唤醒对应服务。当请求完毕服务也跟随停止。好处是统一管理,但启动服务有延时。
  • 工作形态分类

    以 daemon 提供服务的工作状态来分又可以分为两大类:

    • signal-control:通过信号来管理,只要有请求进来就会立即处理
    • interval-control:每隔一段时间主动去执行某项任务
  • 服务依赖问题

    如果服务之间启动互相依赖,则 init 无法解决依赖问题。

  • 执行等级分类

    init 可以根据设定的运行等级(run level)来启动不同的服务。总共有 7 个执行等级,各执行等级启动脚本通过 /etc/rc.d/rc[0-6]/SXXdaemon 链接到 /etc/init.d/daemon

    链接文件名(SXXdaemon)的作用是指定启动顺序。通过 SXX 的设置,开机时可以按顺序启动服务,同时也解决了服务依赖问题。

  • 设定执行等级

    可以使用以下命令进行设置:

    • 开机启动chkconfig daemon on
    • 取消开机启动chkconfig daemon off
    • 查询是否开机启动chkconfig --list daemon
  • 执行等级切换

    例如,要从命令行(run level 3)切换到图形界面(run level 5),只需使用 init 5 命令即可切换。init 会自动分析 /etc/rc.d/rc[3|5].d/ 这两个目录内的脚本,并启动相应的服务。

启动脚本目录配置

启动脚本基本上固定放在以下位置:

  • /etc/init.d/*:所有脚本存放处,因此有大量连接文件。
  • /etc/sysconfig/*:服务初始化环境配置文件,记录一些初始化的参数设置。
  • /etc/xinetd.conf/etc/xinetd.d/*:super daemon 配置文件及其管理的服务配置文件存放处。

Stand Alone 启动方式

可以查看一下 netconsole 这个命令:

[root@101c7 ~]$ /etc/init.d/netconsole 
Usage: /etc/init.d/netconsole {start|stop|status|restart|condrestart}
[root@101c7 ~]$ /etc/init.d/netconsole status
netconsole module not loaded
[root@101c7 ~]$ /etc/init.d/netconsole start
Starting netconsole (via systemctl):  Job for netconsole.service failed because the control process exited with error code. See "systemctl status netconsole.service" and "journalctl -xe" for details.
                                                           [FAILED]

也可以直接使用 service 命令来执行查询和操作:

[root@101c7 ~]$ service --status-all
netconsole module not loaded
Configured devices:
lo ens33
Currently active devices:
lo ens33

例如查看 crond 服务的状态:

[root@101c7 ~]$ service crond status
Redirecting to /bin/systemctl status crond.service
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2021-09-19 02:32:00 EDT; 7s ago

Super Daemon 启动方式

编辑 /etc/xinetd.d/ 下面的配置文件,如果 disable=yes 表示未启用,disable=no 才是开机启动。

修改了配置文件后,重启 xinetd

[root@101c7 ~]$ service xinetd restart

xinetd 启动的服务,显示名称统一是 xinetd

位于 /etc/xinetd.d 下面的配置文件可设置的参数如下:

参数 说明
Disable 设置是否启动,可设为 yesno
id 服务的名称。
Server 程序完整路径,例如 server=/usr/bin/rsync
server_args 程序参数,例如 server_args=--daemon
User 服务所属 UID。
group 服务所属 GID。
socket_type 数据包类型,stream 代表 TCP,dgram 代表 UDP,raw 代表直接交互。
protocol 数据包类型,与 socket_type 重复。
Wait 连接机制,可设为 wait=no 代表多线程。
instances 最大连接数,如果不限制,可设为 instances=unlimited
per_source 单用户最大同时连接数。
Cps 建立新连接限制,如 [两个数字]
log_type 日志文件等级,默认为 info
log_on_failure 登录失败后记录的信息,可设置为 PIDHOSTUSERIDEXITDURATION
env 额外变量设置,如 [变量名称=变量内容]
Port 非正规端口号,如 [小于 65535 的数字]
redirect 服务跳转,如 [IP 端口]
includedir 调用外部设置,可导入某个目录内的配置文件,如 [目录名称]
bind 服务 IP 绑定,如 [IP]
interface bind 相同。
only_from 防火墙机制,规定可以登录的 IP 地址。
no_access only_from 差不多,规定不可登录的 IP 地址。
access_times 时间控制,设置服务启动的时间。
umask 设置 umask,如 [000,777,022]

设置开机启动

使用 chkconfig 命令设置服务的启动等级。例如查看目前被 chkconfig 管理的服务:

[root@101c7 ~]$ chkconfig --list

netconsole      0:off   1:off   2:off   3:off   4:off   5:off   6:off
network         0:off   1:off   2:on    3:on    4:on    5:on    6:off

如果有 super daemon 管理的服务会分别显示在不同的运行级别下:0~6 代表不同运行级别下的启动状态。其中,3 代表命令行界面,5 代表图形界面。

例如要开启 httpd 在运行级别 3 下自动启动:

[root@101c7 ~]$ chkconfig httpd on

如果要加入自定义的启动脚本(已经存在于 /etc/init.d/ 目录下),可以使用 --add 参数。同样,使用 --del 参数可以删除服务的启动脚本:

[root@101c7 ~]$ chkconfig --add myservice

此外,也可以使用 ntsysv 命令来设置管理服务的开机启动。

Systemd 服务管理

自从 CentOS 7 之后,服务管理机制由 init 脚本管理改为 systemd 启动服务管理。

Systemd 的特性

  • 平行处理模式

    旧的 init 启动脚本是线性模式,只能单任务处理。systemd 可以让所有服务同时启动,更好利用多核心架构。

  • 单命令控制

    只需要一个 systemctl 命令来处理事务。此外,由于 systemd 常驻内存,因此任何要求(On-Demand)都会立刻处理。

  • 自动处理服务依赖

    由于 systemd 可以设置服务依赖检查,因此启动服务时,能自动启用相依赖服务。

  • 依服务功能分类

    systemd 把服务定义为服务单元(Unit),并归类到不同的服务类型(Type)中。旧的 init 仅能分为 stand alone 和 super daemon 两种,而 systemd 可以分为 service、socket、target 等多种不同类型,方便记忆和管理。

  • 可设置群组

    systemd 可将许多功能合为一个 Target 项目,也就是集合有相同目标的服务到一个群组,通过群组统一执行。

  • 向下兼容 init 服务脚本

    systemd 可以兼容旧的 init 启动脚本,并通过 systemd 来管理。

Systemd 与 Init 的区别

Systemd 与 Init 的区别主要有下面这些:

  • 在 run level 对应上,只有 1、3、5 对应到 systemd 的某些 target 类型,没有全部对应;
  • systemctl 支持的语法有限,没有 init 纯脚本自由;
  • 没通过 systemctl 来启动的服务,systemd 管理不了;
  • systemd 启动过程中不接受 stdin 传参。也就是不能与用户互动。

Systemd 的 Unit 类型

/usr/lib/systemd/system/ 下的数据可根据扩展名来区分不同的 Unit 类型:

[root@101c7 home]$ ll /usr/lib/systemd/system/ | grep -E '(vsftpd|multi|cron)'
-rw-r--r--. 1 root root  318 Aug  8  2019 crond.service
-rw-r--r--. 1 root root  492 Feb  2  2021 multi-user.target
drwxr-xr-x. 2 root root  258 Sep  7 05:54 multi-user.target.wants
lrwxrwxrwx. 1 root root   17 Sep  7 05:53 runlevel2.target -> multi-user.target
lrwxrwxrwx. 1 root root   17 Sep  7 05:53 runlevel3.target -> multi-user.target
lrwxrwxrwx. 1 root root   17 Sep  7 05:53 runlevel4.target -> multi-user.target
-rw-r--r--. 1 root root  171 Jun  9 12:15 vsftpd.service
-rw-r--r--. 1 root root  184 Jun  9 12:15 vsftpd@.service
-rw-r--r--. 1 root root   89 Jun  9 12:15 vsftpd.target

如上例,其中 vsftpd 和 crond 是服务(service),而 multi-user 是 target 类型。

常见的类型有下面这些:

  • 一般服务类型(.service)

    主要是系统服务及网络服务,最常见的类型。

  • 套接字服务(.socket)

    主要是 IPC(Inter-process communication)的传输信息插槽档(socket file)功能。这种类型的服务通常用在监控信息传递,当有通过此 socket 请求时,将请求发送给对应服务。若服务未启动,则先启动后再传送请求。使用 socket 类型的服务一般不常用,因此开机时通常会稍微延迟启动。一般用于本机服务较多,例如图形界面很多软件都是通过 socket 来通信。

  • 执行环境类型(.target)

    其实是一群 unit 的集合。例如图形模式、救援模式等。

  • 文件系统挂载服务(.mount/.automount)

    例如网络 NFS 文件系统挂载等。

  • 文件监控类型或目录类型(.path)

    某些服务需要监控特定目录来提供队列服务,例如最常见的打印服务。

  • 循环执行的服务(.timer)

    有点类似 anacrontab,不过由 systemd 管理更具弹性。

Systemctl 命令

依据 Unit 类型的不同,systemctl 管理方式有点不同。

查询 Unit

可以使用 systemctl list-units 命令来查询 unit 或文件。

查询运行中的 unit,默认使用 list-units。如果要查询所有 unit,可以使用 --all 参数:

[root@101c7 home]$ systemctl --all
  UNIT                                     LOAD   ACTIVE SUB       DESCRIPTION
  ext333.mount                             loaded active mounted   /ext333
  NetworkManager.service                   loaded active running   Network Manager
  network.target                           loaded active active    Network
LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

135 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
lines 118-143/143 (END)

其中,UNIT 是项目名,LOAD 表示开机时是否会被载入,ACTIVE 和 SUB 是运行状态。

例如,查询所有 socket 服务:

[root@101c7 ~]$ systemctl list-sockets
LISTEN                      UNIT                         ACTIVATES
/dev/log                    systemd-journald.socket      systemd-journald.service
/run/dbus/system_bus_socket dbus.socket                  dbus.service

13 sockets listed.
Pass --all to see loaded but inactive sockets, too.

列出所有已安装的 unit,使用 list-unit-files 查询:

[root@101c7 home]$ systemctl list-unit-files
UNIT FILE                                     STATE   
proc-sys-fs-binfmt_misc.automount             static  
dev-hugepages.mount                           static  
dev-mqueue.mount                              static 

如果要仅查询与 httpd 相关的启动服务,可以使用 --type 指定类型:

[root@101c7 home]$ systemctl --type=service --all | grep httpd
  httpd.service                       loaded    active   running The Apache HTTP Server

管理 Service Unit

systemctl 管理 service 时主要命令有:

命令 说明
start 立即启动服务
stop 立即关闭服务
restart 立即重启服务
reload 不关闭服务情况下,重新载入配置文件,让配置生效
enable 设置开机启动
disable 取消开机启动
status 查看服务运行状态
is-active 服务有没有处于活动状态
is-enable 服务有没有开机启动
mask 注销服务
unmask 取消注销

例如查看 atd 服务的状态:

[root@101c7 home]# systemctl status atd.service
● atd.service - Job spooling tools
   Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2023-05-02 02:06:10 UTC; 21min ago
     Docs: man:atd(8)
 Main PID: 1913 (atd)
    Tasks: 1 (limit: 32768)
   Memory: 824.0K
   CGroup: /system.slice/atd.service
           └─1913 /usr/sbin/atd -f

May 02 02:06:10 101c7 systemd[1]: Started Job spooling tools.

关键信息有:

  • Loadedenabled 代表开机启动,disabled 为不启动,static 为需要别的服务唤醒,masked 代表无法设置启动。
  • Active:unit 的状态,正在运行(running)或是没有运行(dead)。
  • 日志:最下面是日志信息,格式为:时间 信息发出的主机 信息发出的服务 信息内容

使用 stop 正常关闭 atd 服务:

[root@101c7 home]$ systemctl stop atd.service
[root@101c7 home]$ systemctl status atd.service
● atd.service - Job spooling tools
   Loaded: loaded (/usr/lib/systemd/system/atd.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Sat 2021-09-18 13:06:56 EDT; 1s ago
  Process: 27679 ExecStart=/usr/sbin/atd -f $OPTS (code=exited, status=0/SUCCESS)
 Main PID: 27679 (code=exited, status=0/SUCCESS)

Sep 18 13:06:56 101c7 systemd[1]: Stopping Job spooling tools...
Sep 18 13:06:56 101c7 systemd[1]: Stopped Job spooling tools.

如果使用 kill 来关闭服务,systemd 会无法继续监控服务。

常见运行状态:

  • active (running):此时服务有一或多个进程正在运行。
  • active (exited):单次执行的服务,目前没有在运行。
  • active (waiting):等待队列执行中。
  • inactive:服务没有运行。

给 chronyd 设置开机启动:

[root@101c7 home]$ systemctl enable --now chronyd
Created symlink from /etc/systemd/system/multi-user.target.wants/chronyd.service to /usr/lib/systemd/system/chronyd.service.

从返回信息看,其实就是在 /etc/systemd/system/multi-user.target.wants/ 下面新建了一个链接。

管理 Target Unit

systemctl 管理 target 时主要命令有:

命令 说明
get-default 取得目前的 target
set-default 设置默认 target
isolate 切换模式
poweroff/reboot 关机/重启
suspend/hibernate 进入暂停/休眠模式
rescue/emergency 进入救援/紧急模式

首先查询系统中的所有 target:

[root@101c7 home]$ systemctl --type=target --all
  UNIT                      LOAD      ACTIVE   SUB    DESCRIPTION
  basic.target              loaded    active   active Basic System
  bluetooth.target          loaded    active   active Bluetooth

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

35 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.

结果显示有 35 个 target,常见的 target 有以下几个:

  • graphical.target:文本加图形界面,包含了 multi-user.target。
  • multi-user.target:纯文本模式。
  • rescue.target:救援模式。
  • emergency.target:无法使用救援模式时,可以进入紧急处理模式。
  • shutdown.target:关机流程。
  • getty.target:和 tty 有关。

例如要切换到图形界面模式:

[root@101c7 home]$ systemctl get-default
multi-user.target
[root@101c7 home]$ systemctl isolate graphical.target

查询服务依赖

可以使用命令 list-dependencies 来查询:

[root@101c7 ~]$ systemctl list-dependencies
default.target
● ├─atd.service
● ├─auditd.service
● ├─chronyd.service

反向查询服务被依赖情况可以用 --reverse 参数。例如查询 sshd 服务被依赖目标:

[root@101c7 ~]$ systemctl list-dependencies sshd.service --reverse
sshd.service
● └─multi-user.target
●   └─graphical.target

Systemctl 配置

系统服务的开机启动配置位于/etc/systemd/system目录下。如果要修改服务的实际脚本,则应该将其放置在/usr/lib/systemd/system/目录下。

Systemd 配置目录

systemd 将每种服务依据功能放置在不同目录:

  • /usr/lib/systemd/system/:包含每个服务的主要启动脚本设置,类似于/etc/init.d

  • /run/systemd/system/:包含系统在运行过程中所生成的服务脚本,优先级高于/usr/lib/systemd/system

  • /etc/systemd/system/:包含用户创建的服务执行脚本,类似于/etc/rc.d/rc5.d/Sxx,执行优先级最高。

  • /etc/sysconfig/:包含服务初始化时的一些参数配置。

  • /var/lib/:包含服务产生的数据默认存储目录。

  • /run/:用于放置临时文件,包括锁文件、PID 文件等。

Systemctl 配置文件

以下是以 sshd 服务的配置文件为例:

[root@101c7 ~]$ cat /usr/lib/systemd/system/sshd.service 
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

配置文件分为三段:

  • [Unit]:Unit 定义描述文字,文档位置,服务依赖关系等设置。

    参数 说明
    Description 使用 systemctl status 查询时显示在第一行的描述
    Documentation 提供的服务配套文档配置
    After 说明此 Unit 的前导启动服务,没有强制约束
    Before 说明此 Unit 的被依赖服务,同样没有强制约束力
    Requires 定义此 Unit 的依赖服务,如果依赖服务没启动,此 Unit 也无法启动
    Wants 定义在此 Unit 后启动的服务,没有明确规范
    Conflicts 冲突性检查,代表和此 Unit 有冲突的服务
  • [Service]:这段也有可能是 [Socket]、[Path]、[Timer] 等,根据 Unit 类型决定。规范了配置文件路径、启动参数等。

    参数 说明
    Type 说明服务启动方式,有下面几种类型
    simple:默认值,服务由 ExecStart 启动,启动后常驻内存
    forking:通过 spawns 衍生出其他子程序作为主要服务,父程序随后终止
    oneshot:只用跑一次的程序,不会常驻内存
    dbus:服务必须取一个 D-Bus 名称
    idle:在系统空闲时才运行
    EnvironmentFile 指定启动脚本的环境配置文件
    ExecStart 启动服务运行的命令或脚本
    ExecStop 关闭服务运行的命令
    ExecReload 重载服务运行的命令
    Restart 设置服务自动重启参数,假如设为 1 则表示总会重启,只能用 systemctl 来停止
    RemainAfterExit 设为 1 时,当服务所属的所有程序都停止后再次尝试启动
    TimeoutSec 服务启动或关闭时等待的超时时间,时间一到会强制结束进程
    KillMode process 表示终止服务时只结束主程序,control-group 则是一同结束关联进程
    RestartSec 重启服务前等待的时间
  • [Install]:指定此 unit 安装的 target

    参数 说明
    WantedBy 后面大多接 target unit,就是说此 unit 属于哪个 target 环境
    Also 此 Unit 被设为开机启动时,其他一同要设为开机启动的 Unit
    Alias 设置一个链接别名

如果要将备份脚本 backup.sh 设置为 service 用 systemctl 来管理,可以新建一个简单的配置文件,例如:

[root@101c7 ~]$ vi /etc/systemd/system/backup.service
[Unit]
Description=backup my dir
Requires=atd.service

[Service]
Type=simple
ExecStart=/bin/bash -c "echo /root/backup.sh | at now"

[Install]
WantedBy=multi-user.target
"/etc/systemd/system/backup.service" [New] 10L, 170C written
[root@101c7 ~]$ systemctl daemon-reload
[root@101c7 ~]$ systemctl start backup
[root@101c7 ~]$ systemctl status backup
● backup.service - backup my dir
   Loaded: loaded (/etc/systemd/system/backup.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

Sep 19 01:00:34 101c7 systemd[1]: Started backup my dir.
Sep 19 01:00:34 101c7 bash[9147]: job 10 at Sun Sep 19 01:00:00 2021

重复配置方式

有一些服务名带有@符号代表启动多重的重复设置,目的是简化多个执行的启动设置。例如 getty@.service

[root@101c7 ~]$ cat /usr/lib/systemd/system/getty@.service
[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
After=rc-local.service
Before=getty.target
IgnoreOnIsolate=yes
ConditionPathExists=/dev/tty0

[Service]
ExecStart=-/sbin/agetty --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=

[Install]
WantedBy=getty.target
DefaultInstance=tty1

ExecStart 指定的启动命令 agetty --noclear %I%I 指代范例名称,这里等于 tty1。具体在 getty.target 里有定义:

[root@101c7 ~]$ systemctl show getty.target
Id=getty.target
Names=getty.target
Wants=getty@tty1.service
WantedBy=multi-user.target
Conflicts=shutdown.target
Before=multi-user.target
After=getty@tty1.service

当执行完 getty.target 后,会持续要求 getty@tty1.service 服务启动,由于 /usr/lib/systemd/system/etc/systemd/system 中没有 getty@tty1.service 存在,systemd 则找到 getty@.service 设置,将 @ 后面的数据带入成 %I 的变量。

当然也可以手动指定 @ 后面的参数来启动服务:

[root@101c7 ~]$ systemctl start getty@tty9.service

timer 类型配置文件

我们可以利用 systemd 来设置定时任务,比起用 crond 设置来说,多了日志记录功能,并且可以和其他服务相结合。

想要使用 timer 的功能必须:

  • 系统的 timer.target 一定要启动;
  • 要有个自定义 .service 服务存在;
  • 要有个自定义 .timer 的时间启动服务存在。

一个 timer 类配置主要用到 [Timer] 段,可用的参数如下:

参数 说明
OnActiveSec timers.target 启动多久后执行此 Unit
OnBootSec 当开机后多久执行
OnStartupSec systemd 第一次启动后多久执行
OnUnitActiveSec Unit 服务最后一次启动后,隔多久再执行一次
OnUnitInactiveSec Unit 服务最后一次停止后,隔多久再执行一次
OnCalendar 使用实际时间的方式启动服务
Unit 一般不需要设置,只有在 .timer 文件和 .service 文件名不一致时用到
Persistent 当使用 OnCalendar 设置时,指定该功能要不要持续进行。通常为 yes

时间设置可以使用间隔时间,例如隔 3 小时(3h),隔 5 天又 300 分钟(300m 5day)。也可以使用实际时间格式:

英语口语 实际时间格式
now Wed 2020-09-09 15:43:05
today Wed 2020-09-09 00:00:00
tomorrow Thu 2020-09-10 00:00:00
hourly --:00:00
daily --* 00:00:00
weekly Mon --* 00:00:00
monthly --01 00:00:00
+1h16m55s Thu 2020-09-09 17:00:00
2020-09-11 Fri 2020-09-11 17:00:00

例如设置一个backup.timer作用为开机后 1 小时执行,每 2 天执行一次:

[root@101c7 ~]$ vi /etc/systemd/system/backup.timer
[Unit]
Description=backup my dir timer

[Timer]
OnBootSec=1h
OnUnitActivesec=2d

[Install]
WantedBy=multi-user.target

"/etc/systemd/system/backup.timer" [New] 9L, 118C written

.timer设置为开机启动,对应的.service可以不需要开机启动:

[root@101c7 ~]$ systemctl daemon-reload
[root@101c7 ~]$ systemctl enable --now backup.timer
Created symlink from /etc/systemd/system/multi-user.target.wants/backup.timer to /etc/systemd/system/backup.timer.
[root@101c7 ~]$ systemctl restart backup.timer
[root@101c7 ~]$ systemctl list-unit-files | grep backup
backup.service                                disabled
backup.timer                                  enabled 

查看一下这个 timer unit 的启动时间、backup.service上次执行时间和下次执行间隔时间:

[root@101c7 ~]$ systemctl show timers.target | grep ConditionTimestamp
ConditionTimestamp=Sat 2021-09-18 23:12:52 EDT
[root@101c7 ~]$ systemctl show backup.service | grep ExecMainExitTimestamp
ExecMainExitTimestamp=Sun 2021-09-19 01:34:00 EDT
[root@101c7 ~]$ systemctl show backup.timer | grep Next
NextElapseUSecRealtime=0
NextElapseUSecMonotonic=0

使用OnCalendar实际时间设置为每周日 14:00 执行一次可以这样:

[root@101c7 ~]$ vi /etc/systemd/system/backup.timer
[Unit]
Description=backup my dir timer

[Timer]
OnCalendar=Sun *-*-* 14:00:00
Persistent=true
Unit=backup.service

[Install]
WantedBy=multi-user.target
~
"/etc/systemd/system/backup.timer" 10L, 152C written
[root@101c7 ~]$ systemctl daemon-reload
[root@101c7 ~]$ systemctl restart backup.timer
[root@101c7 ~]$ systemctl show backup.timer | grep Next
NextElapseUSecRealtime=51y 8month 2w 4d 12h
NextElapseUSecMonotonic=0

注意,NextElapseUSecRealtime时间是以 Unix 标准时间显示。