douhuan6065 2014-08-25 21:08
浏览 6

golang webapp init.d脚本挂起

I have a go web app compiled to a single binary that I am trying to manage via init.d. Here is my init.d script:

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

The problem is that when I run service my-go-app start, it just hangs, like this:

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

and never returns. In this state, if I open a separate terminal, I can see that the app is running by checking the log file but there is nothing in /var/run/my-go-app/my-go-app.pid (though the pid file does get created).

Has anyone encountered (and hopefully resolved) this before? How can I run my go app as an init.d daemon?

EDIT: I was able to get this to work by adding the "-b -m" command line flags to start-stop-daemonwhen starting the service. That line now looks like this:

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

My concern with this approach is the warning in the start-stop-daemon manpage:

-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.

This seems like a bad idea to me, because it sounds like SysV won't know if the process dies. Am I understanding this correctly? Has anyone else tried this approach?

  • 写回答

2条回答 默认 最新

  • doumen6605 2014-08-26 18:57
    关注

    If you are running a system with Upstart you can use this script:

    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
    

    You can also add the following code to your daemon at a point where your application has been started and initialized correctly:

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

    and the following to lines to the above upstart job:

    env MYAPP_RAISESTOP="yes"
    expect stop
    

    I am sorry if the if () { } is not real Go syntax; I am a C programmer haha (although the stuff inside the () and {} is real, I did a little research :).

    Doing this last bit ensures that Upstart will wait until your application is set up correctly before firing off the started event. If no other jobs are waiting for your app, then you do not really need that.

    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。