Systemd Service 单元文件的编写
目前我所掌握的使一个Linux下的软件开机自启动的方法只有将其加入rc.local文件或桌面环境的autostart文件中,但前者不能很好的保证软件的依赖关系,后者要求系统具备桌面环境。虽然知道现在大多数发行版已经使用systemd来管理系统服务,但一直没有研究过如何编写其单元文件,为了解决上述问题,研究了一下systemd的service单元文件的写法,将遇到的问题做个总结。
systemctl
systemctl命令基本相当于System V init的service命令,可用于系统服务的管理,也可以进行电源管理,常用命令如下:
- 系统服务管理
1 | systemctl enable <unit> # 将<unit>设置为开机自启动 |
- 电源管理
1 | systemctl reboot # 重启 |
systemd单元文件
systemd的单元文件有以下几类:
- 系统服务
.service - 挂载点
.mount - sockets
.socket - 系统设备
.device - 交换分区
.swp - 文件路径
.path - 启动目标
.target - 定时器
.timer
当使用systemctl对一个单元进行操作时,一般需要使用单元的全名,如ssh.service,但如果使用不带后缀名的单元名称,systemctl将会把这个单元当做系统服务(.service)进行操作。如果一个单元文件中存在@字符,表示该单元文件是一个模板单元,当使用systemctl操作模板单元时,需要对单元进行实例化,否则会调用失败。
单元文件可以从两个地方加载:
/usr/lib/systemd/system/:软件包安装的单元/etc/systemd/system/:系统管理员安装的单元
加载优先级上,系统管理员安装的单元优先级高于软件包安装的单元。
Serivce单元文件编写
service单元文件有三个段落:[Unit] [Service] [Install];其单元文件的编写模板可以参考man手册的EXAMPLE章节,上面提到的单元加载目录下也有很多例子可供参考。
依赖关系的处理
如果需要A单元在B单元启动之后启动,仅指定Requires=B或Wants=B是不行的,如果不指定After=B,A单元和B单元会并行启动。为了保证A在B单元启动之后再启动,应该在A的配置文件中[Unit]段中添加Requires=B和After=B。
在[Unit]段中,用于表示依赖关系的选项有Wants、Requires、BindsTo和PartOf,他们所表示的依赖关系的强弱可以大致表示为
1 | PartOf = BindsTo > Requires > Wants |
Wants的依赖关系最弱,当依赖的单元启动失败时,不会对其他单元的启动造成影响;Requires所指定的单元中有一个启动失败时,其他相关的单元都不会被启动;BindsTo的依赖性比Requires更强,当启动使用了BindsTo的单元时,BindsTo所指定的单元均会被启动,当列出的单元全部被启动后,该单元也会被启动,但是如果指定的单元中任意一个终止或重启,该单元也会终止或重启;PartOf类似于BindsTo,不同的是,使用PartOf的单元不会随着依赖单元的启动而启动。
为启动的服务设置环境变量
可以在单元配置文件的[Service]段落中添加Environment选项,例如
1 | Environment=LANG=zh_CN.UTF_8 |
如果需要添加多个环境变量,应在 可以在[Service]中添加多个Environment,而不是在一个Environment后面添加多个环境变量的值。[Service]中添加多个Environment,也可以在Environment后添加多个环境变量的定义,使用空格分隔,如:
1 | Environment=PATH=/home/jack CONFIG='-std=c99' |
对没错也可以使用',可以查看man手册的相关章节获得更多信息。
也可以使用EnvironmentFile选项指定一个包含环境变量列表的文件路径,这个文件中每一行都是一个环境变量的值。例如,单元文件中[Service]字段包含选项如下:
1 | EnvironmentFile=/home/jack/env |
/home/jack/env文件包含内容格式如下:
1 | LANG=zh_CN.UTF-8 |
设置运行服务的用户和组
在单元配置文件的[Service]段落中添加User和Group选项即可,如
1 | User=Jack |
设置服务的工作路径
在单元配置文件的[Service]段落中添加WorkingDirectory选项,如
1 | WorkingDirectory=/home/Jack/ |
总结
经过了激烈的讨论之后绝大多数发行版还是迁移到了Systemd,这个东西确实符合UNIXkeep it simple and stupid的哲学,而是一个大而全的东西。Systemd出现后接管了Linux上包括启动日志在内的很多东西,造成使用者们之前掌握的一部分技能在这上面不顶用了,这会不会也是Systemd出现后遭到抵制的原因之一呢。
更多Systemd的相关资料可以查看man手册的systemd章节,以及ArchLinux Wiki页面中关于Systemd的部分。