说明符解析:%i 和 %I 区别?

Jér*_*ôme 10 systemd

我正在尝试将 celery 作为服务运行,如文档中所述

该文档使用%n%I日志文件的说明符:

芹菜服务:

ExecStart= [...] --logfile=${CELERYD_LOG_FILE}
Run Code Online (Sandbox Code Playgroud)

celery.service.d/celery.conf

Environment="CELERYD_LOG_FILE=/var/log/celery/%n%I.log"
Run Code Online (Sandbox Code Playgroud)

执行此操作时,我可以%n在开始时解决的服务状态中看到%I 保持在此阶段:

systemctl status celery.service
[...]
    --logfile=/var/log/celery/worker%I.log
Run Code Online (Sandbox Code Playgroud)

我得到了那些日志文件:

/var/log/celery/worker.log
/var/log/celery/worker-1.log
/var/log/celery/worker-2.log
Run Code Online (Sandbox Code Playgroud)

%i但是,如果我使用,则整个事情都会在开始时解决

celery.service.d/celery.conf

Environment="CELERYD_LOG_FILE=/var/log/celery/%n%i.log"
Run Code Online (Sandbox Code Playgroud)

产生这个:

systemctl status celery.service
[...]
    --logfile=/var/log/celery/celery.service.log
Run Code Online (Sandbox Code Playgroud)

我只得到一个日志文件:

/var/log/celery/celery.service.log
Run Code Online (Sandbox Code Playgroud)

这令人不安。

systemd 文档来看,唯一的区别应该是转义:

  • "%i" | 实例名称 | 对于实例化单元:这是“@”字符和单元名称后缀之间的字符串。
  • "%I" | 未转义的实例名称 | 与 "%i" 相同,但转义已撤消

有什么我想念的吗?

另外,我注意到如果我直接在.service文件中设置日志路径,则只%n%i接受表单。

ExecStart= [...] --logfile=/var/log/celery/%n%i.log
Run Code Online (Sandbox Code Playgroud)

会做,并导致

/var/log/celery/celery.service.log
Run Code Online (Sandbox Code Playgroud)

尽管

ExecStart= [...] --logfile=/var/log/celery/%n%I.log
Run Code Online (Sandbox Code Playgroud)

触发错误:

celery.service failed to run 'start' task: Operation not supported
Failed to start Celery worker.
Run Code Online (Sandbox Code Playgroud)

怎么来的?

我在 Debian Jessie 上使用systemd 215-17

编辑1:

好像%I一点都不懂systemd。我们在使用时看到的%I是特定于 Celery 的。(请参阅芹菜文档)。So%isystemdwhile管理,%I被忽略并由 透明传递systemd,然后由 Celery 管理。

这解释了很多,但留下了一些问题:

  • 这里怎么不systemd明白%I
  • 相反,如果我想通过 Celery a%i怎么办?
  • 如果我直接在.service文件中而不是在.conf文件中传递选项,为什么会有所不同?

我浏览了systemd变更日志,但没有发现任何关于%I比我使用的版本更新的信息。

编辑2:

我在运行时看到此错误消息systemctl status celery.service

[/etc/systemd/system/celery.service.d/celery.conf:18] Failed to resolve specifiers, ignoring: "CELERYD_LOG_FILE=/var/log/celery/%n%I.log"
Run Code Online (Sandbox Code Playgroud)

不过,我无法重现它。我不知道为什么它只发生一次而不是每次都发生。

Phe*_*nyl 6

文档您已经提到,之间的区别%i%I是传递的参数的“逃逸”。

下一个问题是:“逃避”是什么意思?

转义意味着更改特殊字符。%i/dash-by替换特殊字符\x20

警告:如果实例名称包含一个破折号-,这个破折号在变量中被替换%I。这就是为什么文档说“逃避撤消”。

例子

让我们some-service@.service包含以下几行:

[Service]
Environment="OPTIONS=%I %i"
ExecStart=/usr/bin/bash -c "echo $OPTIONS >> /tmp/test-specifier"
Run Code Online (Sandbox Code Playgroud)

然后让我们启动服务:systemctl start some-service@/etc/path/to/some-conf 输出/tmp/test-specifier将是:

/etc/path/to/some/conf -etc-path-to-some-conf
Run Code Online (Sandbox Code Playgroud)

请注意some-conf已成为some/conf变量%I

结论

因此,实例名称的行为/etc/path/to/some-conf是:

  • %i 带转义的说明符: -etc-path-to-some-conf
  • %I 没有转义的说明符: /etc/path/to/some/conf

测试设置

CentOS 7 与 systemd-219-67

可以systemd-escape从命令行尝试使用 systemd 的字符串转义。

参考

https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers http://0pointer.de/blog/projects/instances.html https://www.freedesktop.org/software/ systemd/man/systemd-escape.html