diff --git a/commands.go b/commands.go index 5ad35636c2..ff4b12e942 100644 --- a/commands.go +++ b/commands.go @@ -469,6 +469,13 @@ func (cli *DockerCli) CmdInfo(args ...string) error { fmt.Fprintf(cli.out, "LXC Version: %s\n", remoteInfo.Get("LXCVersion")) fmt.Fprintf(cli.out, "EventsListeners: %d\n", remoteInfo.GetInt("NEventsListener")) fmt.Fprintf(cli.out, "Kernel Version: %s\n", remoteInfo.Get("KernelVersion")) + + if initSha1 := remoteInfo.Get("InitSha1"); initSha1 != "" { + fmt.Fprintf(cli.out, "Init SHA1: %s\n", initSha1) + } + if initPath := remoteInfo.Get("InitPath"); initPath != "" { + fmt.Fprintf(cli.out, "Init Path: %s\n", initPath) + } } if len(remoteInfo.GetList("IndexServerAddress")) != 0 { diff --git a/hack/make/dynbinary b/hack/make/dynbinary index 7e8786a9be..c02094c0c5 100644 --- a/hack/make/dynbinary +++ b/hack/make/dynbinary @@ -12,6 +12,6 @@ export DOCKER_INITSHA1="$(sha1sum $DEST/dockerinit-$VERSION | cut -d' ' -f1)" # exported so that "dyntest" can easily access it later without recalculating it ( - export LDFLAGS_STATIC="-X github.com/dotcloud/docker/utils.INITSHA1 \"$DOCKER_INITSHA1\"" + export LDFLAGS_STATIC="-X github.com/dotcloud/docker/utils.INITSHA1 \"$DOCKER_INITSHA1\" -X github.com/dotcloud/docker/utils.INITPATH \"$DOCKER_INITPATH\"" source "$(dirname "$BASH_SOURCE")/binary" ) diff --git a/runtime.go b/runtime.go index 588e713ca5..2ecaf12086 100644 --- a/runtime.go +++ b/runtime.go @@ -725,18 +725,18 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See http://docs.docker.io/en/latest/contributing/devenvironment for official build instructions.") } - if !utils.IAMSTATIC { - if err := os.Mkdir(path.Join(config.Root, fmt.Sprintf("init")), 0700); err != nil && !os.IsExist(err) { + if sysInitPath != localCopy { + // When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade). + if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) { return nil, err } - if _, err := utils.CopyFile(sysInitPath, localCopy); err != nil { return nil, err } - sysInitPath = localCopy - if err := os.Chmod(sysInitPath, 0700); err != nil { + if err := os.Chmod(localCopy, 0700); err != nil { return nil, err } + sysInitPath = localCopy } runtime := &Runtime{ diff --git a/server.go b/server.go index 51e0aac4db..6a3ff2cd2d 100644 --- a/server.go +++ b/server.go @@ -633,6 +633,13 @@ func (srv *Server) DockerInfo(job *engine.Job) engine.Status { kernelVersion = kv.String() } + // if we still have the original dockerinit binary from before we copied it locally, let's return the path to that, since that's more intuitive (the copied path is trivial to derive by hand given VERSION) + initPath := utils.DockerInitPath("") + if initPath == "" { + // if that fails, we'll just return the path from the runtime + initPath = srv.runtime.sysInitPath + } + v := &engine.Env{} v.SetInt("Containers", len(srv.runtime.List())) v.SetInt("Images", imgcount) @@ -648,6 +655,8 @@ func (srv *Server) DockerInfo(job *engine.Job) engine.Status { v.SetInt("NEventsListener", len(srv.events)) v.Set("KernelVersion", kernelVersion) v.Set("IndexServerAddress", auth.IndexServerAddress()) + v.Set("InitSha1", utils.INITSHA1) + v.Set("InitPath", initPath) if _, err := v.WriteTo(job.Stdout); err != nil { job.Error(err) return engine.StatusErr diff --git a/utils/utils.go b/utils/utils.go index cfb63358d9..ffe90ac734 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -26,6 +26,7 @@ import ( var ( IAMSTATIC bool // whether or not Docker itself was compiled statically via ./hack/make.sh binary INITSHA1 string // sha1sum of separate static dockerinit, if Docker itself was compiled dynamically via ./hack/make.sh dynbinary + INITPATH string // custom location to search for a valid dockerinit binary (available for packagers as a last resort escape hatch) ) // A common interface to access the Fatal method of @@ -162,14 +163,23 @@ func Trunc(s string, maxlen int) string { return s[:maxlen] } -// Figure out the absolute path of our own binary +// Figure out the absolute path of our own binary (if it's still around). func SelfPath() string { path, err := exec.LookPath(os.Args[0]) if err != nil { + if os.IsNotExist(err) { + return "" + } + if execErr, ok := err.(*exec.Error); ok && os.IsNotExist(execErr.Err) { + return "" + } panic(err) } path, err = filepath.Abs(path) if err != nil { + if os.IsNotExist(err) { + return "" + } panic(err) } return path @@ -190,7 +200,13 @@ func dockerInitSha1(target string) string { } func isValidDockerInitPath(target string, selfPath string) bool { // target and selfPath should be absolute (InitPath and SelfPath already do this) + if target == "" { + return false + } if IAMSTATIC { + if selfPath == "" { + return false + } if target == selfPath { return true } @@ -216,6 +232,7 @@ func DockerInitPath(localCopy string) string { } var possibleInits = []string{ localCopy, + INITPATH, filepath.Join(filepath.Dir(selfPath), "dockerinit"), // FHS 3.0 Draft: "/usr/libexec includes internal binaries that are not intended to be executed directly by users or shell scripts. Applications may use a single subdirectory under /usr/libexec." @@ -229,6 +246,9 @@ func DockerInitPath(localCopy string) string { "/usr/local/lib/docker/dockerinit", } for _, dockerInit := range possibleInits { + if dockerInit == "" { + continue + } path, err := exec.LookPath(dockerInit) if err == nil { path, err = filepath.Abs(path)