[lxc-devel] [lxd/master] Better handle stdout/stderr during RunCommand
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Jul 11 18:12:59 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190711/98831440/attachment-0001.bin>
-------------- next part --------------
From 56bddfc7868af7ee2030dd0b7e2eeb665beb2fd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 11 Jul 2019 11:33:35 -0400
Subject: [PATCH 1/2] shared: Better handle stdout/stderr in RunCommand
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
shared/util.go | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/shared/util.go b/shared/util.go
index d833d4e7f4..da6bd619cd 100644
--- a/shared/util.go
+++ b/shared/util.go
@@ -765,25 +765,41 @@ func RemoveDuplicatesFromString(s string, sep string) string {
}
type RunError struct {
- msg string
- Err error
+ msg string
+ Err error
+ Stdout string
+ Stderr string
}
func (e RunError) Error() string {
return e.msg
}
-func RunCommand(name string, arg ...string) (string, error) {
- output, err := exec.Command(name, arg...).CombinedOutput()
+func RunCommandSplit(name string, arg ...string) (string, string, error) {
+ cmd := exec.Command(name, arg...)
+
+ var stdout bytes.Buffer
+ var stderr bytes.Buffer
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+
+ err := cmd.Run()
if err != nil {
err := RunError{
- msg: fmt.Sprintf("Failed to run: %s %s: %s", name, strings.Join(arg, " "), strings.TrimSpace(string(output))),
- Err: err,
+ msg: fmt.Sprintf("Failed to run: %s %s: %s", name, strings.Join(arg, " "), strings.TrimSpace(string(stderr.Bytes()))),
+ Stdout: string(stdout.Bytes()),
+ Stderr: string(stderr.Bytes()),
+ Err: err,
}
- return string(output), err
+ return string(stdout.Bytes()), string(stderr.Bytes()), err
}
- return string(output), nil
+ return string(stdout.Bytes()), string(stderr.Bytes()), nil
+}
+
+func RunCommand(name string, arg ...string) (string, error) {
+ stdout, _, err := RunCommandSplit(name, arg...)
+ return stdout, err
}
func RunCommandWithFds(stdin io.Reader, stdout io.Writer, name string, arg ...string) error {
From 9ecce230607eb7920ad5e3f13086e50c8b18d6d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 11 Jul 2019 12:27:44 -0400
Subject: [PATCH 2/2] lxd: Use RunCommandSplit when needed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/container_lxc.go | 64 +++++++++++++-------------------------------
lxd/seccomp.go | 4 +--
2 files changed, 20 insertions(+), 48 deletions(-)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 9f9f506189..934050cbef 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -2732,7 +2732,7 @@ func (c *containerLXC) detachInterfaceRename(netns string, ifName string, hostNa
lxdPID := os.Getpid()
// Run forknet detach
- out, err := shared.RunCommand(
+ _, err := shared.RunCommand(
c.state.OS.ExecPath,
"forknet",
"detach",
@@ -2744,7 +2744,7 @@ func (c *containerLXC) detachInterfaceRename(netns string, ifName string, hostNa
// Process forknet detach response
if err != nil {
- logger.Error("Error calling 'lxd forknet detach", log.Ctx{"container": c.name, "output": out, "netns": netns, "ifName": ifName, "hostName": hostName, "pid": lxdPID})
+ logger.Error("Error calling 'lxd forknet detach", log.Ctx{"container": c.name, "err": err, "netns": netns, "ifName": ifName, "hostName": hostName, "pid": lxdPID})
}
return nil
@@ -3173,20 +3173,12 @@ func (c *containerLXC) Start(stateful bool) error {
name := projectPrefix(c.Project(), c.name)
// Start the LXC container
- out, err := shared.RunCommand(
+ _, err = shared.RunCommand(
c.state.OS.ExecPath,
"forkstart",
name,
c.state.OS.LxcPath,
configPath)
-
- // Capture debug output
- if out != "" {
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
- logger.Debugf("forkstart: %s", line)
- }
- }
-
if err != nil && !c.IsRunning() {
// Attempt to extract the LXC errors
lxcLog := ""
@@ -6328,8 +6320,7 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error {
finalStateDir = fmt.Sprintf("%s/%s", args.stateDir, args.dumpDir)
}
- var out string
- out, migrateErr = shared.RunCommand(
+ _, migrateErr = shared.RunCommand(
c.state.OS.ExecPath,
"forkmigrate",
c.name,
@@ -6338,12 +6329,6 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error {
finalStateDir,
fmt.Sprintf("%v", preservesInodes))
- if out != "" {
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
- logger.Debugf("forkmigrate: %s", line)
- }
- }
-
if migrateErr == nil {
// Start proxy devices
err = c.restartProxyDevices()
@@ -6599,7 +6584,7 @@ func (c *containerLXC) FileExists(path string) error {
}
// Check if the file exists in the container
- out, err := shared.RunCommand(
+ _, stderr, err := shared.RunCommandSplit(
c.state.OS.ExecPath,
"forkfile",
"exists",
@@ -6617,12 +6602,12 @@ func (c *containerLXC) FileExists(path string) error {
}
// Process forkcheckfile response
- if out != "" {
- if strings.HasPrefix(out, "error:") {
- return fmt.Errorf(strings.TrimPrefix(strings.TrimSuffix(out, "\n"), "error: "))
+ if stderr != "" {
+ if strings.HasPrefix(stderr, "error:") {
+ return fmt.Errorf(strings.TrimPrefix(strings.TrimSuffix(stderr, "\n"), "error: "))
}
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(stderr, "\n"), "\n") {
logger.Debugf("forkcheckfile: %s", line)
}
}
@@ -6646,7 +6631,7 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
}
// Get the file from the container
- out, err := shared.RunCommand(
+ _, stderr, err := shared.RunCommandSplit(
c.state.OS.ExecPath,
"forkfile",
"pull",
@@ -6672,7 +6657,7 @@ func (c *containerLXC) FilePull(srcpath string, dstpath string) (int64, int64, o
var errStr string
// Process forkgetfile response
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(stderr, "\n"), "\n") {
if line == "" {
continue
}
@@ -6790,7 +6775,7 @@ func (c *containerLXC) FilePush(type_ string, srcpath string, dstpath string, ui
}
// Push the file to the container
- out, err := shared.RunCommand(
+ _, stderr, err := shared.RunCommandSplit(
c.state.OS.ExecPath,
"forkfile",
"push",
@@ -6817,7 +6802,7 @@ func (c *containerLXC) FilePush(type_ string, srcpath string, dstpath string, ui
}
// Process forkgetfile response
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(stderr, "\n"), "\n") {
if line == "" {
continue
}
@@ -6859,7 +6844,7 @@ func (c *containerLXC) FileRemove(path string) error {
}
// Remove the file from the container
- out, err := shared.RunCommand(
+ _, stderr, err := shared.RunCommandSplit(
c.state.OS.ExecPath,
"forkfile",
"remove",
@@ -6877,7 +6862,7 @@ func (c *containerLXC) FileRemove(path string) error {
}
// Process forkremovefile response
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
+ for _, line := range strings.Split(strings.TrimRight(stderr, "\n"), "\n") {
if line == "" {
continue
}
@@ -7169,7 +7154,7 @@ func (c *containerLXC) networkState() map[string]api.ContainerStateNetwork {
// Process forkgetnet response
if err != nil {
- logger.Error("Error calling 'lxd forkgetnet", log.Ctx{"container": c.name, "output": out, "pid": pid})
+ logger.Error("Error calling 'lxd forkgetnet", log.Ctx{"container": c.name, "err": err, "pid": pid})
return result
}
@@ -7344,13 +7329,7 @@ func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int,
mntsrc := filepath.Join("/dev/.lxd-mounts", filepath.Base(tmpMount))
pidStr := fmt.Sprintf("%d", pid)
- out, err := shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-mount", pidStr, mntsrc, target)
-
- if out != "" {
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
- logger.Debugf("forkmount: %s", line)
- }
- }
+ _, err = shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-mount", pidStr, mntsrc, target)
if err != nil {
return err
}
@@ -7408,14 +7387,7 @@ func (c *containerLXC) removeMount(mount string) error {
} else {
// Remove the mount from the container
pidStr := fmt.Sprintf("%d", pid)
- out, err := shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-umount", pidStr, mount)
-
- if out != "" {
- for _, line := range strings.Split(strings.TrimRight(out, "\n"), "\n") {
- logger.Debugf("forkumount: %s", line)
- }
- }
-
+ _, err := shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-umount", pidStr, mount)
if err != nil {
return err
}
diff --git a/lxd/seccomp.go b/lxd/seccomp.go
index 6e5a497e17..3654ecb5e8 100644
--- a/lxd/seccomp.go
+++ b/lxd/seccomp.go
@@ -793,12 +793,12 @@ func (s *SeccompServer) doMknod(c container, dev types.Device, requestPID int) (
prefixPath = strings.TrimPrefix(prefixPath, rootPath)
dev["hostpath"] = filepath.Join(c.RootfsPath(), rootPath, prefixPath, dev["path"])
- errnoMsg, err := shared.RunCommand(util.GetExecPath(),
+ _, stderr, err := shared.RunCommandSplit(util.GetExecPath(),
"forkmknod", dev["pid"], dev["path"],
dev["mode_t"], dev["dev_t"], dev["hostpath"],
fmt.Sprintf("%d", uid), fmt.Sprintf("%d", gid))
if err != nil {
- tmp, err2 := strconv.Atoi(errnoMsg)
+ tmp, err2 := strconv.Atoi(stderr)
if err2 == nil {
goErrno = -tmp
}
More information about the lxc-devel
mailing list