зеркало из https://github.com/microsoft/docker.git
Setup daemon pidfile/cleanup in Server.Daemon() instead of main()
This commit is contained in:
Родитель
c542b2f873
Коммит
c1ae1a0e1c
|
@ -7,13 +7,9 @@ import (
|
|||
"github.com/dotcloud/docker/sysinit"
|
||||
"github.com/dotcloud/docker/utils"
|
||||
"github.com/dotcloud/docker/engine"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -89,7 +85,7 @@ func main() {
|
|||
job.SetenvList("ProtoAddresses", flHosts)
|
||||
job.Setenv("DefaultIp", *flDefaultIp)
|
||||
job.SetenvBool("InterContainerCommunication", *flInterContainerComm)
|
||||
if err := daemon(job, *pidfile); err != nil {
|
||||
if err := job.Run(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
|
@ -109,50 +105,3 @@ func main() {
|
|||
func showVersion() {
|
||||
fmt.Printf("Docker version %s, build %s\n", VERSION, GITCOMMIT)
|
||||
}
|
||||
|
||||
func createPidFile(pidfile string) error {
|
||||
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
|
||||
pid, err := strconv.Atoi(string(pidString))
|
||||
if err == nil {
|
||||
if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
|
||||
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.Create(pidfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
_, err = fmt.Fprintf(file, "%d", os.Getpid())
|
||||
return err
|
||||
}
|
||||
|
||||
func removePidFile(pidfile string) {
|
||||
if err := os.Remove(pidfile); err != nil {
|
||||
log.Printf("Error removing %s: %s", pidfile, err)
|
||||
}
|
||||
}
|
||||
|
||||
// daemon runs `job` as a daemon.
|
||||
// A pidfile is created for the duration of the job,
|
||||
// and all signals are intercepted.
|
||||
func daemon(job *engine.Job, pidfile string) error {
|
||||
if err := createPidFile(pidfile); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer removePidFile(pidfile)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
|
||||
go func() {
|
||||
sig := <-c
|
||||
log.Printf("Received signal '%v', exiting\n", sig)
|
||||
removePidFile(pidfile)
|
||||
os.Exit(0)
|
||||
}()
|
||||
return job.Run()
|
||||
}
|
||||
|
|
35
server.go
35
server.go
|
@ -24,6 +24,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
"syscall"
|
||||
"os/signal"
|
||||
)
|
||||
|
||||
func (srv *Server) Close() error {
|
||||
|
@ -40,8 +41,31 @@ func JobServeApi(job *engine.Job) string {
|
|||
return err.Error()
|
||||
}
|
||||
defer srv.Close()
|
||||
// Parse addresses to serve on
|
||||
protoAddrs := job.Args
|
||||
if err := srv.Daemon(); err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return "0"
|
||||
}
|
||||
|
||||
// Daemon runs the remote api server `srv` as a daemon,
|
||||
// Only one api server can run at the same time - this is enforced by a pidfile.
|
||||
// The signals SIGINT, SIGKILL and SIGTERM are intercepted for cleanup.
|
||||
func (srv *Server) Daemon() error {
|
||||
if err := utils.CreatePidFile(srv.runtime.config.Pidfile); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer utils.RemovePidFile(srv.runtime.config.Pidfile)
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
|
||||
go func() {
|
||||
sig := <-c
|
||||
log.Printf("Received signal '%v', exiting\n", sig)
|
||||
utils.RemovePidFile(srv.runtime.config.Pidfile)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
protoAddrs := srv.runtime.config.ProtoAddresses
|
||||
chErrors := make(chan error, len(protoAddrs))
|
||||
for _, protoAddr := range protoAddrs {
|
||||
protoAddrParts := strings.SplitN(protoAddr, "://", 2)
|
||||
|
@ -52,7 +76,7 @@ func JobServeApi(job *engine.Job) string {
|
|||
log.Println("/!\\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\\")
|
||||
}
|
||||
} else {
|
||||
return "Invalid protocol format."
|
||||
return fmt.Errorf("Invalid protocol format.")
|
||||
}
|
||||
go func() {
|
||||
chErrors <- ListenAndServe(protoAddrParts[0], protoAddrParts[1], srv, true)
|
||||
|
@ -61,12 +85,13 @@ func JobServeApi(job *engine.Job) string {
|
|||
for i := 0; i < len(protoAddrs); i += 1 {
|
||||
err := <-chErrors
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
return err
|
||||
}
|
||||
}
|
||||
return "0"
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (srv *Server) DockerVersion() APIVersion {
|
||||
return APIVersion{
|
||||
Version: VERSION,
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func CreatePidFile(pidfile string) error {
|
||||
if pidString, err := ioutil.ReadFile(pidfile); err == nil {
|
||||
pid, err := strconv.Atoi(string(pidString))
|
||||
if err == nil {
|
||||
if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
|
||||
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.Create(pidfile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
_, err = fmt.Fprintf(file, "%d", os.Getpid())
|
||||
return err
|
||||
}
|
||||
|
||||
func RemovePidFile(pidfile string) {
|
||||
if err := os.Remove(pidfile); err != nil {
|
||||
log.Printf("Error removing %s: %s", pidfile, err)
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче