linux - 如何在 Debian 中将简单的 Go 服务器作为守护进程运行?

标签 linux go server raspberry-pi debian

我最近用 Go 编写了一个简单的服务器:

package main
import (
    "net/http"
    "fmt"
    "os/exec"
)

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":****", nil)
    }

func handler(output http.ResponseWriter, input *http.Request) {

    instruction := "Instructed to " + input.URL.Path[1:] + "."

    fmt.Printf(instruction)

    if input.URL.Path[1:] == "********" {

            *************
            *************
            *************                

            if err != nil {
                    fmt.Println("There was a problem executing the script.")
                    }
            } else {

            fmt.Println(" I'm unfamiliar with this instruction.")
            }

    }

如果编译然后由 ./go_http_server & 执行,它工作得很好。

问题是它无法在重启后继续存在。所以在阅读之后,我试图通过在/etc/init.d 中放置一个脚本来守护它:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          myservice
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Put a short description of the service here
# Description:       Put a long description of the service here
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/****/****
DAEMON=$DIR/go_http_server
DAEMON_NAME=*********

# Add any command line options for your daemon here
DAEMON_OPTS=""

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=*****

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
    log_daemon_msg "Starting system $DAEMON_NAME daemon"
    start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
    log_end_msg $?
}
do_stop () {
    log_daemon_msg "Stopping system $DAEMON_NAME daemon"
    start-stop-daemon --stop --pidfile $PIDFILE --retry 10
    log_end_msg $?
}

case "$1" in

    start|stop)
        do_${1}
        ;;

    restart|reload|force-reload)
        do_stop
        do_start
        ;;

    status)
        status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?

...然后运行 ​​update-rc.d go_http_server defaults,噗!它在启动时运行,由 ps -ef | 验证grep go_http_server.

但它在作为服务运行时不接收 GET 请求。我认为它可能在网络接口(interface)启动之前就已运行,因此尝试了 service go_http_server stop,然后是 service go_http_server start;仍然拒绝接收 GET 请求。再次停止服务,然后执行./go_http_server & 使服务器再次正常运行。

这几天我一直在谷歌上断断续续地搜索这个。要么我的搜索查询很糟糕,要么这不是一个明显的问题。如何守护我的 Go 服务器?


编辑:完全相同的事情发生在我用 Python 编写的服务器上:它在使用 ./python_server.py 执行时正常工作,但是——如果作为服务启动——HTTP 请求被忽略。这两个文件都已成为可执行文件,守护进程用户是根用户还是任何其他用户都无关紧要。不确定这是否有帮助,但我认为它可能是相关的。

最佳答案

Supervisor 非常适合这里,它可以自动捕获和轮换写入标准输出的日志,在崩溃时重新启动并管理端口/权限。

以下是 Go 网络服务的示例配置:

# where 'mygoapp' is the name of your application
$ sudo vim /etc/supervisor/conf.d/mygoapp.conf 

[program:yourapp]
command=/home/yourappuser/bin/yourapp # the location of your app
autostart=true
autorestart=true
startretries=10
user=yourappuser # the user your app should run as (i.e. *not* root!)
directory=/srv/www/yourapp.com/ # where your application runs from
environment=APP_SETTINGS="/srv/www/yourapp.com/prod.toml" # environmental variables
redirect_stderr=true
stdout_logfile=/var/log/supervisor/yourapp.log # the name of the log file.
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10

我写了一篇文章[ 1 ] 带您完成这些步骤,但是 Supervisor documentation非常全面。

同样,Debian系统也使用systemd[ 2 ], 也可以实现这一点。

关于linux - 如何在 Debian 中将简单的 Go 服务器作为守护进程运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35583853/

相关文章:

server - 如何在ansible中的 "Do you want to continue"提示符上提供自定义输入?

windows - MQTT 代理窗口

c# - 高性能 WebSocket 游戏服务器的单点登录?

c - 使用 readdir 获取文件大小

c - 无论如何要避免在 libcurl 中循环监视多句柄?

google-app-engine - aetest 和 google.golang.org/appengine

http - 在超时处理程序中进入竞争条件

linux - 确定拥有磁盘的 linux 驱动程序

regex - 重命名树中基本名称中包含扩展名的文件

去测试 : only run tests that contain a build tag?