![进一步阅读](https://linux22.com/image/67722/%E8%BF%9B%E4%B8%80%E6%AD%A5%E9%98%85%E8%AF%BB.png)
我正在尝试编写一个应该公开 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
因此,当我附加strace
pid 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
,错误的使用sudo
to降低特权(而不是获得他们)——切换到合适的服务管理器就可以摆脱这个问题。
不要随意乱搞。 了解您的守护进程实际上是如何运行的,然后编写一个描述它的服务单元。
您的 System 5脚本调用名为with和verbs 的rc
程序。因此乍一看,人们可能会认为 systemd 服务单元也应该如此。但事实证明arkmanager
start
stop
arkmanager
本身是完后还有穷人的守护进程主管用 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 天了。他们也没有制造恐怖。
进一步阅读
- 伦纳特·珀特林 (2013-10-07)。
systemctl
。 systemd 手册页。 freedesktop.org。 - 乔纳森·德博因·波拉德 (2015)。 systemd 恐怖屋。常见答案(固定 URL)。
- https://unix.stackexchange.com/a/207363/5132
- https://askubuntu.com/a/626858/43344
- “自动启动”。专用服务器设置。生存进化维基。