From f5312c2445d774c9355c947d3c748d064740246e Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 1 Jul 2015 20:32:07 -0400 Subject: [PATCH] scripts: Add 'container' subcommand. * guix/scripts/container.scm: New file. * guix/scripts/container/exec.scm: New file. * po/guix/POTFILES.in: Add them. * Makefile.am (MODULES): Add them. * doc/guix.texi (Invoking guix container): New section. --- Makefile.am | 2 + doc/guix.texi | 54 ++++++++++++++++++++++++++ guix/scripts/container.scm | 63 ++++++++++++++++++++++++++++++ guix/scripts/container/exec.scm | 86 +++++++++++++++++++++++++++++++++++++++++ po/guix/POTFILES.in | 2 + 5 files changed, 207 insertions(+) create mode 100644 guix/scripts/container.scm create mode 100644 guix/scripts/container/exec.scm diff --git a/Makefile.am b/Makefile.am index 4f90b1d..1582af3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -128,6 +128,8 @@ MODULES = \ guix/scripts/edit.scm \ guix/scripts/size.scm \ guix/scripts/graph.scm \ + guix/scripts/container.scm \ + guix/scripts/container/exec.scm \ guix.scm \ $(GNU_SYSTEM_MODULES) diff --git a/doc/guix.texi b/doc/guix.texi index 3491cfb..271b24b 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -144,6 +144,7 @@ Utilities * Invoking guix environment:: Setting up development environments. * Invoking guix publish:: Sharing substitutes. * Invoking guix challenge:: Challenging substitute servers. +* Invoking guix container:: Process isolation. GNU Distribution @@ -3582,6 +3583,7 @@ programming interface of Guix in a convenient way. * Invoking guix environment:: Setting up development environments. * Invoking guix publish:: Sharing substitutes. * Invoking guix challenge:: Challenging substitute servers. +* Invoking guix container:: Process isolation. @end menu @node Invoking guix build @@ -4985,6 +4987,58 @@ URLs to compare to. @end table address@hidden Invoking guix container address@hidden Invoking @command{guix container} address@hidden container + +Note: This tool is experimental. The interface is subject to radical +change in the future. + +The purpose of @command{guix container} is to manipulate processes +running within an isolated environment, commonly known as a +``container,'' typically created by the @command{guix environment} +(@pxref{Invoking guix environment}) and @command{guix system container} +(@pxref{Invoking guix system}) commands. + +The general syntax is: + address@hidden +guix container @var{action} @address@hidden address@hidden example + address@hidden specifies the operation to perform with a container, and address@hidden specifies the context-specific arguments for the action. + +The following actions are available: + address@hidden @code address@hidden exec +Execute a command within the context of a running container. + +The syntax is: + address@hidden +guix container exec @var{pid} @var{program} @address@hidden address@hidden example + address@hidden specifies the process ID of the running container. address@hidden specifies an executable file name within the container's +root file system. @var{arguments} are the additional options that will +be passed to @var{program}. + +The following command launches an interactive login shell inside a +GuixSD container, started by @command{guix system container}, and whose +process ID is 9001: + address@hidden +guix container exec 9001 /run/current-system/profile/bin/bash --login address@hidden example + +Note that the @var{pid} cannot be the parent process of a container. It +must be the container's PID 1 or one of its child processes. + address@hidden table + @c ********************************************************************* @node GNU Distribution @chapter GNU Distribution diff --git a/guix/scripts/container.scm b/guix/scripts/container.scm new file mode 100644 index 0000000..cd9f345 --- /dev/null +++ b/guix/scripts/container.scm @@ -0,0 +1,63 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2015 David Thompson +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts container) + #:use-module (ice-9 match) + #:use-module (guix ui) + #:export (guix-container)) + +(define (show-help) + (display (_ "Usage: guix container ACTION ARGS... +Build and manipulate Linux containers.\n")) + (newline) + (display (_ "The valid values for ACTION are:\n")) + (newline) + (display (_ "\ + exec execute a command inside of an existing container\n")) + (newline) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define %actions '("exec")) + +(define (resolve-action name) + (let ((module (resolve-interface + `(guix scripts container ,(string->symbol name)))) + (proc (string->symbol (string-append "guix-container-" name)))) + (module-ref module proc))) + +(define (guix-container . args) + (with-error-handling + (match args + (() + (format (current-error-port) + (_ "guix container: missing action~%"))) + ((or ("-h") ("--help")) + (show-help) + (exit 0)) + (("--version") + (show-version-and-exit "guix container")) + ((action args ...) + (if (member action %actions) + (apply (resolve-action action) args) + (format (current-error-port) + (_ "guix container: invalid action~%"))))))) diff --git a/guix/scripts/container/exec.scm b/guix/scripts/container/exec.scm new file mode 100644 index 0000000..b842fd3 --- /dev/null +++ b/guix/scripts/container/exec.scm @@ -0,0 +1,86 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2015 David Thompson +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts container exec) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-37) + #:use-module (guix scripts) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (gnu build linux-container) + #:export (guix-container-exec)) + +(define %options + (list (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix container exec"))))) + +(define (show-help) + (display (_ "Usage: guix container exec PID COMMAND [ARGS...] +Execute COMMMAND within the container process PID.\n")) + (newline) + (display (_ " + -h, --help display this help and exit")) + (display (_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + +(define (partition-args args) + "Split ARGS into two lists; one containing the arguments for this program, +and the other containing arguments for the command to be executed." + (break (lambda (arg) + ;; Split after the pid argument. + (not (false-if-exception (string->number arg)))) + args)) + +(define (guix-container-exec . args) + (define (handle-argument arg result) + (if (assoc-ref result 'pid) + (leave (_ "~a: extraneous argument~%") arg) + (alist-cons 'pid (string->number* arg) result))) + + (with-error-handling + (let-values (((args command) (partition-args args))) + (let* ((opts (parse-command-line args %options '(()) + #:argument-handler + handle-argument)) + (pid (assoc-ref opts 'pid))) + + (unless pid + (leave (_ "no pid specified~%"))) + + (when (null? command) + (leave (_ "no command specified~%"))) + + (unless (file-exists? (string-append "/proc/" (number->string pid))) + (leave (_ "no such process ~d~%") pid)) + + (let ((result (container-excursion pid + (lambda () + (match command + ((program . program-args) + (apply execlp program program program-args))))))) + (unless (zero? result) + (leave (_ "exec failed with status ~d~%") result))))))) diff --git a/po/guix/POTFILES.in b/po/guix/POTFILES.in index 0c4e4f8..6197529 100644 --- a/po/guix/POTFILES.in +++ b/po/guix/POTFILES.in @@ -23,6 +23,8 @@ guix/scripts/edit.scm guix/scripts/size.scm guix/scripts/graph.scm guix/scripts/challenge.scm +guix/scripts/container.scm +guix/scripts/container/exec.scm guix/upstream.scm guix/ui.scm guix/http-client.scm -- 2.5.0