golang webapp init.d脚本挂起

golang webapp init.d脚本挂起,go,upstart,init.d,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=/va

我有一个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
问题是,当我运行go app start服务时,它只是挂起,如下所示:

ubuntu@ip-10-0-0-40:~$ service my-go-app start
Starting my-go-app:
start-stop-daemon -b -m --start --quiet --umask 007 --pidfile $PIDFILE --chuid ubuntu:ubuntu --exec $DAEMON -- $DAEMON_ARGS
永远不会回来。在此状态下,如果我打开一个单独的终端,我可以通过检查日志文件看到应用程序正在运行,但是/var/run/my-go-app/my-go-app.pid中没有任何内容,尽管创建了pid文件

以前有没有人遇到过这样的问题,希望能解决?如何作为init.d守护进程运行go应用程序

编辑: 通过在启动服务时添加-b-m命令行标志来启动停止守护进程,我可以实现这一点。这条线现在看起来像这样:

ubuntu@ip-10-0-0-40:~$ service my-go-app start
Starting my-go-app:
start-stop-daemon -b -m --start --quiet --umask 007 --pidfile $PIDFILE --chuid ubuntu:ubuntu --exec $DAEMON -- $DAEMON_ARGS
我对这种方法的担忧是启动-停止守护程序手册页中的警告:


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

如果您使用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)
}
以及上述upstart作业的以下行:

env MYAPP_RAISESTOP="yes"
expect stop
如果if{}不是真正的Go语法,我很抱歉;我是一个C程序员哈哈,虽然和{}里面的东西是真实的,但我做了一些研究:


执行最后这一点可以确保Upstart在启动启动事件之前将等待应用程序正确设置。如果没有其他作业在等待你的应用程序,那么你并不真正需要它。

如果你想使用SysVinit并用Go程序启动stop daemon,则需要-background标志

我建议使用类似或的方式

编辑:


严格来说,这不是真的,如果你的Go程序将其自身后台化,那么可以排除-background标志。

我不认为这是goapp的错。upstart脚本中有错误。您的脚本看起来更像标准的SysV样式的init脚本,而不是upstart。对于一个实际的upstart脚本,请看:感谢您指出这一点,我更新了标题为init.d script,而不是upstart script是的,使用-b通常不是一个好主意。除非您编写一个将自身后台监控的程序,否则您无法真正做到这一点,您应该让upstart这样的服务运行您的程序。使用upstart、systemd、supervisord等。我在我的原始帖子中错误地提到了使用upstart我使用的是systemv-我应该使用upstart有什么特别的原因吗?upstart可以在应用程序崩溃时自动重启应用程序,编写upstart作业更容易正确。虽然如果你已经有了可以工作的东西,那么你应该会没事的。谢谢jmaloney-你能帮我理解为什么我需要Go程序的-background标志吗?@mike如果你想排除-background标志,你的Go程序必须将自己后台化。有一些技术可以做,但据我所知,这是不推荐的。