From 50f992a7b3750d62d7604d913946cd8a82fe6253 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Thu, 7 Aug 2014 16:20:41 -0700 Subject: [PATCH] Add pid file support --- README.md | 7 +++++++ main.go | 22 +++++++++++++++++++++- main_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 91a01d7..854685e 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,13 @@ The main magic of how this works is that the container processes are moved from The above will use the `name=systemd` and `cpu` cgroups of systemd but then use Docker's cgroups for all the others, like the freezer cgroup. +Pid File +-------- + +If for whatever reason you want to create a pid file for the container PID, you can. Just add `--pid-file` as below + +`ExecStart=/opt/bin/systemd-docker --pid-file=/var/run/%n.pid --env run --rm --name %n nginx` + systemd-notify support ---------------------- diff --git a/main.go b/main.go index c27b00e..a6dbfc1 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,7 @@ type Context struct { NotifySocket string Cmd *exec.Cmd Pid int + PidFile string Client *dockerClient.Client } @@ -72,10 +73,11 @@ func parseContext(args []string) (*Context, error) { AllCgroups: false, } - flags := flag.NewFlagSet("run", flag.ContinueOnError) + flags := flag.NewFlagSet("systemd-docker", flag.ContinueOnError) var flCgroups opts.ListOpts + flags.StringVar(&c.PidFile, []string{"p", "-pid-file"}, "", "pipe file") flags.BoolVar(&c.Logs, []string{"l", "-logs"}, true, "pipe logs") flags.BoolVar(&c.Notify, []string{"n", "-notify"}, false, "setup systemd notify for container") flags.BoolVar(&c.Env, []string{"e", "-env"}, false, "inherit environment variable") @@ -443,6 +445,19 @@ func notify(c *Context) error { return nil } +func pidFile(c *Context) error { + if len(c.PidFile) == 0 || c.Pid <= 0 { + return nil + } + + err := ioutil.WriteFile(c.PidFile, []byte(strconv.Itoa(c.Pid)), 0644) + if err != nil { + return err + } + + return nil +} + func pipeLogs(c *Context) error { if !c.Logs { return nil @@ -527,6 +542,11 @@ func mainWithArgs(args []string) (*Context, error) { return c, err } + err = pidFile(c) + if err != nil { + return c, err + } + go pipeLogs(c) err = keepAlive(c) diff --git a/main_test.go b/main_test.go index ae41aca..b40e31b 100644 --- a/main_test.go +++ b/main_test.go @@ -1,10 +1,12 @@ package main import ( + "io/ioutil" "log" "os" "os/exec" "path" + "strconv" "syscall" "testing" @@ -452,3 +454,40 @@ func TestNamedContainerAttach(t *testing.T) { deleteTestContainer(t) } + +func Exist(path string) bool { + _, err := os.Stat(path) + return os.IsExist(err) +} + +func TestPidFile(t *testing.T) { + client, err := getClient(&Context{}) + if err != nil { + t.Fatal(err) + } + + pidFileName := "./pid-file" + + os.Remove(pidFileName) + + c, err := mainWithArgs([]string{"--logs=false", "--pid-file", "./pid-file", "run", "--rm", "busybox", "echo", "hi"}) + if err != nil { + t.Fatal(err) + } + + _, err = client.InspectContainer(c.Id) + if err == nil { + t.Fatal("Container should not exist") + } + + bytes, err := ioutil.ReadFile(pidFileName) + if err != nil { + t.Fatal(err) + } + + if string(bytes) != strconv.Itoa(c.Pid) { + t.Fatal("Failed to write pid file") + } + + os.Remove(pidFileName) +}