Quoting Stéphane Graber (stgra...@ubuntu.com): > On 12/27/2012 05:01 PM, Dwight Engen wrote: > > lxc-start -c makes the named file/device the container's console, but using > > this with a regular file in order to get a log of the console output does > > not work very well if you also want to login on the console. This change > > implements an additional option (-L) to simply log the console's output to > > a file. > > > > Both options can be used separately or together. For example to get a usable > > console and log: lxc-start -n name -c /dev/tty8 -L console.log > > > > The console state is cleaned up more when lxc_delete_console is called, and > > some of the clean up paths in lxc_create_console were fixed. > > > > The lxc_priv and lxc_unpriv macros were modified to make use of gcc's local > > label feature so they can be expanded more than once in the same function. > > > > Signed-off-by: Dwight Engen <dwight.en...@oracle.com>
Acked-by: Serge E. Hallyn <serge.hal...@ubuntu.com> Thanks, looks good, and agreed this is useful. > > I think I'd like Serge to take a quick look at that one as I have very > limited knowledge of what's going on with the console handling. > I didn't spot any specific problem though. > > Just one comment below related to the manpage change. > > > --- > > doc/lxc-start.sgml.in | 28 ++++++++++------ > > src/lxc/arguments.h | 1 + > > src/lxc/caps.h | 12 ++++--- > > src/lxc/conf.c | 2 ++ > > src/lxc/conf.h | 2 ++ > > src/lxc/console.c | 58 +++++++++++++++++++++++++++----- > > src/lxc/lxc_start.c | 91 > > ++++++++++++++++++++++++++++++--------------------- > > 7 files changed, 134 insertions(+), 60 deletions(-) > > > > diff --git a/doc/lxc-start.sgml.in b/doc/lxc-start.sgml.in > > index 5c98a25..e4036f4 100644 > > --- a/doc/lxc-start.sgml.in > > +++ b/doc/lxc-start.sgml.in > > @@ -51,7 +51,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA > > 02111-1307 USA > > <command>lxc-start</command> > > <arg choice="req">-n <replaceable>name</replaceable></arg> > > <arg choice="opt">-f <replaceable>config_file</replaceable></arg> > > - <arg choice="opt">-c <replaceable>console_file</replaceable></arg> > > + <arg choice="opt">-c <replaceable>console_device</replaceable></arg> > > + <arg choice="opt">-L <replaceable>console_logfile</replaceable></arg> > > <arg choice="opt">-d</arg> > > <arg choice="opt">-p <replaceable>pid_file</replaceable></arg> > > <arg choice="opt">-s KEY=VAL</arg> > > @@ -76,11 +77,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA > > 02111-1307 USA > > defined, the default isolation is used. > > </para> > > <para> > > - The orphan process group > > - and daemon are not supported by this command, use > > - the <command>lxc-execute</command> command instead. > > - </para> > > - <para> > > Why was that dropped? I don't see any mention in the commit message > about it. Is that no longer relevant? > > > If no command is specified, <command>lxc-start</command> will > > use the default > > <command>"/sbin/init"</command> command to run a system > > @@ -139,13 +135,25 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, > > MA 02111-1307 USA > > <varlistentry> > > <term> > > <option>-c, > > - --console <replaceable>console_file</replaceable></option> > > + --console <replaceable>console_device</replaceable></option> > > + </term> > > + <listitem> > > + <para> > > + Specify a device to use for the container's console, for example > > + /dev/tty8. If this option is not specified the current terminal > > + will be used unless <option>-d</option> is specified. > > + </para> > > + </listitem> > > + </varlistentry> > > + > > + <varlistentry> > > + <term> > > + <option>-L, > > + --console-log <replaceable>console_logfile</replaceable></option> > > </term> > > <listitem> > > <para> > > - Specify a file to output the container console. If the > > - option is not specified the output will go the terminal > > - except if the <option>-d</option> is specified. > > + Specify a file to log the container's console output to. > > </para> > > </listitem> > > </varlistentry> > > diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h > > index 188c460..5f2ecba 100644 > > --- a/src/lxc/arguments.h > > +++ b/src/lxc/arguments.h > > @@ -45,6 +45,7 @@ struct lxc_arguments { > > int daemonize; > > const char *rcfile; > > const char *console; > > + const char *console_log; > > const char *pidfile; > > > > /* for lxc-checkpoint/restart */ > > diff --git a/src/lxc/caps.h b/src/lxc/caps.h > > index 0cf8460..88cf09e 100644 > > --- a/src/lxc/caps.h > > +++ b/src/lxc/caps.h > > @@ -33,27 +33,29 @@ extern int lxc_caps_last_cap(void); > > > > #define lxc_priv(__lxc_function) \ > > ({ \ > > + __label__ out; \ > > int __ret, __ret2, __errno = 0; \ > > __ret = lxc_caps_up(); \ > > if (__ret) \ > > - goto __out; \ > > + goto out; \ > > __ret = __lxc_function; \ > > if (__ret) \ > > __errno = errno; \ > > __ret2 = lxc_caps_down(); \ > > - __out: __ret ? errno = __errno,__ret : __ret2; \ > > + out: __ret ? errno = __errno,__ret : __ret2; \ > > }) > > > > -#define lxc_unpriv(__lxc_function) \ > > +#define lxc_unpriv(__lxc_function) \ > > ({ \ > > + __label__ out; \ > > int __ret, __ret2, __errno = 0; \ > > __ret = lxc_caps_down(); \ > > if (__ret) \ > > - goto __out; \ > > + goto out; \ > > __ret = __lxc_function; \ > > if (__ret) \ > > __errno = errno; \ > > __ret2 = lxc_caps_up(); \ > > - __out: __ret ? errno = __errno,__ret : __ret2; \ > > + out: __ret ? errno = __errno,__ret : __ret2; \ > > }) > > #endif > > diff --git a/src/lxc/conf.c b/src/lxc/conf.c > > index c82e759..4f041dc 100644 > > --- a/src/lxc/conf.c > > +++ b/src/lxc/conf.c > > @@ -2005,6 +2005,8 @@ struct lxc_conf *lxc_conf_init(void) > > memset(new, 0, sizeof(*new)); > > > > new->personality = -1; > > + new->console.log_path = NULL; > > + new->console.log_fd = -1; > > new->console.path = NULL; > > new->console.peer = -1; > > new->console.master = -1; > > diff --git a/src/lxc/conf.h b/src/lxc/conf.h > > index d496916..b576893 100644 > > --- a/src/lxc/conf.h > > +++ b/src/lxc/conf.h > > @@ -175,6 +175,8 @@ struct lxc_console { > > int master; > > int peer; > > char *path; > > + char *log_path; > > + int log_fd; > > char name[MAXPATHLEN]; > > struct termios *tios; > > }; > > diff --git a/src/lxc/console.c b/src/lxc/console.c > > index 73bec78..cb756f0 100644 > > --- a/src/lxc/console.c > > +++ b/src/lxc/console.c > > @@ -195,11 +195,21 @@ int lxc_create_console(struct lxc_conf *conf) > > goto err; > > } > > > > + if (console->log_path) { > > + fd = lxc_unpriv(open(console->log_path, O_CLOEXEC | O_RDWR | > > O_CREAT | O_APPEND, 0600)); > > + if (fd < 0) { > > + SYSERROR("failed to open '%s'", console->log_path); > > + goto err; > > + } > > + DEBUG("using '%s' as console log", console->log_path); > > + console->log_fd = fd; > > + } > > + > > fd = lxc_unpriv(open(console->path, O_CLOEXEC | O_RDWR | O_CREAT | > > O_APPEND, 0600)); > > if (fd < 0) { > > SYSERROR("failed to open '%s'", console->path); > > - goto err; > > + goto err_close_console_log; > > } > > > > DEBUG("using '%s' as console", console->path); > > @@ -212,7 +222,7 @@ int lxc_create_console(struct lxc_conf *conf) > > console->tios = malloc(sizeof(tios)); > > if (!console->tios) { > > SYSERROR("failed to allocate memory"); > > - goto err; > > + goto err_close_console; > > } > > > > /* Get termios */ > > @@ -241,26 +251,54 @@ int lxc_create_console(struct lxc_conf *conf) > > > > err_free: > > free(console->tios); > > + > > +err_close_console: > > + close(console->peer); > > + console->peer = -1; > > + > > +err_close_console_log: > > + if (console->log_fd >= 0) { > > + close(console->log_fd); > > + console->log_fd = -1; > > + } > > + > > err: > > close(console->master); > > + console->master = -1; > > + > > close(console->slave); > > + console->slave = -1; > > return -1; > > } > > > > -void lxc_delete_console(const struct lxc_console *console) > > +void lxc_delete_console(struct lxc_console *console) > > { > > if (console->tios && > > tcsetattr(console->peer, TCSAFLUSH, console->tios)) > > WARN("failed to set old terminal settings"); > > + free(console->tios); > > + console->tios = NULL; > > + > > + close(console->peer); > > + console->peer = -1; > > + > > + if (console->log_fd >= 0) { > > + close(console->log_fd); > > + console->log_fd = -1; > > + } > > + > > close(console->master); > > + console->master = -1; > > + > > close(console->slave); > > + console->slave = -1; > > } > > > > static int console_handler(int fd, void *data, struct lxc_epoll_descr > > *descr) > > { > > struct lxc_console *console = (struct lxc_console *)data; > > char buf[1024]; > > - int r; > > + int r,w; > > > > r = read(fd, buf, sizeof(buf)); > > if (r < 0) { > > @@ -280,10 +318,14 @@ static int console_handler(int fd, void *data, struct > > lxc_epoll_descr *descr) > > return 0; > > > > if (console->peer == fd) > > - r = write(console->master, buf, r); > > - else > > - r = write(console->peer, buf, r); > > - > > + w = write(console->master, buf, r); > > + else { > > + w = write(console->peer, buf, r); > > + if (console->log_fd > 0) > > + w = write(console->log_fd, buf, r); > > + } > > + if (w != r) > > + WARN("console short write"); > > return 0; > > } > > > > diff --git a/src/lxc/lxc_start.c b/src/lxc/lxc_start.c > > index fb756dd..184fb04 100644 > > --- a/src/lxc/lxc_start.c > > +++ b/src/lxc/lxc_start.c > > @@ -54,10 +54,46 @@ lxc_log_define(lxc_start_ui, lxc_start); > > > > static struct lxc_list defines; > > > > +static int ensure_path(char **confpath, const char *path) > > +{ > > + int err = -1, fd; > > + char *fullpath = NULL; > > + > > + if (path) { > > + if (access(path, W_OK)) { > > + fd = creat(path, 0600); > > + if (fd < 0) { > > + SYSERROR("failed to create '%s'", path); > > + goto err; > > + } > > + close(fd); > > + } > > + > > + fullpath = realpath(path, NULL); > > + if (!fullpath) { > > + SYSERROR("failed to get the real path of '%s'", path); > > + goto err; > > + } > > + > > + *confpath = strdup(fullpath); > > + if (!*confpath) { > > + ERROR("failed to dup string '%s'", fullpath); > > + goto err; > > + } > > + } > > + err = 0; > > + > > +err: > > + if (fullpath) > > + free(fullpath); > > + return err; > > +} > > + > > static int my_parser(struct lxc_arguments* args, int c, char* arg) > > { > > switch (c) { > > case 'c': args->console = arg; break; > > + case 'L': args->console_log = arg; break; > > case 'd': args->daemonize = 1; args->close_all_fds = 1; break; > > case 'f': args->rcfile = arg; break; > > case 'C': args->close_all_fds = 1; break; > > @@ -72,6 +108,7 @@ static const struct option my_longopts[] = { > > {"rcfile", required_argument, 0, 'f'}, > > {"define", required_argument, 0, 's'}, > > {"console", required_argument, 0, 'c'}, > > + {"console-log", required_argument, 0, 'L'}, > > {"close-all-fds", no_argument, 0, 'C'}, > > {"pidfile", required_argument, 0, 'p'}, > > LXC_COMMON_OPTIONS > > @@ -85,15 +122,16 @@ static struct lxc_arguments my_args = { > > lxc-start start COMMAND in specified container NAME\n\ > > \n\ > > Options :\n\ > > - -n, --name=NAME NAME for name of the container\n\ > > - -d, --daemon daemonize the container\n\ > > - -p, --pidfile=FILE Create a file with the process id\n\ > > - -f, --rcfile=FILE Load configuration file FILE\n\ > > - -c, --console=FILE Set the file output for the container console\n\ > > - -C, --close-all-fds If any fds are inherited, close them\n\ > > - If not specified, exit with failure instead\n\ > > - Note: --daemon implies --close-all-fds\n\ > > - -s, --define KEY=VAL Assign VAL to configuration variable KEY\n", > > + -n, --name=NAME NAME for name of the container\n\ > > + -d, --daemon daemonize the container\n\ > > + -p, --pidfile=FILE Create a file with the process id\n\ > > + -f, --rcfile=FILE Load configuration file FILE\n\ > > + -c, --console=FILE Use specified FILE for the container console\n\ > > + -L, --console-log=FILE Log container console output to FILE\n\ > > + -C, --close-all-fds If any fds are inherited, close them\n\ > > + If not specified, exit with failure instead\n\ > > + Note: --daemon implies --close-all-fds\n\ > > + -s, --define KEY=VAL Assign VAL to configuration variable KEY\n", > > .options = my_longopts, > > .parser = my_parser, > > .checker = NULL, > > @@ -177,35 +215,14 @@ int main(int argc, char *argv[]) > > return err; > > } > > > > - if (my_args.console) { > > - > > - char *console, fd; > > - > > - if (access(my_args.console, W_OK)) { > > - > > - fd = creat(my_args.console, 0600); > > - if (fd < 0) { > > - SYSERROR("failed to touch file '%s'", > > - my_args.console); > > - return err; > > - } > > - close(fd); > > - } > > - > > - console = realpath(my_args.console, NULL); > > - if (!console) { > > - SYSERROR("failed to get the real path of '%s'", > > - my_args.console); > > - return err; > > - } > > - > > - conf->console.path = strdup(console); > > - if (!conf->console.path) { > > - ERROR("failed to dup string '%s'", console); > > - return err; > > - } > > + if (ensure_path(&conf->console.path, my_args.console) < 0) { > > + ERROR("failed to ensure console path '%s'", my_args.console); > > + return err; > > + } > > > > - free(console); > > + if (ensure_path(&conf->console.log_path, my_args.console_log) < 0) { > > + ERROR("failed to ensure console log '%s'", my_args.console_log); > > + return err; > > } > > > > if (my_args.pidfile != NULL) { > > > > > -- > Stéphane Graber > Ubuntu developer > http://www.ubuntu.com > ------------------------------------------------------------------------------ Master Java SE, Java EE, Eclipse, Spring, Hibernate, JavaScript, jQuery and much more. Keep your Java skills current with LearnJavaNow - 200+ hours of step-by-step video tutorials by Java experts. SALE $49.99 this month only -- learn more at: http://p.sf.net/sfu/learnmore_122612 _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel