From: Christian Brauner Date: Fri, 4 Mar 2016 18:32:00 +0000 (+0100) Subject: lxc-attach: fix redirection - stderr X-Git-Tag: lxc-2.0.0.rc6~5^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d96556572ce4e64837c03eec1f64121a2bc8a3f8;p=thirdparty%2Flxc.git lxc-attach: fix redirection - stderr So that we can do things like: lxc-attach -n a -- sh -c 'echo ERR >&2' > /dev/null There seems to be no easy way to discern when we need to write to stderr instead of stdout when we receive an event on the master fd of an allocated pty. So we're using a "trick"/"hack". We write to STDOUT_FILENO if it refers to a pty. If STDOUT_FILENO does not refer to a pty we check whether STDERR_FILENO refers to a pty and if so write to it. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c index 348014d96..ffcd3d189 100644 --- a/src/lxc/lxc_attach.c +++ b/src/lxc/lxc_attach.c @@ -273,7 +273,39 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int * if (lxc_console_create(conf) < 0) return -1; ts = conf->console.tty_state; - ts->stdoutfd = STDOUT_FILENO; + /* + * We need to make sure that the ouput that is produced inside the + * container is received on the host. Suppose we want to run + * + * lxc-attach -n a -- /bin/sh -c 'hostname >&2' > /dev/null + * + * This command produces output on stderr inside the container. On the + * host we close stdout by redirecting it to /dev/null. But stderr is, + * as expected, still connected to a tty. We receive the output produced + * on stderr in the container on stderr on the host. + * + * For the command + * + * lxc-attach -n a -- /bin/sh -c 'hostname >&2' 2> /dev/null + * + * the logic is analogous but because we now have closed stderr on the + * host no output will be received. + * + * Finally, imagine a more complicated case + * + * lxc-attach -n a -- /bin/sh -c 'echo OUT; echo ERR >&2' > /tmp/out 2> /tmp/err + * + * Here, we produce output in the container on stdout and stderr. On the + * host we redirect stdout and stderr to files. Because of that stdout + * and stderr are not dup2()ed. Thus, they are not connected to a pty + * and output on stdout and stderr is redirected to the corresponding + * files as expected. + */ + if (!isatty(STDOUT_FILENO) && isatty(STDERR_FILENO)) + ts->stdoutfd = STDERR_FILENO; + else + ts->stdoutfd = STDOUT_FILENO; + conf->console.descr = &descr; /* Shift ttys to container. */