编写 systemd 服务文件是一个非常重要的技能,特别是当你想要控制系统服务的启动、停止和管理时。systemd 服务文件通常是用于定义如何启动和管理后台服务、进程或命令。掌握如何编写服务文件会让你能够根据需求自定义服务的行为。

systemd 服务文件结构

一个基本的 systemd 服务文件有几个常见的部分,通常分为 [Unit][Service][Install] 三个主要段落。下面将逐一解释每个段落的含义及如何配置。

1. systemd 服务文件基本结构

[Unit]
Description=描述服务的简短信息
After=依赖关系服务,例如 network.target

[Service]
Type=服务类型
ExecStart=启动命令
User=运行服务的用户
Group=运行服务的用户组
Restart=重启策略
Environment=环境变量

[Install]
WantedBy=目标服务(例如 multi-user.target)
  • [Unit]:定义服务的元数据和依赖关系。
  • [Service]:定义如何启动和管理服务。
  • [Install]:定义服务如何与目标关联,以便在启动时启用或禁用服务。

2. 各个段落的详细解释

[Unit]

[Unit] 段主要用来定义服务的描述信息、依赖关系和其他相关设置。

  • Description: 服务的简短描述,通常是一个简洁明了的服务名称。
  • After: 定义服务启动顺序,表示该服务在某些其他服务或目标启动之后启动。常用的目标包括 network.target(网络服务已启动时),multi-user.target(多用户模式下)等。
  • Before: 指定此服务必须在其他服务之前启动。
[Unit]
Description=My Custom Service
After=network.target

[Service]

[Service] 段定义了如何启动和管理服务。它是大多数服务文件的核心部分。

  • Type: 定义服务的类型,常见的类型有:
    • simple:默认类型,ExecStart 启动的命令被认为是主进程,systemd 会等待它退出。
    • forking:服务进程在启动时会创建子进程(例如后台守护进程),systemd 等待该进程的 PID 文件来确定进程是否启动成功。
    • oneshot:执行一次任务后结束,适用于短期任务(例如挂载、卸载等操作)。
    • notify:当主进程通过 sd_notify() 通知 systemd 时,systemd 会认为服务已经启动。
    • dbus:服务通过 D-Bus 与 systemd 进行通信。
  • ExecStart: 定义启动服务时执行的命令或脚本路径。此命令是服务的主进程。
  • ExecStop: 定义停止服务时执行的命令。如果你希望在服务停止时执行额外的命令,可以设置此选项。
  • ExecReload: 当你希望重新加载服务时执行的命令。
  • Restart: 定义服务崩溃时的重启策略。常用的选项包括:
    • no:不自动重启。
    • always:如果服务崩溃或停止,systemd 会重启它。
    • on-failure:仅在服务失败时重启。
  • UserGroup: 设置服务运行的用户和用户组。默认是 root,但建议为安全考虑使用非 root 用户来运行应用。
  • Environment: 设置环境变量。
[Service]
Type=simple
ExecStart=/usr/bin/my-service
Restart=on-failure
User=myuser
Group=mygroup

[Install]

[Install] 段定义服务如何与启动目标关联,通常是系统启动时自动启动该服务。

  • WantedBy: 这个选项指定服务在哪个目标(target)下启用。例如,multi-user.target 表示服务在多用户模式下启用,graphical.target 表示服务在图形界面目标下启用。可以设置多个目标,服务会在达到其中之一时启动。
[Install]
WantedBy=multi-user.target

3. 编写一个简单的 systemd 服务文件

假设我们有一个脚本 /usr/local/bin/my-script.sh,我们想通过 systemd 来管理它。这个脚本会在启动时自动运行。

[Unit]
Description=My Simple Script Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/my-script.sh
Restart=on-failure
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target

4. 步骤解析

  1. Description=My Simple Script Service:给服务起一个名字,描述它的功能。
  2. After=network.target:表示该服务在网络服务启动之后执行。通常网络服务是依赖服务。
  3. ExecStart=/usr/local/bin/my-script.sh:指定执行的命令或脚本路径。
  4. Restart=on-failure:如果服务崩溃或退出,systemd 会自动重启该服务。
  5. User=myuserGroup=mygroup:指定服务使用非 root 用户来运行,增加安全性。
  6. WantedBy=multi-user.target:表示该服务在 multi-user.target 阶段启动,通常表示进入多用户模式时自动启动。

5. 配置和启用服务

将上面内容保存为一个 .service 文件,比如 /etc/systemd/system/my-service.service

启用并启动服务

  1. 启用服务,使其在系统启动时自动启动:

     sudo systemctl enable my-service.service
    
  2. 启动服务:

     sudo systemctl start my-service.service
    
  3. 查看服务的状态:

     sudo systemctl status my-service.service
    

停止并禁用服务

  1. 停止服务:

     sudo systemctl stop my-service.service
    
  2. 禁用服务,使其不再在系统启动时自动启动:

     sudo systemctl disable my-service.service
    

6. 日志查看

通过 journalctl 查看服务的日志信息,这对于调试和查看服务的执行情况非常有用。

sudo journalctl -u my-service.service

总结

  • systemd 服务文件由 [Unit][Service][Install] 三个主要段落组成。
  • 在服务文件中,你可以定义服务的描述、启动命令、重启策略、用户等信息。
  • 使用 systemctl 命令来启用、启动、停止、查看和禁用服务。
  • WantedBy 决定服务在哪个目标(target)下启用,通常用 multi-user.target 表示服务在多用户模式下启动。

通过这些基本步骤,你可以创建和管理自己的 systemd 服务文件。如果你遇到任何问题,随时可以进一步深入学习 systemd 的更多高级功能。