doupingyun73833
2016-02-23 17:11
浏览 98

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

I recently wrote a simple server in 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.")
            }

    }

It works perfectly well if compiled and then executed by ./go_http_server &.

The problem is that it doesn't survive reboots. So after some reading, I attempted to daemonize it by placing a script in /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 $?

...then running update-rc.d go_http_server defaults, and poof! It runs on boot, as verified by ps -ef | grep go_http_server.

But it doesn't receive GET requests while running as a service. Thinking it might be running before the network interface was up, I tried service go_http_server stop, followed by service go_http_server start; still refused to receive GET requests. Stopping the service again and then executing ./go_http_server & makes the server function correctly once more.

I've been Googling this on and off for a couple days now. Either my search queries suck, or this isn't an obvious problem. How do I daemonize my Go server?


EDIT: The exact same thing happens with a server I wrote in Python: it works as it should when executed using ./python_server.py, but--if started as service--HTTP requests are ignored. Both files have been made executable, and it doesn't matter if the daemon user is root or any other user. Not sure if this helps, but I thought it might be relevant.

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • douboshan1466 2016-02-25 04:50
    已采纳

    Supervisor is a good fit here, and can automatically capture and rotate logs written to stdout, restart on crash and manage ports/permissions.

    Here's what an example configuration would look like for a Go web service:

    # 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
    

    I wrote an article[1] that takes you through the steps, but the Supervisor documentation is extremely comprehensive.

    Similarly, Debian systems also use systemd[2], which can achieve this as well.

    打赏 评论

相关推荐 更多相似问题