4

我从 复制了这个systemd service文件lighttpd-package并对其进行了调整以systemd启动 mojolicious 内置服务器守护程序。我可以保留mojolicious 守护进程ExecReload的设置吗?KillSignal

[Unit]
Description=Start mojolicious.pl daemon
After=syslog.target network.target

[Service]
ExecStart=/path/to/mojolicious.pl daemon --listen "http://*:3001"
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT

[Install]
WantedBy=multi-user.target
4

4 回答 4

9

我认为亚历克斯morbo在说它自动重新加载时正在考虑。对于生产,您最好使用hypnotoad. 如果您确实切换到,hypnotoad那么会有各种有用的信号。例如/bin/kill -USR2 $MAINPID,将进行优雅的重新加载,避免对任何当前连接造成干扰。有关更多信号(对于 hypnotoad),请参阅http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad#SIGNALS

于 2012-07-04T11:26:23.157 回答
2

我不知道您为什么需要“重新加载”,Mojolicious 在应用程序代码更改时执行内部重新加载。您可以将其替换为

/bin/kill -0 $MAINPID

如果该行应该在那里,HUP 将是正常应用程序的终端(除非您以不同方式处理它)

于 2012-06-21T17:12:50.220 回答
1

systemd reload 和 hypnotoad reload 需要一个包装脚本才能正常工作

注意:此解决方法适用于 Mojolicious 6.x。SystemD 兼容性已在 Mojolicious 7.x 中修复

如果您想在 systemd 下重新加载,那么标准的 hypnotoad 重新加载(即hypnotoad myapp.pl)或者kill -USR $MAINPID是不可取的。SystemD 假设一旦重新加载 hypnotoad 服务器的命令返回,重新加载就完成了。但是,相反,这两个选项都会立即退出,并且不要等待重新加载完成。

当我尝试了这些标准的重新加载选项时,systemd 完成了重新加载命令的执行,然后,当 hypnotoad 执行“开始零停机时间软件升级 > 升级成功”时,监视 pid 文件被删除和替换。

如果您已将 systemd 配置为始终运行 hypnotoad 应用程序,则 systemd 将在 hypnotoad 正常运行之后再次重新启动(停止并启动)应用程序。

这是发生的事情:

  • systemd 重新加载 hypnotoad-app (ExecReload=hypnotoad myapp.pl)
  • hypnotoad-app 在被告知重新加载后退出
  • hypnotoad 使用最新的 myapp.pl 启动一个新进程
  • systemd 认为 reload 刚刚完成,并且看到 PIDFile 中的 pid 没有改变
  • hypnotoad 看到旧进程没有负载,杀死它们,并在“升级[is]成功”时删除并使用新进程的 PID 创建一个新的 PIDFile(这是 hypnotoad 的“零停机时间”重新加载过程)
  • systemd 看到 pid 文件被删除(它忽略了它被重新创建,可能是因为在设计上,systemd 想要控制分叉)
  • systemd 等待 HOLDOFF ( RestartSec=<seconds>) 如果已配置
  • systemd 对 hypnotoad-app 进行完整的单元启动

systemd 文档特别指出,当ExecReload=命令返回时,systemd 期望进程已经完成重新加载,并且 pid 文件具有重新加载进程的新 PID。但是 Hypnotoad 不能像那样同步工作。所以 systemd 和 hypnotoad 不能很好地协同工作。

https://www.freedesktop.org/software/systemd/man/systemd.service.html

但是请注意,通过发送信号(如上面的示例行)来重新加载守护程序通常不是一个好的选择,因为这是一个异步操作,因此不适合命令多个服务相互重新加载。强烈建议将 ExecReload= 设置为不仅会触发守护程序的配置重新加载,而且还会同步等待它完成的命令。

解决方案是围绕重新加载过程编写一个包装器。

#!/bin/bash

SERVER="/path/to/myapp.pl"
HYPNOTOAD="/usr/bin/hypnotoad"
PIDFILE="/var/run/myapp.pid"

# Timeout == LOOPSAFE x SLEEPTIME
SLEEPTIME="0.5"
LOOPSAFE=20
LOOPCOUNT=0
#

if [ ! -f "${PIDFILE}" ]; then
  # The PID files does not exist, maybe $SERVER is not running
  exit 1
fi

OLDPID=$(cat ${PIDFILE})
NEWPID=$OLDPID

# Reload the application
${HYPNOTOAD} ${SERVER}

while (( $LOOPCOUNT <= $LOOPSAFE )); do
  let LOOPCOUNT++
  if [ -f ${PIDFILE} ]; then
    NEWPID=$(cat ${PIDFILE})
    if (( $NEWPID > 1 )) && (( $NEWPID != $OLDPID )); then
      exit 0
    fi
  fi
  sleep ${SLEEPTIME}
done

exit 1

这是 Hypnotoad 所需的 systemd 单元文件

[Unit]
Description=Hypnotoad-app
Requires=network.target
After=network.target

[Service]
Type=simple
SyslogIdentifier=hypnotoad-app
PIDFile=/var/run/myapp.pid
EnvironmentFile=-/etc/sysconfig/myapp
ExecStart=/usr/bin/hypnotoad --foreground /path/to/myapp.pl
ExecStop=/usr/bin/hypnotoad --stop /path/to/myapp.pl
ExecReload=/path/to/reload-myapp.sh
KillMode=process
Restart=always
RestartSec=5
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target

这是重新加载过程现在的工作方式

  • systemd 重新加载 hypnotoad-app
  • systemd 执行重载脚本
  • reload 脚本会重新加载 hypnotoad-app,并等待“成功升级”——本质上是休眠,直到 PID 文件具有新重新加载的 myapp.pl 进程的 PID
  • systemd 现在使用新的 PID 监视 pid 文件,该 PID 不再更改 - 所以现在 systemd 不会尝试重新启动它
于 2017-09-06T17:06:48.703 回答
0

另一种选择是hypnotoad在前台运行-f& 使用服务监督runit& 一个简单的/etc/sv/myapp/run脚本:

#!/bin/sh

app=/path/to/my/app
daemon=/path/to/hypnotoad

exec 2>&1
exec $daemon -f $app

然后你可以hypnotoad重新阅读它的配置sv hup myapp

Red Hat 不runit提供,但rpm可以从这里构建最新版本。

不要忘记使用ln -s /etc/sv/myapp /etc/service/myapp启用服务runit

于 2018-01-24T17:07:16.853 回答