golang webapp init.d脚本挂起

时间:2014-08-25 21:08:33

标签: go upstart init.d

我有一个go web应用程序编译为单个二进制文件,我试图通过init.d管理。这是我的init.d脚本:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/bin/my-go-app
DAEMON_ARGS="--logFile /var/log/my-go-app/my-go-app.log"
NAME=my-go-app
DESC=my-go-app

RUNDIR=/var/run/my-go-app
PIDFILE=$RUNDIR/my-go-app.pid

test -x $DAEMON || exit 0

if [ -r /etc/default/$NAME ]
then
        . /etc/default/$NAME
fi

. /lib/lsb/init-functions

set -e

case "$1" in
  start)
        echo -n "Starting $DESC: "
        mkdir -p $RUNDIR
        touch $PIDFILE
        chown ubuntu:ubuntu $RUNDIR $PIDFILE
        chmod 755 $RUNDIR

        if [ -n "$ULIMIT" ]
        then
                ulimit -n $ULIMIT
        fi

        if start-stop-daemon --start --quiet --umask 007 --pidfile $PIDFILE --chuid ubuntu:ubuntu --exec $DAEMON -- $DAEMON_ARGS
        then
                echo "$NAME."
        else
                echo "failed"
        fi
                ;;
  stop)
        echo -n "Stopping $DESC: "
        if start-stop-daemon --stop --retry forever/TERM/1 --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON
        then
                echo "$NAME."
        else
                echo "failed"
        fi
        rm -f $PIDFILE
        sleep 1
        ;;

  restart|force-reload)
        ${0} stop
        ${0} start
        ;;

  status)
        echo -n "$DESC is "
        if start-stop-daemon --stop --quiet --signal 0 --name ${NAME} --pidfile ${PIDFILE}
        then
                echo "running"
        else
                echo "not running"
                exit 1
        fi
        ;;

  *)
        echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2
        exit 1
        ;;
esac

exit 0

问题在于,当我运行service my-go-app start时,它会挂起,就像这样:

ubuntu@ip-10-0-0-40:~$ service my-go-app start
Starting my-go-app:

永远不会回来。在这种状态下,如果我打开一个单独的终端,我可以通过检查日志文件看到该应用程序正在运行但是/var/run/my-go-app/my-go-app.pid中没有任何内容(尽管pid文件确实已经创建了。)

有没有人遇到过(并希望解决)这个?如何将我的go app作为init.d守护进程运行?

编辑: 我能够通过添加" -b -m"来实现这一点。启动服务时命令行标志为start-stop-daemon。该行现在看起来像这样:

start-stop-daemon -b -m --start --quiet --umask 007 --pidfile $PIDFILE --chuid ubuntu:ubuntu --exec $DAEMON -- $DAEMON_ARGS

我对此方法的关注是start-stop-daemon联机帮助页中的警告:

-b, --background
              Typically used with programs that don't detach on their own. This option will force start-stop-daemon to fork before starting the process,  and
              force  it into the background.  WARNING: start-stop-daemon cannot check the exit status if the process fails to execute for any reason. This is
              a last resort, and is only meant for programs that either make no sense forking on their own, or where it's not feasible to add  the  code  for
              them to do this themselves.

这对我来说似乎是一个坏主意,因为听起来SysV不知道这个过程是否会消失。我理解正确吗?还有其他人试过这种方法吗?

2 个答案:

答案 0 :(得分:0)

如果您使用Upstart运行系统,则可以使用此脚本:

start on runlevel [2345]
stop on runlevel [016] or unmounting-filesystem

# Replace {soft} and {hard} with the soft and hard resource limits you desire
#limit nofile {soft} {hard}

umask 007

setuid ubuntu
setgid ubuntu

exec /usr/bin/my-go-app --logFile /var/log/my-go-app/my-go-app.log

您还可以在应用程序启动并正确初始化的位置将以下代码添加到您的守护程序中:

if ("yes" == os.Getenv("MYAPP_RAISESTOP")) {
    p, err := os.FindProcess(os.Getpid())
    p.Signal(syscall.SIGSTOP)
}

以及以下上述新贵工作的路线:

env MYAPP_RAISESTOP="yes"
expect stop

如果if () { }不是真正的Go语法,我很抱歉;我是C程序员哈哈(尽管()和{} 中的东西是真实的,我做了一些研究:)。

执行此操作可确保Upstart在启动started事件之前等待应用程序设置正确。如果没有其他工作正在等待你的应用程序,那么你真的不需要它。

答案 1 :(得分:0)

如果你想在Go程序中使用SysVinit和start-stop-daemon,你将需要--background标志。

我建议改用SupervisorCircus之类的内容。

编辑:

这并非严格属实,如果你的Go程序守护自己,可以排除--background标志。

相关问题