Add option parsing to nsenter and enable specifying commands with arguments.
Docker-DCO-1.1-Signed-off-by: Mrunal Patel <mrunalp@gmail.com> (github: mrunalp)
This commit is contained in:
parent
4145356abe
commit
88acda82d9
|
@ -21,14 +21,8 @@ func ExecIn(container *libcontainer.Container, nspid int, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(vmarmol): Move this to the container JSON.
|
|
||||||
processLabel, err := label.GetPidCon(nspid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enter the namespace and then finish setup
|
// Enter the namespace and then finish setup
|
||||||
finalArgs := []string{os.Args[0], "nsenter", strconv.Itoa(nspid), processLabel, string(containerJson)}
|
finalArgs := []string{os.Args[0], "nsenter", "--nspid", strconv.Itoa(nspid), "--containerjson", string(containerJson), "--"}
|
||||||
finalArgs = append(finalArgs, args...)
|
finalArgs = append(finalArgs, args...)
|
||||||
if err := system.Execv(finalArgs[0], finalArgs[0:], os.Environ()); err != nil {
|
if err := system.Execv(finalArgs[0], finalArgs[0:], os.Environ()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -37,7 +31,7 @@ func ExecIn(container *libcontainer.Container, nspid int, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NsEnter is run after entering the namespace.
|
// NsEnter is run after entering the namespace.
|
||||||
func NsEnter(container *libcontainer.Container, processLabel string, nspid int, args []string) error {
|
func NsEnter(container *libcontainer.Container, nspid int, args []string) error {
|
||||||
// clear the current processes env and replace it with the environment
|
// clear the current processes env and replace it with the environment
|
||||||
// defined on the container
|
// defined on the container
|
||||||
if err := LoadContainerEnvironment(container); err != nil {
|
if err := LoadContainerEnvironment(container); err != nil {
|
||||||
|
@ -46,9 +40,13 @@ func NsEnter(container *libcontainer.Container, processLabel string, nspid int,
|
||||||
if err := FinalizeNamespace(container); err != nil {
|
if err := FinalizeNamespace(container); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := label.SetProcessLabel(processLabel); err != nil {
|
|
||||||
return err
|
if process_label, ok := container.Context["process_label"]; ok {
|
||||||
|
if err := label.SetProcessLabel(process_label); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := system.Execv(args[0], args[0:], container.Env); err != nil {
|
if err := system.Execv(args[0], args[0:], container.Env); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ package namespaces
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
static const kBufSize = 256;
|
static const kBufSize = 256;
|
||||||
|
|
||||||
|
@ -64,6 +65,10 @@ int setns(int fd, int nstype) {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void print_usage() {
|
||||||
|
fprintf(stderr, "<binary> nsenter --nspid <pid> --containerjson <container_json> -- cmd1 arg1 arg2...\n");
|
||||||
|
}
|
||||||
|
|
||||||
void nsenter() {
|
void nsenter() {
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
@ -79,11 +84,40 @@ void nsenter() {
|
||||||
fprintf(stderr, "nsenter: Incorrect usage, not enough arguments\n");
|
fprintf(stderr, "nsenter: Incorrect usage, not enough arguments\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
pid_t init_pid = strtol(argv[2], NULL, 10);
|
|
||||||
if (errno != 0 || init_pid <= 0) {
|
static const struct option longopts[] = {
|
||||||
fprintf(stderr, "nsenter: Failed to parse PID from \"%s\" with error: \"%s\"\n", argv[2], strerror(errno));
|
{ "nspid", required_argument, NULL, 'n' },
|
||||||
|
{ "containerjson", required_argument, NULL, 'c' },
|
||||||
|
{ NULL, 0, NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int c;
|
||||||
|
pid_t init_pid = -1;
|
||||||
|
char *init_pid_str = NULL;
|
||||||
|
char *container_json = NULL;
|
||||||
|
while ((c = getopt_long_only(argc, argv, "n:s:c:", longopts, NULL)) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'n':
|
||||||
|
init_pid_str = optarg;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
container_json = optarg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container_json == NULL || init_pid_str == NULL) {
|
||||||
|
print_usage();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_pid = strtol(init_pid_str, NULL, 10);
|
||||||
|
if (errno != 0 || init_pid <= 0) {
|
||||||
|
fprintf(stderr, "nsenter: Failed to parse PID from \"%s\" with error: \"%s\"\n", init_pid_str, strerror(errno));
|
||||||
|
print_usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
argc -= 3;
|
argc -= 3;
|
||||||
argv += 3;
|
argv += 3;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/docker/libcontainer/namespaces"
|
"github.com/docker/libcontainer/namespaces"
|
||||||
|
@ -12,29 +11,30 @@ var nsenterCommand = cli.Command{
|
||||||
Name: "nsenter",
|
Name: "nsenter",
|
||||||
Usage: "init process for entering an existing namespace",
|
Usage: "init process for entering an existing namespace",
|
||||||
Action: nsenterAction,
|
Action: nsenterAction,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.IntFlag{Name: "nspid"},
|
||||||
|
cli.StringFlag{Name: "containerjson"},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func nsenterAction(context *cli.Context) {
|
func nsenterAction(context *cli.Context) {
|
||||||
args := context.Args()
|
args := context.Args()
|
||||||
if len(args) < 4 {
|
|
||||||
log.Fatalf("incorrect usage: <pid> <process label> <container JSON> <cmd>...")
|
if len(args) == 0 {
|
||||||
|
args = []string{"/bin/bash"}
|
||||||
}
|
}
|
||||||
|
|
||||||
container, err := loadContainerFromJson(args.Get(2))
|
container, err := loadContainerFromJson(context.String("containerjson"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to load container: %s", err)
|
log.Fatalf("unable to load container: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nspid, err := strconv.Atoi(args.Get(0))
|
nspid := context.Int("nspid")
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("unable to read pid: %s from %q", err, args.Get(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
if nspid <= 0 {
|
if nspid <= 0 {
|
||||||
log.Fatalf("cannot enter into namespaces without valid pid: %q", nspid)
|
log.Fatalf("cannot enter into namespaces without valid pid: %q", nspid)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := namespaces.NsEnter(container, args.Get(1), nspid, args[3:]); err != nil {
|
if err := namespaces.NsEnter(container, nspid, args); err != nil {
|
||||||
log.Fatalf("failed to nsenter: %s", err)
|
log.Fatalf("failed to nsenter: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue