首页 > 解决方案 > 使用 autotools 安装 systemd 服务

问题描述

我有一个自动工具项目,它成功地构建和测试了一个应用程序(https://github.com/goglecm/AutoBrightnessCam)。该应用程序安装在 bin 目录中(前面有用户指定的任何前缀)。这很简单。我现在需要创建一个 systemd 服务以在启动时启动它。我已经创建了服务文件并手动运行它,它工作正常。

最后一点是告诉 configure.ac 和 Makefile.am 用应用程序的正确路径修补 *.service.in 文件(就像 config.h 是从 config.h.in 创建的)。

使用 AC_CONFIG_HEADERS 是否适合将 *.service.in 修补到 *.service 中?也许还有另一个用于“非标题”的宏?

另外,我如何指定服务文件应该登陆(即安装)在/etc/systemd/system 中?

有没有更好的方法在没有 systemd 的情况下在启动时启动这个应用程序?

标签: systemdautotools

解决方案


如何指定服务文件应该登陆(即安装)在 /etc/systemd/system 中?

根据 Systemd 的daemon手册页

<开始报价>

安装 systemd 服务文件

在构建安装时(例如make install,在包构建期间),建议将包安装在pkg-config systemd --variable=systemdsystemunitdir(用于系统服务)或pkg-config systemd --variable=systemduserunitdir(用于用户服务)返回的目录中的 systemd 单元文件。这将使系统中的服务在明确请求时可用,但不会在引导期间自动激活它们。可选地,在软件包安装期间(例如rpm -i由管理员),应通过该systemctl(1)工具的 enable 命令在 systemd 配置目录中创建符号链接,以便在启动时自动激活它们。

建议使用的包使用autoconf(1)如下配置脚本摘录来确定源配置期间的单元安装路径:

PKG_PROG_PKG_CONFIG
AC_ARG_WITH([systemdsystemunitdir],
     [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
     [with_systemdsystemunitdir=auto])
AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
     def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)

     AS_IF([test "x$def_systemdsystemunitdir" = "x"],
   [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
    [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
    with_systemdsystemunitdir=no],
   [with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
      [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])

这个片段允许在 systemd 机器上自动安装单元文件,并且即使在缺少 systemd 的机器上也可以选择允许它们安装。(用户单元目录的这个片段的修改留给读者练习。)

此外,为确保 make distcheck 继续工作,建议在基于项目的顶级Makefile.am文件中添加以下内容:automake(1)

AM_DISTCHECK_CONFIGURE_FLAGS = \
  --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)

最后,单元文件应该安装在系统中,并带有如下的 automake 摘录:

if HAVE_SYSTEMD
systemdsystemunit_DATA = \
  foobar.socket \
  foobar.service
endif

...
</ENDQUOTE>

所以看起来你应该使用systemdsystemunitdirand systemduserunitdir。Autotools 对它的支持如何,嗯...

在 Fedora 31 上使用快速 grepgrep systemdsystemunitdir /bin/autoconfgrep -IR systemdsystemunitdir /usr/share显示尚不支持 Autotools。7年了,还在继续……


有没有更好的方法在没有 systemd 的情况下在启动时启动这个应用程序?

Systemd 应该可以启动您的应用程序。只需systemctl(1)像往常一样使用来启用和启动它们。

根据您的GitHub 和autobrightnesscam.service.in,我不会为此使用 Autotools。您可能会浪费大量时间来解决 Autotols 的缺点(根据经验)。

我的configure.ac脚本(这只是一个 shell 脚本)将复制autobrightnesscam.service.inautobrightnesscam.service,然后用于sed复制正确的目录和文件。然后,我会将更新autobrightnesscam.service的内容复制到AC_CONFIG_COMMANDS_POST. 也许是这样的:

SERVICE_FILE=autobrightnesscam.service
SYSTEMD_DIR=`pkg-config systemd --variable=systemdsystemunitdir`

# Use default if SYSTEMD_DIR is empty
if test x"$SYSTEMD_DIR" = "x"; then
    SYSTEMD_DIR=/etc/systemd/system
fi

AC_CONFIG_COMMANDS_POST([cp "$SERVICE_FILE" "$SYSTEMD_DIR"])
AC_CONFIG_COMMANDS_POST([systemctl enable "$SYSTEMD_DIR/$SERVICE_FILE"])
AC_CONFIG_COMMANDS_POST([systemctl start "$SERVICE_FILE"])

推荐阅读