diff --git a/man/machinectl.xml b/man/machinectl.xml
index 2f68f91b9..6cf405ed2 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -403,7 +403,7 @@
- shell [NAME [PATH [ARGUMENTS...]]]
+ shell [[NAME@]NAME [PATH [ARGUMENTS...]]] Open an interactive shell session in a
container or on the local host. The first argument refers to
@@ -415,10 +415,29 @@
immediately invokes a user process. This command runs the
specified executable with the specified arguments, or
/bin/sh if none is specified. By default
- opens a root shell, but using
- a different user may be selected. Use
- to set environment variables for
- the executed process.
+ opens a root shell, but by using
+ , or by prefixing the machine name with
+ a username and an @ character, a different
+ user may be selected. Use to set
+ environment variables for the executed process.
+
+ When using the shell command without
+ arguments (thus invoking the executed shell or command on the
+ local host) it is similar in many ways to a su1
+ session, but unlike su completely isolates
+ the new session from the originating session, so that it
+ shares no process or session properties, and is in a clean and
+ well-defined state. It will be tracked in a new utmp, login,
+ audit and keyring session, and will not inherit an environment
+ variables or resource limits, among other properties.
+
+ Note that the
+ systemd-run1
+ may be used in place of the shell command,
+ and allows more detailed, low-level configuration of the
+ invoked unit. However, it is frequently more privileged than
+ the shell command.
@@ -995,6 +1014,17 @@
current directory.
+
+ Create a new shell session
+
+ # machinectl shell --uid=lennart
+
+ This creates a new shell session on the local host, for
+ the user ID lennart, in a su1-like
+ fashion.
+
+
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 08a2d3fe4..6b29e6164 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1299,7 +1299,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
_cleanup_event_unref_ sd_event *event = NULL;
int master = -1, r;
sd_bus *bus = userdata;
- const char *pty, *match, *machine, *path;
+ const char *pty, *match, *machine, *path, *uid = NULL;
assert(bus);
@@ -1319,7 +1319,22 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m");
- machine = argc < 2 || isempty(argv[1]) ? ".host" : argv[1];
+ machine = argc < 2 || isempty(argv[1]) ? NULL : argv[1];
+
+ if (arg_uid)
+ uid = arg_uid;
+ else if (machine) {
+ const char *at;
+
+ at = strchr(machine, '@');
+ if (at) {
+ uid = strndupa(machine, at - machine);
+ machine = at + 1;
+ }
+ }
+
+ if (isempty(machine))
+ machine = ".host";
match = strjoina("type='signal',"
"sender='org.freedesktop.machine1',"
@@ -1344,7 +1359,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) {
path = argc < 3 || isempty(argv[2]) ? NULL : argv[2];
- r = sd_bus_message_append(m, "sss", machine, arg_uid, path);
+ r = sd_bus_message_append(m, "sss", machine, uid, path);
if (r < 0)
return bus_log_create_error(r);
@@ -2440,8 +2455,9 @@ static int help(int argc, char *argv[], void *userdata) {
" start NAME... Start container as a service\n"
" login [NAME] Get a login prompt in a container or on the\n"
" local host\n"
- " shell [NAME] [COMMAND...] Invoke a shell (or other command) in a container\n"
- " or the local host\n"
+ " shell [[USER@]NAME [COMMAND...]]\n"
+ " Invoke a shell (or other command) in a container\n"
+ " or on the local host\n"
" enable NAME... Enable automatic container start at boot\n"
" disable NAME... Disable automatic container start at boot\n"
" poweroff NAME... Power off one or more containers\n"