我有一个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不知道这个过程是否会消失。我理解正确吗?还有其他人试过这种方法吗?
答案 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标志。
我建议改用Supervisor或Circus之类的内容。
编辑:
这并非严格属实,如果你的Go程序守护自己,可以排除--background
标志。