我写了一个 systemd 脚本mqtt.service
,位于 /home/root
目录中
这是我的mqtt.service
脚本:
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=mqtt
DefaultDependencies=no
After=xdk-daemon.service
[Service]
Restart=always
RestartSec=10
ExecStart=/bin/sh /home/root/mosquitto-1.4/mqtt_start.sh
[Install]
WantedBy=multi-user.target
这就是内容mqtt_start.sh
#!/bin/sh
/home/root/mosquitto-1.4/src/mosquitto -c /home/root/mosquitto-1.4/mosquitto.conf -d -p 1885 > /dev/null 2>&1
如果我粘贴该行:
/home/root/mosquitto-1.4/src/mosquitto -c /home/root/mosquitto-1.4/mosquitto.conf -d -p 1885
进入终端,mqtt代理正常启动但在这里我无法启动它
我做到了
$ systemctl enable /home/root/mqtt.service
$ systemctl status mqtt.service
● mqtt.service - mqtt
Loaded: loaded (/home/root/mqtt.service; enabled)
Active: failed (Result: resources) since Mon 2015-04-06 10:42:48 UTC; 24s ago
Main PID: 677 (code=exited, status=0/SUCCESS)
Apr 06 10:42:39 edison sh[677]: 1428316959: Warning: Mosquitto should not be run as root/administrator.
Apr 06 10:42:48 edison systemd[1]: mqtt.service holdoff time over, scheduling restart.
Apr 06 10:42:48 edison systemd[1]: mqtt.service failed to schedule restart job: Unit mqtt.service failed to load: No such file or directory.
Apr 06 10:42:48 edison systemd[1]: Unit mqtt.service entered failed state.
让我知道我错在哪里。
编辑 :
重新启动后我做了:
systemctl 状态 mqtt.service和结果:
● mqtt.service
Loaded: not-found (Reason: No such file or directory)
Active: inactive (dead)
答案1
您的 systemd 服务单元默认为,Type=simple
但您的包装脚本正在使用该--daemon
选项。这是准备协议不匹配。就绪协议不匹配会导致服务无法正确启动,或者(更常见)被 systemd(错误)诊断为失败。
后者正在这里发生。因为你对系统进行了过度设计,你的守护进程出现了不必要的分叉两次以上,而错误的进程是实际的守护进程。此外,您还不必要地在包装脚本中重复 systemd 服务单元功能。
完全摆脱包装器 shell 脚本,并像这样编写您的服务单元:
[单元] 描述=Mosquitto MQTT 代理 文档=man:mosquitto(8) 文档=man:mosquitto.conf(5) ConditionPathExists=/home/root/mosquitto-1.4/mosquitto.conf After=xdk-daemon.service [服务] ExecStart=/home/root/mosquitto-1.4/src/mosquitto -p 1885 -c /home/root/mosquitto-1.4/mosquitto.conf ExecReload=/bin/kill -HUP $MAINPID 用户=蚊子 重新启动=失败时 重新启动秒=10 [安装] WantedBy=多用户.target
请注意:
- 您不需要该
--daemon
选项。经纪人已经被守护进程化当 systemd 运行它时。 - 您不应该使用该
--daemon
选项。 Mosquitto 不会讲forking
就绪协议,因为它是实际上还没有准备好分叉后退出。 (我们希望有一天人们能够编写这样的程序,这样他们就可以继承他们的监听套接字因此可以通过套接字激活。) - 您不需要在包装器脚本中摆弄标准输出和错误。 systemd 将处理守护进程的标准输出和错误。如果确实需要的话,它们可以在服务单元文件中进行配置,但这对于这个程序来说似乎根本没有必要。
- 由于 systemd 可识别的正确进程现在是守护进程,
systemctl reload mqtt.service
现在可以向正确的位置发送信号并工作。 - systemd 本身将以 user 身份调用代理
mosquitto
;因此,您需要确保存在具有该名称的用户帐户,并且具有必要的访问权限。请注意日志中的警告。 - systemd 人员推荐
on-failure
作为重启策略always
。 DefaultDependencies
除非是守护进程,否则不应设置为 false实际上可以运行在启动过程的早期和关闭过程的后期,对于大多数情况来说通常情况并非如此。默认服务单元依赖关系是合适的对于这种守护进程。