进一步阅读

进一步阅读

我正在尝试编写一个应该公开 options 的 systemd 服务start|stop|status|restart

这是当前的脚本:

[Unit]
Description=Daemon to start ark server
After=network.target

[Service]
ExecStart=/etc/init.d/arkdaemon start
ExecStop=/etc/init.d/arkdaemon stop
Type=forking

[Install]
WantedBy=multi-user.target

我找不到任何方法来指定自定义状态命令。
我想有办法吗,但是如何呢?

答案1

Systemd 支持自定义状态消息,但以下是必须满足的一些先决条件:

  • 服务类型应该是notify
  • /run/systemd/notify您的服务必须通过套接字或调用 systemd-notify使用当前的服务状态更新 systemd

作为参考,您可以检查 Fedora 上的 Apache HTTPD(在其他发行版中可能相同,不知道):

systemctl status httpd.service


● httpd.service - The Apache HTTP Server    
  Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
  Active: active (running) since Fri 2017-10-06 15:21:07 CEST; 18h ago
  Docs: man:httpd.service(8)
  Process: 14424 ExecReload=/usr/sbin/httpd $OPTIONS -k graceful (code=exited, status=0/SUCCESS)  
  Main PID: 4105 (httpd)
  Status: "Total requests: 8; Idle/Busy workers 100/0;Requests/sec: 0.000118; Bytes served/sec:   0 B/sec"

您可以看到 Apache 的状态报告为请求总数:8;空闲/忙碌工人 100/0

因此,当我附加stracepid 4105 时,我们可以看到它定期向以下地址发送状态更新systemd

sudo strace -f -p 4105

wait4(-1, 0x7ffcfab4a25c, WNOHANG|WSTOPPED, NULL) = 0
select(0, NULL, NULL, NULL, {tv_sec=1, tv_usec=0}) = 0 (Timeout)
socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 8
getsockopt(8, SOL_SOCKET, SO_SNDBUF, [212992], [4]) = 0
setsockopt(8, SOL_SOCKET, SO_SNDBUFFORCE, [8388608], 4) = 0
sendmsg(8, {msg_name={sa_family=AF_UNIX, sun_path="/run/systemd/notify"}, msg_namelen=21, msg_iov=[{iov_base="READY=1\nSTATUS=Total requests: 8"..., iov_len=110}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, MSG_NOSIGNAL) = 110
close(8)                                = 0
wait4(-1, 0x7ffcfab4a25c, WNOHANG|WSTOPPED, NULL) = 0

可以看到正在发送READY=1\nSTATUS=请求总数:8...插入插座/run/systemd/notify

推荐阅读

man systemd-notify

或者官方文档

例子 :Systemd 中的服务启动

答案2

我正在尝试编写一个应该公开 options 的 systemd 服务start|stop|status|restart

你的第一个错误。服务单元不是脚本。他们不选项。这些选项是针对systemctl命令的,并且在所有单位中都是统一的。

我意识到使用centos似乎是非标准的,

你的第二个错误与你的第三个错误相关:

我将合并一个 PR 来修复 debian/ubuntu 中的很多内容。那么我们必须为 centos 编写一个替代守护进程,因为它使用不同的 init 方法。

CentOS 是不是排除异己。 Ubuntu 版本 15、Debian 8 和 CentOS 7 都使用 systemd,并且都需要适当的 systemd 服务单元。

ExecStart=/etc/init.d/arkdaemon 启动
ExecStop=/etc/init.d/arkdaemon 停止

你的第四个错误。您不会通过将所有内容都转移到 System 5rc脚本来编写服务单元。除了这在 Debian 和 Ubuntu 上不起作用之外,因为他们试图把一切都押在上面后退至服务单位;这是一个恐怖的概念,值得进入 systemd 恐怖屋。看看 System 5rc脚本,它放回了所有错误的废话 — 活泼的 grep 的输出ps,错误的使用sudoto降低特权(而不是获得他们)——切换到合适的服务管理器就可以摆脱这个问题。

不要随意乱搞。 了解您的守护进程实际上是如何运行的,然后编写一个描述它的服务单元。

您的 System 5脚本调用名为with和verbs 的rc程序。因此乍一看,人们可能会认为 systemd 服务单元也应该如此。但事实证明arkmanagerstartstoparkmanager 本身完后还有穷人的守护进程主管用 shell 脚本编写(很糟糕,因为它们总是如此),它做了所有相同的废话,甚至更多 - grep 的输出ps,使用screen(原文如此!)作为分叉进程的方式,然后发送一个SIGINT对其进行维护,维护自己的(非旋转的)日志文件,并在程序中使用硬连线的 CSI 序列(原文如此!),在管理守护进程时,程序首先不会连接到终端。

你正忙着建造另一个恐怖。停止。

剥去这个摇摇欲坠的可怕大厦,其中一个穷人的守护进程监督另一个,而后者又滥用screen第三个临时监督者的身份,人们会发现底层的服务管理实际上看起来像这样:

[单元]
描述=方舟服务器
文档=https://unix.stackexchange.com/questions/212059/
之后=网络.目标

[服务]
用户=steam
环境=会话=您的Linux会话名称
环境=QUERYPORT=27016
环境=PASS=密码
环境=ADMINPASS=管理员密码
ExecStart=/home/steam/ARK/ShooterGame/Binaries/Linux/ShooterGameServer TheIsland?SessionName=${SESSION}?QueryPort=${QUERYPORT}?ServerPassword=${PASS}?ServerAdminPassword=${ADMINPASS}?listen
限制NOFILE=100000
重新启动=始终

[安装]
WantedBy=多用户.target

迁移到 systemd 的首要规则是什么?这是正确的。现在已经是 2015 年了,很可能已经有人做到了。事实上,这里已经有人比我早 4 天了。他们也没有制造恐怖。

进一步阅读

相关内容