Systemd 状态“stop-sigterm”超时

Systemd 状态“stop-sigterm”超时

我有一个简单的 Java 服务器 + 几个我想使用 systemd 运行并保持活动的脚本(Ubuntu 16.04)我是 systemd 新手,该服务不断重新启动并显示此日志

Nov 16 10:20:12 systemd[1]: app.service: Unit entered failed state.
Nov 16 10:20:12 systemd[1]: app.service: Failed with result 'resources'.
Nov 16 10:29:25 systemd[1]: app.service: State 'stop-sigterm' timed out. Killing.
Nov 16 10:29:25  systemd[1]: app.service: Unit entered failed state.
Nov 16 10:29:25  systemd[1]: app.service: Failed with result 'timeout'.
Nov 16 10:31:06 systemd[1]: app.service: Service hold-off time over, scheduling restart.

我有 2 个简单的 bash 脚本来运行/控制服务器;

这是我的服务定义 app.service

   [Unit]
    Description=java server
    [Service]
    ExecStart=-/home/deploy/server/serverctl.sh start
    ExecStop=-/home/deploy/server/serverctl.sh stop
    ExecReload=-/home/deploy/server/serverctl.sh restart
    SyslogIdentifier=my-app
    User=deploy
    Restart=always
    RestartSec=100
    Type=simple
    [Install]
    WantedBy=multi-user.target

我的start.sh

#!/bin/bash
cd "$(dirname "$0")"
java -mx500m -cp lib/* mylcass  -port 8080 -arg val > server.log 2>&1 & echo $!

它运行服务器并返回 PID

我有一个控制脚本来启动/停止/状态重启服务器,它工作正常

#!/bin/bash

PID_FILE='/tmp/myserver.pid'

# ***********************************************
start() {
  PID=`/path/to/server-start.sh`
}

case "$1" in
start)
    if [ -f $PID_FILE ]; then
        PID=`cat $PID_FILE`
        if [ -z "`ps axf | grep -w ${PID} | grep -v grep`" ]; then
            start
        else
            exit 0
        fi
    else
        start
    fi

    if [ -z $PID ]; then
        exit 3
    else
        echo $PID > $PID_FILE
        exit 0
    fi
;;

status)
    echo "status"   
    if [ -f $PID_FILE ]; then
        PID=`cat $PID_FILE`
        if [ -z "`ps axf | grep -w ${PID} | grep -v grep`" ]; then
            echo "Not running (process dead but pidfile exists)"
            exit 1
        else
            echo "Running [$PID]"
            exit 0
        fi
    else
        echo "Not running"
        exit 3
    fi
;;

stop)
    if [ -f $PID_FILE ]; then
        PID=`cat $PID_FILE`
        if [ -z "`ps axf | grep -w ${PID} | grep -v grep`" ]; then
            exit 1
        else
            PID=`cat $PID_FILE`
            kill -HUP $PID
            rm -f $PID_FILE
            exit 0
        fi
    else
        exit 3
    fi
;;

restart)
    $0 stop
    $0 start
;;

*)
    echo "Usage: $0 {status|start|stop|restart}"
    exit 1
esac

有什么想法吗?如何让 systemd 确保服务器正常运行?

答案1

首先,请停止使用您的“服务器控制脚本”。这是 systemd 的工作。init 系统已经跟踪服务 PID 并提供启动/停止命令。

另外,除非您确实知道有必要,否则不要-在 ExecStart 中使用该标志。它告诉 systemd 忽略启动失败,您肯定想知道服务何时失败。

最后,尽量避免myapp &在启动脚本中使用。(Init 不需要它——根据定义,服务已经在后台运行。)如果您必须使用它,那么Type=forking会更正确。

(设置正确的 Type= 会告诉 systemd 期望什么,即何时将服务器视为“正在启动”、 “已启动” 或 “已完成”。Type=simple 表示初始进程绝不'backgrounds' 本身;Type=forking 则相反。)

这样,下面的方法应该可以更好地发挥作用:

app.service

[Unit]
Description=java server

[Service]
Type=simple
User=deploy
ExecStart=/home/deploy/server/start.sh
SyslogIdentifier=my-app
Restart=always
RestartSec=100

[Install]
WantedBy=multi-user.target

start.sh

#!/bin/sh
cd "$(dirname "$0")"
exec java -mx500m -cp lib/* mylcass -port 8080 -arg val

答案2

如果您的start.sh确实这么简单,您也可以根本不使用它。

恕我直言,这实际上是首选方式:

[Unit]
Description=My Java App

[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy/server
ExecStart=/usr/bin/java -mx500m -cp lib/* mylcass -port 8080 -arg val
SyslogIdentifier=my-app
Restart=always
RestartSec=100

[Install]
WantedBy=multi-user.target

无需复制 Systemd 免费提供给您的功能。

注意,这不会复制脚本> server.log的功能。相反,输出由更好的方式start.sh处理,恕我直言。journald

如果您需要用户配置,请直接在程序中读取配置文件,或使用 systemd 的环境变量。请参阅Environment=EnvironmentFile=服务选项。

您甚至可以将这些环境变量转换为传递给命令的参数${FOO}

使用覆盖文件来app.service.d/*保持 ENV 变量(或其他配置)分开。

相关内容