如何在另一个systemd服务启动之前,在启动时启动一个systemd服务?

我在一台旧的HP笔记本上运行着Ubuntu 16.04。
我安装了一些软件,用来创建一个小型的家庭plex服务器。我安装了sonarr、radarr、deluge、jackett等等,它们都会在启动时自动运行!
几天前,我决定安装rclone,并且通过一个GitHub项目创建了一对文件夹,每次启动时都要通过运行一个脚本来挂载它们(我通过终端写入sudo ~/bin/check.mount来启动它)。Sonarr和Radarr被设置为通过deluge下载文件到一个临时文件夹,然后导出到这两个挂载的文件夹之一。
问题是,当我手动启动脚本时,Sonarr/Radarr已经启动并且找不到它们的根文件夹,所以会给我报错。
我想做的是创建一个mountgdrive.service(服务,或者其他必要的方式)来自动启动check.mount脚本,如果这还不够,还要在sonarr.service和radarr.service中插入延迟!这可行吗?
我使用sudo nano /etc/systemd/system/mountgdrive.service写下了这些内容。
[Unit]
Description=MountSmokeScreen
After=network.target

[Service]
Type=oneshot
ExecStart=/home/samsepioldoloresh4ze/bin/check.mount
TimeoutStopSec=20
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target

并且在 sonarr.service 和 radarr.service 中添加了 mountgdrive.serviceAfter= 部分,就像这样。
[Unit]
Description=Sonarr
After=syslog.target network.target mountgdrive.service

[Service]
User=samsepioldoresh4ze
etcetc
....

但是它不起作用!Sonarr和Radarr正常启动,但是驱动器没有挂载!我做错了什么?

此外,rtcwake在我的笔记本电脑上不起作用 - 我认为这是一个内核问题?!有没有办法解决这个问题?


1如果我理解正确的话,您希望在mountgdrive.service成功运行之后再启动sonarr.serviceradarr.service是吗? - Dan
@Dan 没错!问题是,我写的那个 mountgdrive.service 显然在运行时什么都没做(它没有挂载驱动器),然后 sonarr.serviceradarr.service 正常运行,因为 Ubuntu 执行了 mountgdrive.service - samsepioldoloresh4ze
1我还建议您研究一下.mount单元。如果您的mountgdrive.service只是挂载一个目录或类似的操作,您可能可以将其更改为.mount服务。这样做会使它更可靠,尤其是因为您对它有依赖。 - Dan
1个回答

你遇到这个问题的原因是因为你使用了After=,但你还需要Requires=Wants=
管理依赖关系有三个主要属性。我会简要解释一下它们的区别,但你可以在[Unit] Section Options | freedesktop.org找到更多详细信息。
  1. After=

    此选项仅设置单元的顺序,不能保证服务已经完成启动。

  2. Wants=

    此选项允许你的单元在另一个单元完成启动后才启动。(无论它是否成功启动)

  3. Requires=

    Wants=类似,但是只有在依赖项成功启动后,你的单元才会启动。

你还可以使用每个选项的相反

  1. After=Before=反转
  2. Wants=WantedBy=反转
  3. Requires=RequiredBy=反转

要解决问题,你需要将你的挂载服务更改为:

[Unit]
Description=MountSmokeScreen
After=network.target
Before=sonarr.service radarr.service

[Service]
Type=oneshot
ExecStart=/home/samsepioldoloresh4ze/bin/check.mount
TimeoutStopSec=20
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target sonarr.service radarr.service

或者你可以将 Wants=mountgdrive.service 添加到 sonarr.serviceradarr.service 单元中。
你可以通过运行以下命令来实现,而无需修改默认文件(你需要对 radarr.service 做同样的操作):
systemctl edit sonarr.service

插入以下内容:
[Unit]
Wants=mountgdrive.service

注意:如果您不希望当 'mountgdrive.service' 失败时,两个服务都不启动,可以将 Wants= 替换为 Requires 或将 WantedBy= 替换为 RequiredBy=(尽管通常在文档中推荐使用 Wants= 即可)。
编辑:必须将 WantedByRequiredBy 选项放在 [Install] 部分下使用。(感谢 @Yankee 的指正)

谢谢你提到的Wants=WantedBy=,我一定会用上它们的!不过,当我重新启动笔记本电脑时,出现了这个错误:https://i.imgur.com/a3LE3G9.png - samsepioldoloresh4ze
1脚本似乎出现了一个错误。你可以从以Can't open /.config/SmokeScreen/smokescreen.conf结尾的那一行看出来。也许你的脚本中有"/.config/..."这样的内容。你应该用完整路径替换波浪号(`),即/home/your_user_name/.config/....`(或者使用相对路径到你的脚本)。 - Dan
这是check.mount脚本,所以我应该将所有的$(HOME)和$(bindir)更改为完整路径吗?谢谢! - samsepioldoloresh4ze
1@samsepioldoloresh4ze 是的,$HOME在启动时不可用,因为还没有登录的用户。 - Dan
WantedBy=应该放在[Unit]部分吗?我记得它只能放在[Install]中。 - Yankee
我不认为它可以放在[Unit]下面。每当我在[Unit]部分下添加一个WantedBy=子句时,每次我调用任何systemctl命令时,系统日志中都会出现这个消息:Unknown lvalue 'WantedBy' in section 'Unit', ignoring。编辑:实际上,您发布的文档链接显示它应该放在[Install]下面。 - Yankee