openSUSE:Systemd 打包指南
目录
RPM 宏
自 openSUSE 12.1 起,打包 systemd service 文件必须用到几个 RPM 宏。
编译环境
您应该添加:
%if 0%{?suse_version} >= 1210 BuildRequires: systemd %endif
作为编译依赖。
依赖
添加:
%{?systemd_requires}
来确保您的软件包安装了必要的依赖。
service 文件
服务文件必须被安装到 %{_unitdir} (也就是 /usr/lib/systemd/system
) 永远不能安装到 /etc/systemd/system
(这样用户就可以覆盖它们了,也和打包不冲突。又叫「mask」)。
在安装脚本中注册 service
添加如下宏到您的脚本:
如果 foo.service bar.service
是您想要安装的两个 systemd 服务:
%pre %service_add_pre foo.service bar.service %post %service_add_post foo.service bar.service %preun %service_del_preun foo.service bar.service %postun %service_del_postun foo.service bar.service
如果您的软件包也提供了 sysv 启动脚本,这些宏将会透明地处理 sysv 启动脚本迁移 (只要启动脚本和 systemd 服务的名称相同)
如果您的软件包想要支持针对比 12.1 旧的 openSUSE 编译,您应该针对这些宏使用条件测试:
%if %{?suse_version} >= 1210 [...] %endifIf
启用服务
默认,服务不会在软件包安装后启用。如果您想要默认启用您的服务,您应该在 OBS 上针对 systemd-presets-branding-openSUSE
软件包做提交,修改 default-openSUSE.preset
文件,添加:
enable your_service_name.service
在 /var/run 和 /run 创建文件/子目录
自 openSUSE 12.2 起,/var/run (通常是绑定到或 symlink 到 /run 的)被作为缓存文件系统挂载。因此软件包不应该再包含在 /var/run(或 /run) 下的任何文件夹/文件了,因为它们会在下次启动后消失。
如果需要在里面创建一个新文件/子目录,您应该打包一个 tmpfiles.d 文件(语法参考 man tmpfiles.d),安装到 /usr/lib/tmpfiles.d/。tmpfiles.d 文件的一个小例子:
# 创建一个权限 0770 所有者 foo 和群组 bar 的目录 d /var/run/my_new_directory 0770 foo bar
您应该在 %install 章节这么安装它们:
%{__install} -d -m 0755 %{buildroot}/usr/lib/tmpfiles.d/ %{__install} -m 0644 %{SOURCE4} %{buildroot}/usr/lib/tmpfiles.d/%{name}.conf
如果您期望文件/目录在软件包安装后立即可用(重启前),添加此行到您的软件包 %post:
systemd-tmpfiles --create /usr/lib/tmpfiles.d/<file_name>
如果不想用 /usr/lib/tmpfiles.d,对于13.1或之后的版本也可以用 %_tmpfilesdir 宏。对于老版本,必须在 spec 文件顶部添加以下内容:
%{!?_tmpfilesdir:%global _tmpfilesdir /usr/lib/tmpfiles.d}
向后兼容性
rc 软链接
/usr/sbin/rcname 软链接仍然可以保留。要让它在 systemd 下工作,将每个单元(支持的服务和目标类型)都链到 /usr/sbin/service :
ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcname
附加行为
初始化脚本有些情况下会实现除了常规的 start/stop/status 等以外的附加行为。对于 systemd 的 service 文件,这些附加的功能是不存在的。而他们对一些服务仍然很有用。因此 /usr/sbin/service 实现了 "legacy actions",就像 Fedora 中一样。
假设先前的初始化脚本 "foo" 包含一个行为 "frob"。现在 service 文件被命名为 "foo.service" 而你想让它仍然支持 "frob" 行为。那么在工厂版中自 2014-03-11 (13.1之后) 的版本起,你可以创建一个脚本
/usr/lib/initscripts/legacy-actions/foo/frob
来实现所需要的功能。 显然,此行为只会在 /usr/sbin/service 调用服务的时候启动,例如
# service foo frob
或者
# rcfoo frob