[systemd-commits] 12 commits - Makefile.am TODO man/loginctl.xml man/machinectl.xml man/systemctl.xml src/core src/firstboot src/login src/machine src/nspawn src/shared src/systemctl src/test
Lennart Poettering
lennart at kemper.freedesktop.org
Thu Jan 8 14:13:52 PST 2015
Makefile.am | 4
TODO | 8
man/loginctl.xml | 68 +++++-
man/machinectl.xml | 350 ++++++++++++++++++++++++++++-----
man/systemctl.xml | 209 ++++++++++---------
src/core/execute.c | 12 -
src/firstboot/firstboot.c | 2
src/login/loginctl.c | 475 ++++++++++++++++++++++++---------------------
src/machine/machinectl.c | 142 ++++++++++---
src/nspawn/nspawn.c | 2
src/shared/copy.c | 9
src/shared/copy.h | 4
src/shared/logs-show.c | 8
src/shared/logs-show.h | 5
src/shared/machine-image.c | 9
src/systemctl/systemctl.c | 78 ++++---
src/test/test-copy.c | 2
17 files changed, 923 insertions(+), 464 deletions(-)
New commits:
commit a47e6701bfc45519a4e038daa52e9236e932f59a
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 23:13:28 2015 +0100
update TODO
diff --git a/TODO b/TODO
index ee682c0..90c321c 100644
--- a/TODO
+++ b/TODO
@@ -45,6 +45,14 @@ Release 219 preparations:
Features:
+* nspawn should lock container images while running off them
+
+* when invoking "loginctl session-status" default to callers session
+
+* logind,machined: add generic catch-all polkit verbs for most priviliged operations, similar to systemd itself
+
+* "machinectl status" should also show logs of the container in question
+
* nspawn: don't change superblock mount options from nspawn for cgroup hierarchies
* "machinectl list-images" should show os-release data, as well as machine-info data (including deployment level)
commit d5243d628624038567c576e9b69c1d775eb05a05
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 23:12:16 2015 +0100
core: make EPERM errors when applying OOM adjustment for forked processes non-fatal
This should be useful for user namespaces.
diff --git a/src/core/execute.c b/src/core/execute.c
index 0af4227..63d295c 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1406,12 +1406,16 @@ static int exec_child(ExecCommand *command,
}
if (context->oom_score_adjust_set) {
- char t[16];
+ char t[DECIMAL_STR_MAX(context->oom_score_adjust)];
- snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
- char_array_0(t);
+ /* When we can't make this change due to EPERM, then
+ * let's silently skip over it. User namespaces
+ * prohibit write access to this file, and we
+ * shouldn't trip up over that. */
- if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
+ sprintf(t, "%i", context->oom_score_adjust);
+ err = write_string_file("/proc/self/oom_score_adj", t);
+ if (err < 0 && err != -EPERM) {
*error = EXIT_OOM_ADJUST;
return -errno;
}
commit f7621db0e38c3e96d48766ae648f1b7a0949ea13
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 23:11:35 2015 +0100
loginctl: port to generic verbs.h API
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 9f77903..0fdd42b 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -41,6 +41,7 @@
#include "cgroup-show.h"
#include "cgroup-util.h"
#include "spawn-polkit-agent.h"
+#include "verbs.h"
static char **arg_property = NULL;
static bool arg_all = false;
@@ -85,14 +86,18 @@ static OutputFlags get_output_flags(void) {
on_tty() * OUTPUT_COLOR;
}
-static int list_sessions(sd_bus *bus, char **args, unsigned n) {
+static int list_sessions(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
const char *id, *user, *seat, *object;
+ sd_bus *bus = userdata;
unsigned k = 0;
uint32_t uid;
int r;
+ assert(bus);
+ assert(argv);
+
pager_open_if_enabled();
r = sd_bus_call_method(
@@ -128,14 +133,18 @@ static int list_sessions(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int list_users(sd_bus *bus, char **args, unsigned n) {
+static int list_users(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
const char *user, *object;
+ sd_bus *bus = userdata;
unsigned k = 0;
uint32_t uid;
int r;
+ assert(bus);
+ assert(argv);
+
pager_open_if_enabled();
r = sd_bus_call_method(
@@ -171,13 +180,17 @@ static int list_users(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int list_seats(sd_bus *bus, char **args, unsigned n) {
+static int list_seats(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
const char *seat, *object;
+ sd_bus *bus = userdata;
unsigned k = 0;
int r;
+ assert(bus);
+ assert(argv);
+
pager_open_if_enabled();
r = sd_bus_call_method(
@@ -659,25 +672,25 @@ static int show_properties(sd_bus *bus, const char *path, bool *new_line) {
return r;
}
-static int show_session(sd_bus *bus, char **args, unsigned n) {
+static int show_session(int argc, char *argv[], void *userdata) {
bool properties, new_line = false;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
assert(bus);
- assert(args);
+ assert(argv);
- properties = !strstr(args[0], "status");
+ properties = !strstr(argv[0], "status");
pager_open_if_enabled();
- if (properties && n <= 1) {
+ if (properties && argc <= 1) {
/* If not argument is specified inspect the manager
* itself */
return show_properties(bus, "/org/freedesktop/login1", &new_line);
}
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
const char *path = NULL;
@@ -689,7 +702,7 @@ static int show_session(sd_bus *bus, char **args, unsigned n) {
"org.freedesktop.login1.Manager",
"GetSession",
&error, &reply,
- "s", args[i]);
+ "s", argv[i]);
if (r < 0) {
log_error("Failed to get session: %s", bus_error_message(&error, r));
return r;
@@ -711,33 +724,33 @@ static int show_session(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int show_user(sd_bus *bus, char **args, unsigned n) {
+static int show_user(int argc, char *argv[], void *userdata) {
bool properties, new_line = false;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
assert(bus);
- assert(args);
+ assert(argv);
- properties = !strstr(args[0], "status");
+ properties = !strstr(argv[0], "status");
pager_open_if_enabled();
- if (properties && n <= 1) {
+ if (properties && argc <= 1) {
/* If not argument is specified inspect the manager
* itself */
return show_properties(bus, "/org/freedesktop/login1", &new_line);
}
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
const char *path = NULL;
uid_t uid;
- r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+ return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
r = sd_bus_call_method(
bus,
@@ -768,25 +781,25 @@ static int show_user(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int show_seat(sd_bus *bus, char **args, unsigned n) {
+static int show_seat(int argc, char *argv[], void *userdata) {
bool properties, new_line = false;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
assert(bus);
- assert(args);
+ assert(argv);
- properties = !strstr(args[0], "status");
+ properties = !strstr(argv[0], "status");
pager_open_if_enabled();
- if (properties && n <= 1) {
+ if (properties && argc <= 1) {
/* If not argument is specified inspect the manager
* itself */
return show_properties(bus, "/org/freedesktop/login1", &new_line);
}
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message * reply = NULL;
const char *path = NULL;
@@ -798,7 +811,7 @@ static int show_seat(sd_bus *bus, char **args, unsigned n) {
"org.freedesktop.login1.Manager",
"GetSeat",
&error, &reply,
- "s", args[i]);
+ "s", argv[i]);
if (r < 0) {
log_error("Failed to get seat: %s", bus_error_message(&error, r));
return r;
@@ -820,28 +833,29 @@ static int show_seat(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int activate(sd_bus *bus, char **args, unsigned n) {
+static int activate(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
r = sd_bus_call_method (
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
- streq(args[0], "lock-session") ? "LockSession" :
- streq(args[0], "unlock-session") ? "UnlockSession" :
- streq(args[0], "terminate-session") ? "TerminateSession" :
+ streq(argv[0], "lock-session") ? "LockSession" :
+ streq(argv[0], "unlock-session") ? "UnlockSession" :
+ streq(argv[0], "terminate-session") ? "TerminateSession" :
"ActivateSession",
&error, NULL,
- "s", args[i]);
+ "s", argv[i]);
if (r < 0) {
log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
return r;
@@ -851,19 +865,20 @@ static int activate(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int kill_session(sd_bus *bus, char **args, unsigned n) {
+static int kill_session(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
if (!arg_kill_who)
arg_kill_who = "all";
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
r = sd_bus_call_method (
bus,
@@ -872,7 +887,7 @@ static int kill_session(sd_bus *bus, char **args, unsigned n) {
"org.freedesktop.login1.Manager",
"KillSession",
&error, NULL,
- "ssi", args[i], arg_kill_who, arg_signal);
+ "ssi", argv[i], arg_kill_who, arg_signal);
if (r < 0) {
log_error("Could not kill session: %s", bus_error_message(&error, -r));
return r;
@@ -882,24 +897,25 @@ static int kill_session(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int enable_linger(sd_bus *bus, char **args, unsigned n) {
+static int enable_linger(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned i;
+ sd_bus *bus = userdata;
bool b;
- int r;
+ int r, i;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
- b = streq(args[0], "enable-linger");
+ b = streq(argv[0], "enable-linger");
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
uid_t uid;
- r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+ return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
r = sd_bus_call_method (
bus,
@@ -918,21 +934,22 @@ static int enable_linger(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int terminate_user(sd_bus *bus, char **args, unsigned n) {
+static int terminate_user(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
uid_t uid;
- r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+ return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
r = sd_bus_call_method (
bus,
@@ -951,24 +968,25 @@ static int terminate_user(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int kill_user(sd_bus *bus, char **args, unsigned n) {
+static int kill_user(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
if (!arg_kill_who)
arg_kill_who = "all";
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
uid_t uid;
- r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL);
+ r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL);
if (r < 0)
- return log_error_errno(r, "Failed to look up user %s: %m", args[i]);
+ return log_error_errno(r, "Failed to look up user %s: %m", argv[i]);
r = sd_bus_call_method (
bus,
@@ -987,16 +1005,17 @@ static int kill_user(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int attach(sd_bus *bus, char **args, unsigned n) {
+static int attach(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
- for (i = 2; i < n; i++) {
+ for (i = 2; i < argc; i++) {
r = sd_bus_call_method (
bus,
@@ -1005,7 +1024,7 @@ static int attach(sd_bus *bus, char **args, unsigned n) {
"org.freedesktop.login1.Manager",
"AttachDevice",
&error, NULL,
- "ssb", args[1], args[i], true);
+ "ssb", argv[1], argv[i], true);
if (r < 0) {
log_error("Could not attach device: %s", bus_error_message(&error, -r));
@@ -1016,11 +1035,13 @@ static int attach(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static int flush_devices(sd_bus *bus, char **args, unsigned n) {
+static int flush_devices(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
@@ -1038,20 +1059,22 @@ static int flush_devices(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int lock_sessions(sd_bus *bus, char **args, unsigned n) {
+static int lock_sessions(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ sd_bus *bus = userdata;
int r;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
- streq(args[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
+ streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions",
&error, NULL,
NULL);
if (r < 0)
@@ -1060,25 +1083,26 @@ static int lock_sessions(sd_bus *bus, char **args, unsigned n) {
return r;
}
-static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
+static int terminate_seat(int argc, char *argv[], void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- unsigned i;
- int r;
+ sd_bus *bus = userdata;
+ int r, i;
- assert(args);
+ assert(bus);
+ assert(argv);
polkit_agent_open_if_enabled();
- for (i = 1; i < n; i++) {
+ for (i = 1; i < argc; i++) {
- r = sd_bus_call_method (
+ r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"TerminateSeat",
&error, NULL,
- "s", args[i]);
+ "s", argv[i]);
if (r < 0) {
log_error("Could not terminate seat: %s", bus_error_message(&error, -r));
return r;
@@ -1088,7 +1112,7 @@ static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
return 0;
}
-static void help(void) {
+static int help(int argc, char *argv[], void *userdata) {
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the login manager.\n\n"
@@ -1134,6 +1158,8 @@ static void help(void) {
" flush-devices Flush all device associations\n"
" terminate-seat NAME... Terminate all sessions on one or more seats\n"
, program_invocation_short_name);
+
+ return 0;
}
static int parse_argv(int argc, char *argv[]) {
@@ -1174,7 +1200,7 @@ static int parse_argv(int argc, char *argv[]) {
switch (c) {
case 'h':
- help();
+ help(0, NULL, NULL);
return 0;
case ARG_VERSION:
@@ -1261,101 +1287,37 @@ static int parse_argv(int argc, char *argv[]) {
return 1;
}
-static int loginctl_main(sd_bus *bus, int argc, char *argv[]) {
-
- static const struct {
- const char* verb;
- const enum {
- MORE,
- LESS,
- EQUAL
- } argc_cmp;
- const int argc;
- int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
- } verbs[] = {
- { "list-sessions", LESS, 1, list_sessions },
- { "session-status", MORE, 2, show_session },
- { "show-session", MORE, 1, show_session },
- { "activate", EQUAL, 2, activate },
- { "lock-session", MORE, 2, activate },
- { "unlock-session", MORE, 2, activate },
- { "lock-sessions", EQUAL, 1, lock_sessions },
- { "unlock-sessions", EQUAL, 1, lock_sessions },
- { "terminate-session", MORE, 2, activate },
- { "kill-session", MORE, 2, kill_session },
- { "list-users", EQUAL, 1, list_users },
- { "user-status", MORE, 2, show_user },
- { "show-user", MORE, 1, show_user },
- { "enable-linger", MORE, 2, enable_linger },
- { "disable-linger", MORE, 2, enable_linger },
- { "terminate-user", MORE, 2, terminate_user },
- { "kill-user", MORE, 2, kill_user },
- { "list-seats", EQUAL, 1, list_seats },
- { "seat-status", MORE, 2, show_seat },
- { "show-seat", MORE, 1, show_seat },
- { "attach", MORE, 3, attach },
- { "flush-devices", EQUAL, 1, flush_devices },
- { "terminate-seat", MORE, 2, terminate_seat },
+static int loginctl_main(int argc, char *argv[], sd_bus *bus) {
+
+ static const Verb verbs[] = {
+ { "help", VERB_ANY, VERB_ANY, 0, help },
+ { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions },
+ { "session-status", 2, VERB_ANY, 0, show_session },
+ { "show-session", VERB_ANY, VERB_ANY, 0, show_session },
+ { "activate", 2, 2, 0, activate },
+ { "lock-session", 2, VERB_ANY, 0, activate },
+ { "unlock-session", 2, VERB_ANY, 0, activate },
+ { "lock-sessions", VERB_ANY, 1, 0, lock_sessions },
+ { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions },
+ { "terminate-session", 2, VERB_ANY, 0, activate },
+ { "kill-session", 2, VERB_ANY, 0, kill_session },
+ { "list-users", VERB_ANY, 1, 0, list_users },
+ { "user-status", 2, VERB_ANY, 0, show_user },
+ { "show-user", VERB_ANY, VERB_ANY, 0, show_user },
+ { "enable-linger", 2, VERB_ANY, 0, enable_linger },
+ { "disable-linger", 2, VERB_ANY, 0, enable_linger },
+ { "terminate-user", 2, VERB_ANY, 0, terminate_user },
+ { "kill-user", 2, VERB_ANY, 0, kill_user },
+ { "list-seats", VERB_ANY, 1, 0, list_seats },
+ { "seat-status", 2, VERB_ANY, 0, show_seat },
+ { "show-seat", VERB_ANY, 1, 0, show_seat },
+ { "attach", 3, VERB_ANY, 0, attach },
+ { "flush-devices", VERB_ANY, 1, 0, flush_devices },
+ { "terminate-seat", 2, VERB_ANY, 0, terminate_seat },
+ {}
};
- int left;
- unsigned i;
-
- assert(argc >= 0);
- assert(argv);
-
- left = argc - optind;
-
- if (left <= 0)
- /* Special rule: no arguments means "list-sessions" */
- i = 0;
- else {
- if (streq(argv[optind], "help")) {
- help();
- return 0;
- }
-
- for (i = 0; i < ELEMENTSOF(verbs); i++)
- if (streq(argv[optind], verbs[i].verb))
- break;
-
- if (i >= ELEMENTSOF(verbs)) {
- log_error("Unknown operation %s", argv[optind]);
- return -EINVAL;
- }
- }
-
- switch (verbs[i].argc_cmp) {
-
- case EQUAL:
- if (left != verbs[i].argc) {
- log_error("Invalid number of arguments.");
- return -EINVAL;
- }
-
- break;
-
- case MORE:
- if (left < verbs[i].argc) {
- log_error("Too few arguments.");
- return -EINVAL;
- }
-
- break;
-
- case LESS:
- if (left > verbs[i].argc) {
- log_error("Too many arguments.");
- return -EINVAL;
- }
-
- break;
-
- default:
- assert_not_reached("Unknown comparison operator.");
- }
-
- return verbs[i].dispatch(bus, argv + optind, left);
+ return dispatch_verb(argc, argv, verbs, bus);
}
int main(int argc, char *argv[]) {
@@ -1376,10 +1338,11 @@ int main(int argc, char *argv[]) {
goto finish;
}
- r = loginctl_main(bus, argc, argv);
+ r = loginctl_main(argc, argv, bus);
finish:
pager_close();
+ polkit_agent_close();
strv_free(arg_property);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index dbfc245..749170e 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1778,8 +1778,8 @@ static int help(int argc, char *argv[], void *userdata) {
" clone NAME NAME Clone an image\n"
" rename NAME NAME Rename an image\n"
" read-only NAME [BOOL] Mark or unmark image read-only\n"
- " remove NAME... Remove an image\n",
- program_invocation_short_name);
+ " remove NAME... Remove an image\n"
+ , program_invocation_short_name);
return 0;
}
commit a03fe1a5d56be86fcc383090e191224590a1ab5d
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 19:16:44 2015 +0100
man: remove references to systemadm from systemctl man page
The tool is badly maintained and we shouldn't refence such old cruft.
diff --git a/man/systemctl.xml b/man/systemctl.xml
index dd9fd99..caad131 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -1718,9 +1718,9 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
- <citerefentry><refentrytitle>systemadm</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>loginctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+ <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.resource-management</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
commit f2068bcce01db31cdc9422f44185f3b49c04d2ce
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 19:15:49 2015 +0100
machined: when cloning a raw disk image, also set the NOCOW flag
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index d087ef3..ce79574 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -256,7 +256,7 @@ static int process_locale(void) {
if (arg_copy_locale && arg_root) {
mkdir_parents(etc_localeconf, 0755);
- r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644);
+ r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644, 0);
if (r != -ENOENT) {
if (r < 0)
return log_error_errno(r, "Failed to copy %s: %m", etc_localeconf);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index e5a24dd..59f6f38 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -1092,7 +1092,7 @@ static int setup_resolv_conf(const char *dest) {
return 0;
}
- r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644);
+ r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644, 0);
if (r < 0) {
log_warning_errno(r, "Failed to copy /etc/resolv.conf to %s: %m", where);
diff --git a/src/shared/copy.c b/src/shared/copy.c
index 3df6367..b681f6f 100644
--- a/src/shared/copy.c
+++ b/src/shared/copy.c
@@ -359,7 +359,7 @@ int copy_file_fd(const char *from, int fdt, bool try_reflink) {
return r;
}
-int copy_file(const char *from, const char *to, int flags, mode_t mode) {
+int copy_file(const char *from, const char *to, int flags, mode_t mode, int chattr_flags) {
int fdt, r;
assert(from);
@@ -371,6 +371,9 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode) {
return -errno;
}
+ if (chattr_flags != 0)
+ (void) chattr_fd(fdt, true, chattr_flags);
+
r = copy_file_fd(from, fdt, true);
if (r < 0) {
close(fdt);
@@ -386,7 +389,7 @@ int copy_file(const char *from, const char *to, int flags, mode_t mode) {
return 0;
}
-int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace) {
+int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, int chattr_flags) {
_cleanup_free_ char *t;
int r;
@@ -397,7 +400,7 @@ int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace
if (r < 0)
return r;
- r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode);
+ r = copy_file(from, t, O_NOFOLLOW|O_EXCL, mode, chattr_flags);
if (r < 0)
return r;
diff --git a/src/shared/copy.h b/src/shared/copy.h
index 58159a0..e4e3079 100644
--- a/src/shared/copy.h
+++ b/src/shared/copy.h
@@ -25,8 +25,8 @@
#include <sys/types.h>
int copy_file_fd(const char *from, int to, bool try_reflink);
-int copy_file(const char *from, const char *to, int flags, mode_t mode);
-int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace);
+int copy_file(const char *from, const char *to, int flags, mode_t mode, int chattr_flags);
+int copy_file_atomic(const char *from, const char *to, mode_t mode, bool replace, int chattr_flags);
int copy_tree(const char *from, const char *to, bool merge);
int copy_tree_at(int fdf, const char *from, int fdt, const char *to, bool merge);
int copy_directory_fd(int dirfd, const char *to, bool merge);
diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c
index 36b64e1..25689ca 100644
--- a/src/shared/machine-image.c
+++ b/src/shared/machine-image.c
@@ -20,6 +20,7 @@
***/
#include <sys/statfs.h>
+#include <linux/fs.h>
#include <fcntl.h>
#include "strv.h"
@@ -440,7 +441,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) {
case IMAGE_GPT:
new_path = strappenda("/var/lib/container/", new_name, ".gpt");
- r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644, false);
+ r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644, false, FS_NOCOW_FL);
break;
default:
@@ -477,6 +478,12 @@ int image_read_only(Image *i, bool b) {
if (chmod(i->path, (st.st_mode & 0444) | (b ? 0000 : 0200)) < 0)
return -errno;
+
+ /* If the images is now read-only, it's a good time to
+ * defrag it, given that no write patterns will
+ * fragment it again. */
+ if (b)
+ (void) btrfs_defrag(i->path);
break;
}
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 74528dd..3121428 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5669,7 +5669,7 @@ static int create_edit_temp_file(const char *new_path, const char *original_path
return r;
}
- r = copy_file(original_path, t, 0, 0644);
+ r = copy_file(original_path, t, 0, 0644, 0);
if (r == -ENOENT) {
r = touch(t);
if (r < 0) {
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index d70a0be..3e1607e 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -44,7 +44,7 @@ static void test_copy_file(void) {
assert_se(write_string_file(fn, "foo bar bar bar foo") == 0);
- assert_se(copy_file(fn, fn_copy, 0, 0644) == 0);
+ assert_se(copy_file(fn, fn_copy, 0, 0644, 0) == 0);
assert_se(read_full_file(fn_copy, &buf, &sz) == 0);
assert_se(streq(buf, "foo bar bar bar foo\n"));
commit e45fc5e738b0b7700e8b4f3c4b25c58a49b44b27
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 19:14:08 2015 +0100
man: bring machinectl man page up-to-date
diff --git a/man/machinectl.xml b/man/machinectl.xml
index ebe8e3b..91bdb5e 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -76,27 +76,31 @@
<term><option>-p</option></term>
<term><option>--property=</option></term>
- <listitem><para>When showing
- machine properties, limit the
- output to certain properties as
- specified by the argument. If not
- specified, all set properties are
- shown. The argument should be a
- property name, such as
- <literal>Name</literal>. If
- specified more than once, all
- properties with the specified names
- are shown.</para></listitem>
+ <listitem><para>When showing machine
+ or image properties, limit the output
+ to certain properties as specified by
+ the argument. If not specified, all
+ set properties are shown. The argument
+ should be a property name, such as
+ <literal>Name</literal>. If specified
+ more than once, all properties with
+ the specified names are
+ shown.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-a</option></term>
<term><option>--all</option></term>
- <listitem><para>When showing
- machine properties, show all
- properties regardless of whether they are
- set or not.</para></listitem>
+ <listitem><para>When showing machine
+ or image properties, show all
+ properties regardless of whether they
+ are set or not.</para>
+
+ <para>When listing VM or container
+ images, do not suppress images
+ beginning in a dot character
+ (<literal>.</literal>).</para></listitem>
</varlistentry>
<varlistentry>
@@ -208,16 +212,24 @@
<xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
</variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Commands</title>
<para>The following commands are understood:</para>
- <variablelist>
+ <refsect2><title>Machine Commands</title><variablelist>
+
<varlistentry>
<term><command>list</command></term>
<listitem><para>List currently running
- virtual machines and containers.
- </para></listitem>
+ (online) virtual machines and
+ containers. To enumerate container
+ images that can be started,
+ use <command>list-images</command>
+ (see below).</para></listitem>
</varlistentry>
<varlistentry>
@@ -265,29 +277,91 @@
</varlistentry>
<varlistentry>
+ <term><command>start</command> <replaceable>NAME</replaceable>...</term>
+
+ <listitem><para>Start a container as a
+ system service, using
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ This starts
+ <filename>systemd-nspawn at .service</filename>,
+ instantiated for the specified machine
+ name, similar to the effect of
+ <command>systemctl start</command> on
+ the service
+ name. <command>systemd-nspawn</command>
+ looks for a container image by the
+ specified name in
+ <filename>/var/lib/container</filename>
+ and runs it. Use
+ <command>list-images</command> (see
+ below), for listing available
+ container images to start.</para>
+
+ <para>Note that
+ <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ also interfaces with a variety of
+ other container and VM managers,
+ <command>systemd-nspawn</command> is
+ just one implementation of it. Most of
+ the commands available in
+ <command>machinectl</command> may be
+ used on containers or VMs controlled
+ by other managers, not just
+ <command>systemd-nspawn</command>. Starting
+ VMs and container images on those
+ managers requires manager-specific
+ tools.</para>
+
+ <para>To interactively start a
+ container on the command line with
+ full access to the container's
+ console, please invoke
+ <command>systemd-nspawn</command>
+ directly. To stop a running container
+ use <command>machinectl
+ poweroff</command>, see
+ below.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><command>login</command> <replaceable>NAME</replaceable></term>
- <listitem><para>Open a terminal login
+ <listitem><para>Open an interactive terminal login
session to a container. This will
create a TTY connection to a specific
container and asks for the execution of a
getty on it. Note that this is only
supported for containers running
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
- as init system.</para></listitem>
+ as init system.</para>
+
+ <para>This command will open a full
+ login prompt on the container, which
+ then asks for username and
+ password. Use
+ <citerefentry><refentrytitle>systemd-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+ with the <option>--machine=</option>
+ switch to invoke a single command,
+ either interactively or in the
+ background within a local
+ container.</para></listitem>
</varlistentry>
<varlistentry>
- <term><command>reboot</command> <replaceable>NAME</replaceable>...</term>
-
- <listitem><para>Reboot one or more
- containers. This will trigger a reboot
- by sending SIGINT to the container's
- init process, which is roughly
- equivalent to pressing Ctrl+Alt+Del on
- a non-containerized system, and is
- compatible with containers running any
- init system.</para></listitem>
+ <term><command>enable</command> <replaceable>NAME</replaceable>...</term>
+ <term><command>disable</command> <replaceable>NAME</replaceable>...</term>
+
+ <listitem><para>Enable or disable a
+ container as a system service to start
+ at system boot, using
+ <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ This enables or disables
+ <filename>systemd-nspawn at .service</filename>,
+ instantiated for the specified machine
+ name, similar to the effect of
+ <command>systemctl enable</command> or
+ <command>systemctl disable</command>
+ on the service name.</para></listitem>
</varlistentry>
<varlistentry>
@@ -302,8 +376,38 @@
not work on containers that do not run
a
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>-compatible
- init system, such as
- sysvinit.</para></listitem>
+ init system, such as sysvinit. Use
+ <command>terminate</command> (see
+ below) to immediately terminate a
+ container or VM, without cleanly
+ shutting it down.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>reboot</command> <replaceable>NAME</replaceable>...</term>
+
+ <listitem><para>Reboot one or more
+ containers. This will trigger a reboot
+ by sending SIGINT to the container's
+ init process, which is roughly
+ equivalent to pressing Ctrl+Alt+Del on
+ a non-containerized system, and is
+ compatible with containers running any
+ system manager.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>terminate</command> <replaceable>NAME</replaceable>...</term>
+
+ <listitem><para>Immediately terminates
+ a virtual machine or container,
+ without cleanly shutting it down. This
+ kills all processes of the virtual
+ machine or container and deallocates
+ all resources attached to that
+ instance. Use
+ <command>poweroff</command> to issue a
+ clean shutdown request.</para></listitem>
</varlistentry>
<varlistentry>
@@ -322,17 +426,6 @@
</varlistentry>
<varlistentry>
- <term><command>terminate</command> <replaceable>NAME</replaceable>...</term>
-
- <listitem><para>Terminates a virtual
- machine or container. This kills all
- processes of the virtual machine or
- container and deallocates all
- resources attached to that
- instance.</para></listitem>
- </varlistentry>
-
- <varlistentry>
<term><command>bind</command> <replaceable>NAME</replaceable> <replaceable>PATH</replaceable> [<replaceable>PATH</replaceable>]</term>
<listitem><para>Bind mounts a
@@ -383,8 +476,122 @@
omitted the same as the source path is
used.</para></listitem>
</varlistentry>
+ </variablelist></refsect2>
- </variablelist>
+ <refsect2><title>Image Commands</title><variablelist>
+
+ <varlistentry>
+ <term><command>list-images</command></term>
+
+ <listitem><para>Show a list of locally
+ installed container and VM
+ images. This enumerates all raw disk
+ images and container directories and
+ subvolumes in
+ <filename>/var/lib/container/</filename>. Use
+ <command>start</command> (see above)
+ to run a container off one of the
+ listed images. Note that by default
+ containers whose name begins with a
+ dot (<literal>.</literal>) are not
+ shown. To show these too, specify
+ <option>--all</option>. Note that a
+ special image <literal>.host</literal>
+ always implicitly exists and refers to
+ the image the host itself is booted
+ from.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>image-status</command> <replaceable>NAME</replaceable>...</term>
+
+ <listitem><para>Show terse status
+ information about one or more
+ container or VM images. This function
+ is intended to generate human-readable
+ output. Use
+ <command>show-image</command> (see
+ below) to generate computer-parsable
+ output instead.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>show-image</command> <replaceable>NAME</replaceable>...</term>
+
+ <listitem><para>Show properties of one
+ or more registered virtual machine or
+ container images, or the manager
+ itself. If no argument is specified,
+ properties of the manager will be
+ shown. If an NAME is specified,
+ properties of this virtual machine or
+ container image are shown. By default,
+ empty properties are suppressed. Use
+ <option>--all</option> to show those
+ too. To select specific properties to
+ show, use
+ <option>--property=</option>. This
+ command is intended to be used
+ whenever computer-parsable output is
+ required. Use
+ <command>image-status</command> if you
+ are looking for formatted
+ human-readable
+ output.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>clone</command> <replaceable>NAME</replaceable> <replaceable>NAME</replaceable></term>
+
+ <listitem><para>Clones a container or
+ disk image. The arguments specify the
+ name of the image to clone and the
+ name of the newly cloned image. Note
+ that plain directory container images
+ are cloned into subvolume images with
+ this command. Note that cloning a
+ container or VM image is optimized for
+ btrfs file systems, and might not be
+ efficient on others, due to file
+ system limitations.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>rename</command> <replaceable>NAME</replaceable> <replaceable>NAME</replaceable></term>
+
+ <listitem><para>Renames a container or
+ disk image. The arguments specify the
+ name of the image to rename and the
+ new name of the
+ image.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>read-only</command> <replaceable>NAME</replaceable> [<replaceable>BOOL</replaceable>]</term>
+
+ <listitem><para>Marks or (unmarks) a
+ container or disk image
+ read-only. Takes a VM or container
+ image name, followed by a boolean as
+ arguments. If the boolean is omitted,
+ positive is implied, i.e. the image is
+ marked read-only.</para></listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><command>remove</command> <replaceable>NAME</replaceable>...</term>
+
+ <listitem><para>Removes one or more
+ container or disk images. The special
+ image <literal>.host</literal>, which
+ refers to the host's own directory
+ tree may not be
+ removed.</para></listitem>
+ </varlistentry>
+
+
+ </variablelist></refsect2>
</refsect1>
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 939b648..dbfc245 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -1760,8 +1760,8 @@ static int help(int argc, char *argv[], void *userdata) {
" list List running VMs and containers\n"
" status NAME... Show VM/container details\n"
" show NAME... Show properties of one or more VMs/containers\n"
- " login NAME Get a login prompt on a container\n"
" start NAME... Start container as a service\n"
+ " login NAME Get a login prompt on a container\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"
commit b619ec8f83ee3f524dae1f4692b26731bbe68616
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 18:08:40 2015 +0100
man: bring systemctl man page and --help text into the same order
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 3ac6f62..dd9fd99 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -386,7 +386,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
querying the user for authentication for privileged
operations.</para>
</listitem>
-
</varlistentry>
<varlistentry>
@@ -993,6 +992,56 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</varlistentry>
<varlistentry>
+ <term><command>reenable <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Reenable one or more unit files, as specified on the
+ command line. This is a combination of
+ <command>disable</command> and <command>enable</command> and
+ is useful to reset the symlinks a unit is enabled with to
+ the defaults configured in the <literal>[Install]</literal>
+ section of the unit file.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>preset <replaceable>NAME</replaceable>...</command></term>
+
+ <listitem>
+ <para>Reset one or more unit files, as specified on the
+ command line, to the defaults configured in the preset
+ policy files. This has the same effect as
+ <command>disable</command> or <command>enable</command>,
+ depending how the unit is listed in the preset files.</para>
+
+ <para>Use <option>--preset-mode=</option> to control
+ whether units shall be enabled and disabled, or only
+ enabled, or only disabled.</para>
+
+ <para>For more information on the preset policy format,
+ see
+ <citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ For more information on the concept of presets, please
+ consult the <ulink
+ url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
+ document.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>preset-all</command></term>
+
+ <listitem>
+ <para>Resets all installed unit files to the defaults
+ configured in the preset policy file (see above).</para>
+
+ <para>Use <option>--preset-mode=</option> to control
+ whether units shall be enabled and disabled, or only
+ enabled, or only disabled.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><command>is-enabled <replaceable>NAME</replaceable>...</command></term>
<listitem>
@@ -1064,56 +1113,6 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</varlistentry>
<varlistentry>
- <term><command>reenable <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Reenable one or more unit files, as specified on the
- command line. This is a combination of
- <command>disable</command> and <command>enable</command> and
- is useful to reset the symlinks a unit is enabled with to
- the defaults configured in the <literal>[Install]</literal>
- section of the unit file.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>preset <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Reset one or more unit files, as specified on the
- command line, to the defaults configured in the preset
- policy files. This has the same effect as
- <command>disable</command> or <command>enable</command>,
- depending how the unit is listed in the preset files.</para>
-
- <para>Use <option>--preset-mode=</option> to control
- whether units shall be enabled and disabled, or only
- enabled, or only disabled.</para>
-
- <para>For more information on the preset policy format,
- see
- <citerefentry><refentrytitle>systemd.preset</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
- For more information on the concept of presets, please
- consult the <ulink
- url="http://freedesktop.org/wiki/Software/systemd/Preset">Preset</ulink>
- document.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><command>preset-all</command></term>
-
- <listitem>
- <para>Resets all installed unit files to the defaults
- configured in the preset policy file (see above).</para>
-
- <para>Use <option>--preset-mode=</option> to control
- whether units shall be enabled and disabled, or only
- enabled, or only disabled.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
<term><command>mask <replaceable>NAME</replaceable>...</command></term>
<listitem>
@@ -1140,25 +1139,6 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</varlistentry>
<varlistentry>
- <term><command>add-wants <replaceable>TARGET</replaceable>
- <replaceable>NAME</replaceable>...</command></term>
- <term><command>add-requires <replaceable>TARGET</replaceable>
- <replaceable>NAME</replaceable>...</command></term>
-
- <listitem>
- <para>Adds <literal>Wants=</literal> resp. <literal>Requires=</literal>
- dependency to the specified <replaceable>TARGET</replaceable> for
- one or more units. </para>
-
- <para>This command honors <option>--system</option>,
- <option>--user</option>, <option>--runtime</option> and
- <option>--global</option> in a similar way as
- <command>enable</command>.</para>
-
- </listitem>
- </varlistentry>
-
- <varlistentry>
<term><command>link <replaceable>FILENAME</replaceable>...</command></term>
<listitem>
@@ -1173,20 +1153,21 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</varlistentry>
<varlistentry>
- <term><command>get-default</command></term>
+ <term><command>add-wants <replaceable>TARGET</replaceable>
+ <replaceable>NAME</replaceable>...</command></term>
+ <term><command>add-requires <replaceable>TARGET</replaceable>
+ <replaceable>NAME</replaceable>...</command></term>
<listitem>
- <para>Get the default target specified
- via <filename>default.target</filename> link.</para>
- </listitem>
- </varlistentry>
+ <para>Adds <literal>Wants=</literal> resp. <literal>Requires=</literal>
+ dependency to the specified <replaceable>TARGET</replaceable> for
+ one or more units. </para>
- <varlistentry>
- <term><command>set-default <replaceable>NAME</replaceable></command></term>
+ <para>This command honors <option>--system</option>,
+ <option>--user</option>, <option>--runtime</option> and
+ <option>--global</option> in a similar way as
+ <command>enable</command>.</para>
- <listitem>
- <para>Set the default target to boot into. Command links
- <filename>default.target</filename> to the given unit.</para>
</listitem>
</varlistentry>
@@ -1226,6 +1207,27 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<filename>/run</filename>.</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><command>get-default</command></term>
+
+ <listitem>
+ <para>Return the default target to boot into. This returns
+ the target unit name <filename>default.target</filename>
+ is aliased (symlinked) to.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>set-default <replaceable>NAME</replaceable></command></term>
+
+ <listitem>
+ <para>Set the default target to boot into. This sets
+ (symlinks) the <filename>default.target</filename> alias
+ to the given target unit.</para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</refsect2>
@@ -1547,6 +1549,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<quote>firmware over the air</quote> update.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term><command>kexec</command></term>
@@ -1560,6 +1563,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
immediately followed by the reboot.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term><command>exit</command></term>
@@ -1569,8 +1573,29 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
with the <option>--user</option> option) and will fail
otherwise.</para>
</listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>switch-root <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></command></term>
+
+ <listitem>
+ <para>Switches to a different root directory and executes a
+ new system manager process below it. This is intended for
+ usage in initial RAM disks ("initrd"), and will transition
+ from the initrd's system manager process (a.k.a "init"
+ process) to the main system manager process. This call takes two
+ arguments: the directory that is to become the new root directory, and
+ the path to the new system manager binary below it to
+ execute as PID 1. If the latter is omitted or the empty
+ string, a systemd binary will automatically be searched for
+ and used as init. If the system manager path is omitted or
+ equal to the empty string, the state of the initrd's system
+ manager process is passed to the main system manager, which
+ allows later introspection of the state of the services
+ involved in the initrd boot.</para>
+ </listitem>
</varlistentry>
+
<varlistentry>
<term><command>suspend</command></term>
@@ -1580,6 +1605,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term><command>hibernate</command></term>
@@ -1589,6 +1615,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term><command>hybrid-sleep</command></term>
@@ -1598,26 +1625,6 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<filename>hybrid-sleep.target</filename> target.</para>
</listitem>
</varlistentry>
- <varlistentry>
- <term><command>switch-root <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></command></term>
-
- <listitem>
- <para>Switches to a different root directory and executes a
- new system manager process below it. This is intended for
- usage in initial RAM disks ("initrd"), and will transition
- from the initrd's system manager process (a.k.a "init"
- process) to the main system manager process. This call takes two
- arguments: the directory that is to become the new root directory, and
- the path to the new system manager binary below it to
- execute as PID 1. If the latter is omitted or the empty
- string, a systemd binary will automatically be searched for
- and used as init. If the system manager path is omitted or
- equal to the empty string, the state of the initrd's system
- manager process is passed to the main system manager, which
- allows later introspection of the state of the services
- involved in the initrd boot.</para>
- </listitem>
- </varlistentry>
</variablelist>
</refsect2>
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index ded4943..74528dd 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -6075,7 +6075,7 @@ static void systemctl_help(void) {
" based on preset configuration\n"
" preset-all Enable/disable all unit files based on\n"
" preset configuration\n"
- " is-enabled NAME... Check whether unit files are enabled\n\n"
+ " is-enabled NAME... Check whether unit files are enabled\n"
" mask NAME... Mask one or more units\n"
" unmask NAME... Unmask one or more units\n"
" link PATH... Link one or more units files into\n"
@@ -6084,10 +6084,9 @@ static void systemctl_help(void) {
" on specified one or more units\n"
" add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
" on specified one or more units\n"
- " get-default Get the name of the default target\n"
- " set-default NAME Set the default target\n"
" edit NAME... Edit one or more unit files\n"
- "\n"
+ " get-default Get the name of the default target\n"
+ " set-default NAME Set the default target\n\n"
"Machine Commands:\n"
" list-machines [PATTERN...] List local containers and host\n\n"
"Job Commands:\n"
commit 17cd091332040b9a3658db9374440fce7805ca54
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 18:07:25 2015 +0100
man: add the same command sections to the man page as the --help text shows
diff --git a/man/loginctl.xml b/man/loginctl.xml
index 5ff9f75..7a6cc15 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -193,10 +193,15 @@
<xi:include href="standard-options.xml" xpointer="version" />
<xi:include href="standard-options.xml" xpointer="no-pager" />
</variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Commands</title>
<para>The following commands are understood:</para>
- <variablelist>
+ <refsect2><title>Session Commands</title><variablelist>
+
<varlistentry>
<term><command>list-sessions</command></term>
@@ -291,7 +296,9 @@
<option>--signal=</option> to select
the signal to send.</para></listitem>
</varlistentry>
+ </variablelist></refsect2>
+ <refsect2><title>User Commands</title><variablelist>
<varlistentry>
<term><command>list-users</command></term>
@@ -371,7 +378,9 @@
<option>--signal=</option> to select
the signal to send.</para></listitem>
</varlistentry>
+ </variablelist></refsect2>
+ <refsect2><title>Seat Commands</title><variablelist>
<varlistentry>
<term><command>list-seats</command></term>
@@ -458,7 +467,7 @@
and deallocates all runtime resources
attached to them.</para></listitem>
</varlistentry>
- </variablelist>
+ </variablelist></refsect2>
</refsect1>
commit 079dac08c6a2725ce6e5ed2afa3f03d057c999c6
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 15:33:46 2015 +0100
systemctl,loginctl: start polkit agent for all polkit enabled operations
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index 57a0ab0..9f77903 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -50,8 +50,8 @@ static bool arg_legend = true;
static const char *arg_kill_who = NULL;
static int arg_signal = SIGTERM;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static bool arg_ask_password = true;
static char *arg_host = NULL;
+static bool arg_ask_password = true;
static unsigned arg_lines = 10;
static OutputMode arg_output = OUTPUT_SHORT;
@@ -827,6 +827,8 @@ static int activate(sd_bus *bus, char **args, unsigned n) {
assert(args);
+ polkit_agent_open_if_enabled();
+
for (i = 1; i < n; i++) {
r = sd_bus_call_method (
@@ -856,6 +858,8 @@ static int kill_session(sd_bus *bus, char **args, unsigned n) {
assert(args);
+ polkit_agent_open_if_enabled();
+
if (!arg_kill_who)
arg_kill_who = "all";
@@ -921,6 +925,8 @@ static int terminate_user(sd_bus *bus, char **args, unsigned n) {
assert(args);
+ polkit_agent_open_if_enabled();
+
for (i = 1; i < n; i++) {
uid_t uid;
@@ -952,6 +958,8 @@ static int kill_user(sd_bus *bus, char **args, unsigned n) {
assert(args);
+ polkit_agent_open_if_enabled();
+
if (!arg_kill_who)
arg_kill_who = "all";
@@ -1036,6 +1044,8 @@ static int lock_sessions(sd_bus *bus, char **args, unsigned n) {
assert(args);
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call_method (
bus,
"org.freedesktop.login1",
@@ -1057,6 +1067,8 @@ static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
assert(args);
+ polkit_agent_open_if_enabled();
+
for (i = 1; i < n; i++) {
r = sd_bus_call_method (
@@ -1077,6 +1089,7 @@ static int terminate_seat(sd_bus *bus, char **args, unsigned n) {
}
static void help(void) {
+
printf("%s [OPTIONS...] {COMMAND} ...\n\n"
"Send control commands to or query the login manager.\n\n"
" -h --help Show this help\n"
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 2c29f14..939b648 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -72,7 +72,6 @@ static OutputMode arg_output = OUTPUT_SHORT;
static void pager_open_if_enabled(void) {
- /* Cache result before we open the pager */
if (arg_no_pager)
return;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index b44c6d7..ded4943 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -176,7 +176,6 @@ static void ask_password_agent_open_if_enabled(void) {
ask_password_agent_open();
}
-#ifdef HAVE_LOGIND
static void polkit_agent_open_if_enabled(void) {
/* Open the polkit agent as a child process if necessary */
@@ -192,7 +191,6 @@ static void polkit_agent_open_if_enabled(void) {
polkit_agent_open();
}
-#endif
static OutputFlags get_output_flags(void) {
return
@@ -2706,6 +2704,7 @@ static int start_unit(sd_bus *bus, char **args) {
assert(bus);
ask_password_agent_open_if_enabled();
+ polkit_agent_open_if_enabled();
if (arg_action == ACTION_SYSTEMCTL) {
enum action action;
@@ -3029,6 +3028,8 @@ static int kill_unit(sd_bus *bus, char **args) {
assert(bus);
assert(args);
+ polkit_agent_open_if_enabled();
+
if (!arg_kill_who)
arg_kill_who = "all";
@@ -4601,6 +4602,8 @@ static int set_property(sd_bus *bus, char **args) {
char **i;
int r;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_message_new_method_call(
bus,
&m,
@@ -4661,6 +4664,8 @@ static int snapshot(sd_bus *bus, char **args) {
const char *path;
int r;
+ polkit_agent_open_if_enabled();
+
if (strv_length(args) > 1)
n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
else
@@ -4723,6 +4728,8 @@ static int delete_snapshot(sd_bus *bus, char **args) {
assert(args);
+ polkit_agent_open_if_enabled();
+
r = expand_names(bus, args + 1, ".snapshot", &names);
if (r < 0)
log_error_errno(r, "Failed to expand names: %m");
@@ -4766,6 +4773,8 @@ static int daemon_reload(sd_bus *bus, char **args) {
const char *method;
int r;
+ polkit_agent_open_if_enabled();
+
if (arg_action == ACTION_RELOAD)
method = "Reload";
else if (arg_action == ACTION_REEXEC)
@@ -4824,6 +4833,8 @@ static int reset_failed(sd_bus *bus, char **args) {
if (strv_length(args) <= 1)
return daemon_reload(bus, args);
+ polkit_agent_open_if_enabled();
+
r = expand_names(bus, args + 1, NULL, &names);
if (r < 0)
log_error_errno(r, "Failed to expand names: %m");
@@ -5285,6 +5296,8 @@ static int enable_unit(sd_bus *bus, char **args) {
bool send_force = true, send_preset_mode = false;
const char *method;
+ polkit_agent_open_if_enabled();
+
if (streq(verb, "enable")) {
method = "EnableUnitFiles";
expect_carries_install_info = true;
@@ -5430,6 +5443,8 @@ static int add_dependency(sd_bus *bus, char **args) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_message_new_method_call(
bus,
&m,
@@ -5493,6 +5508,8 @@ static int preset_all(sd_bus *bus, char **args) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_message_new_method_call(
bus,
&m,
commit acf97e213e69a97e63ab8f7fad7ecd53608c757a
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 15:23:54 2015 +0100
machinectl: given that machinectl invokes a number of polkit enabled methods, start the polkit agent on terminals
diff --git a/man/machinectl.xml b/man/machinectl.xml
index baa0e17..ebe8e3b 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -109,6 +109,14 @@
</varlistentry>
<varlistentry>
+ <term><option>--no-ask-password</option></term>
+
+ <listitem><para>Do not query the user
+ for authentication for privileged
+ operations.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--kill-who=</option></term>
<listitem><para>When used with
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 6180de1..2c29f14 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -38,6 +38,7 @@
#include "util.h"
#include "macro.h"
#include "pager.h"
+#include "spawn-polkit-agent.h"
#include "bus-util.h"
#include "bus-error.h"
#include "build.h"
@@ -65,6 +66,7 @@ static char *arg_host = NULL;
static bool arg_read_only = false;
static bool arg_mkdir = false;
static bool arg_quiet = false;
+static bool arg_ask_password = true;
static unsigned arg_lines = 10;
static OutputMode arg_output = OUTPUT_SHORT;
@@ -77,6 +79,19 @@ static void pager_open_if_enabled(void) {
pager_open(false);
}
+static void polkit_agent_open_if_enabled(void) {
+
+ /* Open the polkit agent as a child process if necessary */
+
+ if (!arg_ask_password)
+ return;
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return;
+
+ polkit_agent_open();
+}
+
static OutputFlags get_output_flags(void) {
return
arg_all * OUTPUT_SHOW_ALL |
@@ -911,6 +926,8 @@ static int kill_machine(int argc, char *argv[], void *userdata) {
assert(bus);
+ polkit_agent_open_if_enabled();
+
if (!arg_kill_who)
arg_kill_who = "all";
@@ -956,6 +973,8 @@ static int terminate_machine(int argc, char *argv[], void *userdata) {
assert(bus);
+ polkit_agent_open_if_enabled();
+
for (i = 1; i < argc; i++) {
int r;
@@ -1345,6 +1364,8 @@ static int login_machine(int argc, char *argv[], void *userdata) {
return -ENOTSUP;
}
+ polkit_agent_open_if_enabled();
+
r = sd_event_default(&event);
if (r < 0)
return log_error_errno(r, "Failed to get event loop: %m");
@@ -1375,7 +1396,7 @@ static int login_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- r = sd_bus_message_set_allow_interactive_authorization(m, true);
+ r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
@@ -1434,6 +1455,8 @@ static int remove_image(int argc, char *argv[], void *userdata) {
assert(bus);
+ polkit_agent_open_if_enabled();
+
for (i = 1; i < argc; i++) {
r = sd_bus_call_method(
bus,
@@ -1458,6 +1481,8 @@ static int rename_image(int argc, char *argv[], void *userdata) {
sd_bus *bus = userdata;
int r;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
@@ -1480,6 +1505,8 @@ static int clone_image(int argc, char *argv[], void *userdata) {
sd_bus *bus = userdata;
int r;
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
@@ -1510,6 +1537,8 @@ static int read_only_image(int argc, char *argv[], void *userdata) {
}
}
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call_method(
bus,
"org.freedesktop.machine1",
@@ -1535,6 +1564,8 @@ static int start_machine(int argc, char *argv[], void *userdata) {
assert(bus);
+ polkit_agent_open_if_enabled();
+
r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_oom();
@@ -1567,7 +1598,7 @@ static int start_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- r = sd_bus_message_set_allow_interactive_authorization(m, true);
+ r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
@@ -1607,6 +1638,8 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
assert(bus);
+ polkit_agent_open_if_enabled();
+
method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles";
r = sd_bus_message_new_method_call(
@@ -1619,7 +1652,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- r = sd_bus_message_set_allow_interactive_authorization(m, true);
+ r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
@@ -1687,7 +1720,7 @@ static int enable_machine(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_create_error(r);
- r = sd_bus_message_set_allow_interactive_authorization(m, true);
+ r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
if (r < 0)
return bus_log_create_error(r);
@@ -1709,6 +1742,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not show the headers and footers\n"
+ " --no-ask-password Do not ask for system passwords\n"
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
" -p --property=NAME Show only properties by this name\n"
@@ -1760,6 +1794,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_KILL_WHO,
ARG_READ_ONLY,
ARG_MKDIR,
+ ARG_NO_ASK_PASSWORD,
};
static const struct option options[] = {
@@ -1779,6 +1814,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "quiet", no_argument, NULL, 'q' },
{ "lines", required_argument, NULL, 'n' },
{ "output", required_argument, NULL, 'o' },
+ { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{}
};
@@ -1853,6 +1889,10 @@ static int parse_argv(int argc, char *argv[]) {
}
break;
+ case ARG_NO_ASK_PASSWORD:
+ arg_ask_password = false;
+ break;
+
case 'H':
arg_transport = BUS_TRANSPORT_REMOTE;
arg_host = optarg;
@@ -1938,6 +1978,7 @@ int main(int argc, char*argv[]) {
finish:
pager_close();
+ polkit_agent_close();
strv_free(arg_property);
commit 8b0cc9a36c8f92f010f2e8465942d2cd7c580d78
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 15:09:12 2015 +0100
machinectl: show most recent log output in "machinectl status", too
diff --git a/Makefile.am b/Makefile.am
index 420a567..e024748 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5078,6 +5078,8 @@ machinectl_SOURCES = \
machinectl_LDADD = \
libsystemd-internal.la \
+ libsystemd-logs.la \
+ libsystemd-journal-internal.la \
libsystemd-shared.la
rootbin_PROGRAMS += \
diff --git a/man/machinectl.xml b/man/machinectl.xml
index eef1740..baa0e17 100644
--- a/man/machinectl.xml
+++ b/man/machinectl.xml
@@ -165,6 +165,34 @@
mount.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><option>-n</option></term>
+ <term><option>--lines=</option></term>
+
+ <listitem><para>When used with
+ <command>status</command>, controls
+ the number of journal lines to show,
+ counting from the most recent
+ ones. Takes a positive integer
+ argument. Defaults to 10.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o</option></term>
+ <term><option>--output=</option></term>
+
+ <listitem><para>When used with
+ <command>status</command>, controls
+ the formatting of the journal entries
+ that are shown. For the available
+ choices, see
+ <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ Defaults to
+ <literal>short</literal>.</para></listitem>
+ </varlistentry>
+
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />
@@ -189,12 +217,19 @@
<listitem><para>Show terse runtime
status information about one or more
- virtual machines and containers. This
- function is intended to generate
- human-readable output. If you are
- looking for computer-parsable output,
- use <command>show</command> instead.
- </para></listitem>
+ virtual machines and containers,
+ followed by the most recent log data
+ from the journal. This function is
+ intended to generate human-readable
+ output. If you are looking for
+ computer-parsable output, use
+ <command>show</command> instead. Note
+ that the log data shown is reported by
+ the virtual machine or container
+ manager, and frequently contains
+ console output of the machine, but not
+ necessarily journal contents of the
+ machine itself.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index c80114c..6180de1 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -44,6 +44,7 @@
#include "strv.h"
#include "unit-name.h"
#include "cgroup-show.h"
+#include "logs-show.h"
#include "cgroup-util.h"
#include "ptyfwd.h"
#include "event-util.h"
@@ -64,6 +65,8 @@ static char *arg_host = NULL;
static bool arg_read_only = false;
static bool arg_mkdir = false;
static bool arg_quiet = false;
+static unsigned arg_lines = 10;
+static OutputMode arg_output = OUTPUT_SHORT;
static void pager_open_if_enabled(void) {
@@ -74,6 +77,15 @@ static void pager_open_if_enabled(void) {
pager_open(false);
}
+static OutputFlags get_output_flags(void) {
+ return
+ arg_all * OUTPUT_SHOW_ALL |
+ arg_full * OUTPUT_FULL_WIDTH |
+ (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+ on_tty() * OUTPUT_COLOR |
+ !arg_quiet * OUTPUT_WARN_CUTOFF;
+}
+
typedef struct MachineInfo {
const char *name;
const char *class;
@@ -305,7 +317,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *path = NULL;
const char *cgroup;
- int r, output_flags;
+ int r;
unsigned c;
assert(bus);
@@ -342,17 +354,13 @@ static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) {
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
return 0;
- output_flags =
- arg_all * OUTPUT_SHOW_ALL |
- arg_full * OUTPUT_FULL_WIDTH;
-
c = columns();
if (c > 18)
c -= 18;
else
c = 0;
- show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
return 0;
}
@@ -467,7 +475,7 @@ typedef struct MachineStatusInfo {
char *unit;
char *root_directory;
pid_t leader;
- usec_t timestamp;
+ struct dual_timestamp timestamp;
int *netif;
unsigned n_netif;
} MachineStatusInfo;
@@ -487,8 +495,8 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
else
putchar('\n');
- s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp);
- s2 = format_timestamp(since2, sizeof(since2), i->timestamp);
+ s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp.realtime);
+ s2 = format_timestamp(since2, sizeof(since2), i->timestamp.realtime);
if (s1)
printf("\t Since: %s; %s\n", s2, s1);
@@ -552,6 +560,22 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) {
if (i->unit) {
printf("\t Unit: %s\n", i->unit);
show_unit_cgroup(bus, i->unit, i->leader);
+
+ if (arg_transport == BUS_TRANSPORT_LOCAL) {
+
+ show_journal_by_unit(
+ stdout,
+ i->unit,
+ arg_output,
+ 0,
+ i->timestamp.monotonic,
+ arg_lines,
+ 0,
+ get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+ SD_JOURNAL_LOCAL_ONLY,
+ true,
+ NULL);
+ }
}
}
@@ -579,15 +603,16 @@ static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_
static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) {
static const struct bus_properties_map map[] = {
- { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
- { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
- { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
- { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
- { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
- { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
- { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp) },
- { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
- { "NetworkInterfaces", "ai", map_netif, 0 },
+ { "Name", "s", NULL, offsetof(MachineStatusInfo, name) },
+ { "Class", "s", NULL, offsetof(MachineStatusInfo, class) },
+ { "Service", "s", NULL, offsetof(MachineStatusInfo, service) },
+ { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) },
+ { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) },
+ { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) },
+ { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp.realtime) },
+ { "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) },
+ { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) },
+ { "NetworkInterfaces", "ai", map_netif, 0 },
{}
};
@@ -1693,7 +1718,11 @@ static int help(int argc, char *argv[], void *userdata) {
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
" --read-only Create read-only bind mount\n"
- " --mkdir Create directory before bind mounting, if missing\n\n"
+ " --mkdir Create directory before bind mounting, if missing\n"
+ " -n --lines=INTEGER Number of journal entries to show\n"
+ " -o --output=STRING Change journal output mode (short,\n"
+ " short-monotonic, verbose, export, json,\n"
+ " json-pretty, json-sse, cat)\n\n"
"Machine Commands:\n"
" list List running VMs and containers\n"
" status NAME... Show VM/container details\n"
@@ -1748,6 +1777,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
{ "mkdir", no_argument, NULL, ARG_MKDIR },
{ "quiet", no_argument, NULL, 'q' },
+ { "lines", required_argument, NULL, 'n' },
+ { "output", required_argument, NULL, 'o' },
{}
};
@@ -1756,7 +1787,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hp:als:H:M:q", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hp:als:H:M:qn:o:", options, NULL)) >= 0)
switch (c) {
@@ -1787,6 +1818,21 @@ static int parse_argv(int argc, char *argv[]) {
arg_full = true;
break;
+ case 'n':
+ if (safe_atou(optarg, &arg_lines) < 0) {
+ log_error("Failed to parse lines '%s'", optarg);
+ return -EINVAL;
+ }
+ break;
+
+ case 'o':
+ arg_output = output_mode_from_string(optarg);
+ if (arg_output < 0) {
+ log_error("Unknown output '%s'.", optarg);
+ return -EINVAL;
+ }
+ break;
+
case ARG_NO_PAGER:
arg_no_pager = true;
break;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 20c765e..b44c6d7 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -197,10 +197,10 @@ static void polkit_agent_open_if_enabled(void) {
static OutputFlags get_output_flags(void) {
return
arg_all * OUTPUT_SHOW_ALL |
+ arg_full * OUTPUT_FULL_WIDTH |
(!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
on_tty() * OUTPUT_COLOR |
- !arg_quiet * OUTPUT_WARN_CUTOFF |
- arg_full * OUTPUT_FULL_WIDTH;
+ !arg_quiet * OUTPUT_WARN_CUTOFF;
}
static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
commit 3c7560019e623e6e0d03a860b4f19a3a8715feca
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jan 8 14:38:52 2015 +0100
loginctl: show the 10 most recent log user/session log lines in "loginctl user-status" and "loginctl session-status"
diff --git a/Makefile.am b/Makefile.am
index 483feb3..420a567 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5539,6 +5539,8 @@ loginctl_SOURCES = \
loginctl_LDADD = \
libsystemd-internal.la \
+ libsystemd-logs.la \
+ libsystemd-journal-internal.la \
libudev-internal.la \
libsystemd-shared.la
diff --git a/man/loginctl.xml b/man/loginctl.xml
index 749db92..5ff9f75 100644
--- a/man/loginctl.xml
+++ b/man/loginctl.xml
@@ -157,6 +157,35 @@
<constant>SIGTERM</constant>.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>-n</option></term>
+ <term><option>--lines=</option></term>
+
+ <listitem><para>When used with
+ <command>user-status</command> and
+ <command>session-status</command>,
+ controls the number of journal lines
+ to show, counting from the most recent
+ ones. Takes a positive integer
+ argument. Defaults to 10.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>-o</option></term>
+ <term><option>--output=</option></term>
+
+ <listitem><para>When used with
+ <command>user-status</command> and
+ <command>session-status</command>,
+ controls the formatting of the journal
+ entries that are shown. For the
+ available choices, see
+ <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ Defaults to
+ <literal>short</literal>.</para></listitem>
+ </varlistentry>
+
<xi:include href="user-system-options.xml" xpointer="host" />
<xi:include href="user-system-options.xml" xpointer="machine" />
@@ -179,11 +208,12 @@
<listitem><para>Show terse runtime
status information about one or more
- sessions. This function is intended to
- generate human-readable output. If you
- are looking for computer-parsable
- output, use
- <command>show-session</command>
+ sessions, followed by the most recent
+ log data from the journal. This
+ function is intended to generate
+ human-readable output. If you are
+ looking for computer-parsable output,
+ use <command>show-session</command>
instead.</para></listitem>
</varlistentry>
@@ -274,13 +304,14 @@
<listitem><para>Show terse runtime
status information about one or more
- logged in users. This function is
- intended to generate human-readable
- output. If you are looking for
- computer-parsable output, use
- <command>show-user</command> instead.
- Users may be specified by their
- usernames or numeric user IDs.
+ logged in users, followed by the most
+ recent log data from the journal. This
+ function is intended to generate
+ human-readable output. If you are
+ looking for computer-parsable output,
+ use <command>show-user</command>
+ instead. Users may be specified by
+ their usernames or numeric user IDs.
</para></listitem>
</varlistentry>
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index cc27544..57a0ab0 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -37,6 +37,7 @@
#include "strv.h"
#include "unit-name.h"
#include "sysfs-show.h"
+#include "logs-show.h"
#include "cgroup-show.h"
#include "cgroup-util.h"
#include "spawn-polkit-agent.h"
@@ -51,6 +52,8 @@ static int arg_signal = SIGTERM;
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
static bool arg_ask_password = true;
static char *arg_host = NULL;
+static unsigned arg_lines = 10;
+static OutputMode arg_output = OUTPUT_SHORT;
static void pager_open_if_enabled(void) {
@@ -73,6 +76,15 @@ static void polkit_agent_open_if_enabled(void) {
polkit_agent_open();
}
+static OutputFlags get_output_flags(void) {
+
+ return
+ arg_all * OUTPUT_SHOW_ALL |
+ arg_full * OUTPUT_FULL_WIDTH |
+ (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+ on_tty() * OUTPUT_COLOR;
+}
+
static int list_sessions(sd_bus *bus, char **args, unsigned n) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
@@ -206,7 +218,7 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_free_ char *path = NULL;
const char *cgroup;
- int r, output_flags;
+ int r;
unsigned c;
assert(bus);
@@ -239,17 +251,13 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit
if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup, false) != 0 && leader <= 0)
return 0;
- output_flags =
- arg_all * OUTPUT_SHOW_ALL |
- arg_full * OUTPUT_FULL_WIDTH;
-
c = columns();
if (c > 18)
c -= 18;
else
c = 0;
- show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, output_flags);
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags());
return 0;
}
@@ -257,7 +265,7 @@ typedef struct SessionStatusInfo {
const char *id;
uid_t uid;
const char *name;
- usec_t timestamp;
+ struct dual_timestamp timestamp;
unsigned int vtnr;
const char *seat;
const char *tty;
@@ -277,7 +285,7 @@ typedef struct SessionStatusInfo {
typedef struct UserStatusInfo {
uid_t uid;
const char *name;
- usec_t timestamp;
+ struct dual_timestamp timestamp;
const char *state;
char **sessions;
const char *display;
@@ -357,24 +365,25 @@ static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_messag
static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) {
static const struct bus_properties_map map[] = {
- { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
- { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
- { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
- { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
- { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
- { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
- { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
- { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
- { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
- { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
- { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
- { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
- { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
- { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
- { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
- { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp) },
- { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
- { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
+ { "Id", "s", NULL, offsetof(SessionStatusInfo, id) },
+ { "Name", "s", NULL, offsetof(SessionStatusInfo, name) },
+ { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) },
+ { "Display", "s", NULL, offsetof(SessionStatusInfo, display) },
+ { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) },
+ { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) },
+ { "Service", "s", NULL, offsetof(SessionStatusInfo, service) },
+ { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) },
+ { "Type", "s", NULL, offsetof(SessionStatusInfo, type) },
+ { "Class", "s", NULL, offsetof(SessionStatusInfo, class) },
+ { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) },
+ { "State", "s", NULL, offsetof(SessionStatusInfo, state) },
+ { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) },
+ { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) },
+ { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) },
+ { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) },
+ { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) },
+ { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) },
+ { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) },
{}
};
@@ -399,8 +408,8 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
else
printf("%u\n", (unsigned) i.uid);
- s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp);
- s2 = format_timestamp(since2, sizeof(since2), i.timestamp);
+ s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
+ s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
if (s1)
printf("\t Since: %s; %s\n", s2, s1);
@@ -471,6 +480,22 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
if (i.scope) {
printf("\t Unit: %s\n", i.scope);
show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader);
+
+ if (arg_transport == BUS_TRANSPORT_LOCAL) {
+
+ show_journal_by_unit(
+ stdout,
+ i.scope,
+ arg_output,
+ 0,
+ i.timestamp.monotonic,
+ arg_lines,
+ 0,
+ get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+ SD_JOURNAL_LOCAL_ONLY,
+ true,
+ NULL);
+ }
}
return 0;
@@ -479,13 +504,14 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li
static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) {
static const struct bus_properties_map map[] = {
- { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
- { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
- { "State", "s", NULL, offsetof(UserStatusInfo, state) },
- { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
- { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp) },
- { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
- { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
+ { "Name", "s", NULL, offsetof(UserStatusInfo, name) },
+ { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) },
+ { "State", "s", NULL, offsetof(UserStatusInfo, state) },
+ { "UID", "u", NULL, offsetof(UserStatusInfo, uid) },
+ { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) },
+ { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) },
+ { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) },
+ { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) },
{}
};
@@ -510,8 +536,8 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
else
printf("%u\n", (unsigned) i.uid);
- s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp);
- s2 = format_timestamp(since2, sizeof(since2), i.timestamp);
+ s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime);
+ s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime);
if (s1)
printf("\t Since: %s; %s\n", s2, s1);
@@ -538,6 +564,19 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line)
if (i.slice) {
printf("\t Unit: %s\n", i.slice);
show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0);
+
+ show_journal_by_unit(
+ stdout,
+ i.slice,
+ arg_output,
+ 0,
+ i.timestamp.monotonic,
+ arg_lines,
+ 0,
+ get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+ SD_JOURNAL_LOCAL_ONLY,
+ true,
+ NULL);
}
finish:
@@ -1051,7 +1090,10 @@ static void help(void) {
" -a --all Show all properties, including empty ones\n"
" -l --full Do not ellipsize output\n"
" --kill-who=WHO Who to send signal to\n"
- " -s --signal=SIGNAL Which signal to send\n\n"
+ " -s --signal=SIGNAL Which signal to send\n"
+ " -n --lines=INTEGER Number of journal entries to show\n"
+ " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
+ " verbose, export, json, json-pretty, json-sse, cat)\n\n"
"Session Commands:\n"
" list-sessions List sessions\n"
" session-status ID... Show session status\n"
@@ -1104,6 +1146,8 @@ static int parse_argv(int argc, char *argv[]) {
{ "host", required_argument, NULL, 'H' },
{ "machine", required_argument, NULL, 'M' },
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
+ { "lines", required_argument, NULL, 'n' },
+ { "output", required_argument, NULL, 'o' },
{}
};
@@ -1112,7 +1156,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hp:als:H:M:", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0)
switch (c) {
@@ -1145,6 +1189,21 @@ static int parse_argv(int argc, char *argv[]) {
arg_full = true;
break;
+ case 'n':
+ if (safe_atou(optarg, &arg_lines) < 0) {
+ log_error("Failed to parse lines '%s'", optarg);
+ return -EINVAL;
+ }
+ break;
+
+ case 'o':
+ arg_output = output_mode_from_string(optarg);
+ if (arg_output < 0) {
+ log_error("Unknown output '%s'.", optarg);
+ return -EINVAL;
+ }
+ break;
+
case ARG_NO_PAGER:
arg_no_pager = true;
break;
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index dff0d30..b7a99d2 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -1234,12 +1234,12 @@ int show_journal_by_unit(
unsigned how_many,
uid_t uid,
OutputFlags flags,
- bool system,
+ int journal_open_flags,
+ bool system_unit,
bool *ellipsized) {
_cleanup_journal_close_ sd_journal*j = NULL;
int r;
- int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
assert(mode >= 0);
assert(mode < _OUTPUT_MODE_MAX);
@@ -1248,7 +1248,7 @@ int show_journal_by_unit(
if (how_many <= 0)
return 0;
- r = sd_journal_open(&j, jflags);
+ r = sd_journal_open(&j, journal_open_flags);
if (r < 0)
return r;
@@ -1256,7 +1256,7 @@ int show_journal_by_unit(
if (r < 0)
return r;
- if (system)
+ if (system_unit)
r = add_matches_for_unit(j, unit);
else
r = add_matches_for_user_unit(j, unit, uid);
diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h
index 187ee59..8d9641e 100644
--- a/src/shared/logs-show.h
+++ b/src/shared/logs-show.h
@@ -25,7 +25,7 @@
#include <unistd.h>
#include <sys/types.h>
-#include "systemd/sd-journal.h"
+#include "sd-journal.h"
#include "util.h"
#include "output-mode.h"
@@ -58,7 +58,8 @@ int show_journal_by_unit(
unsigned how_many,
uid_t uid,
OutputFlags flags,
- bool system,
+ int journal_open_flags,
+ bool system_unit,
bool *ellipsized);
void json_escape(
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 86b5ae0..20c765e 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -194,6 +194,15 @@ static void polkit_agent_open_if_enabled(void) {
}
#endif
+static OutputFlags get_output_flags(void) {
+ return
+ arg_all * OUTPUT_SHOW_ALL |
+ (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
+ on_tty() * OUTPUT_COLOR |
+ !arg_quiet * OUTPUT_WARN_CUTOFF |
+ arg_full * OUTPUT_FULL_WIDTH;
+}
+
static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
assert(error);
@@ -3224,12 +3233,6 @@ static void print_status_info(
char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
const char *path;
- int flags =
- arg_all * OUTPUT_SHOW_ALL |
- (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR |
- !arg_quiet * OUTPUT_WARN_CUTOFF |
- arg_full * OUTPUT_FULL_WIDTH;
char **t, **t2;
assert(i);
@@ -3499,21 +3502,23 @@ static void print_status_info(
if (i->control_pid > 0)
extra[k++] = i->control_pid;
- show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
+ show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags());
}
}
if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
- show_journal_by_unit(stdout,
- i->id,
- arg_output,
- 0,
- i->inactive_exit_timestamp_monotonic,
- arg_lines,
- getuid(),
- flags | OUTPUT_BEGIN_NEWLINE,
- arg_scope == UNIT_FILE_SYSTEM,
- ellipsized);
+ show_journal_by_unit(
+ stdout,
+ i->id,
+ arg_output,
+ 0,
+ i->inactive_exit_timestamp_monotonic,
+ arg_lines,
+ getuid(),
+ get_output_flags() | OUTPUT_BEGIN_NEWLINE,
+ SD_JOURNAL_LOCAL_ONLY,
+ arg_scope == UNIT_FILE_SYSTEM,
+ ellipsized);
}
if (i->need_daemon_reload)
@@ -4377,13 +4382,6 @@ static int show_system_status(sd_bus *bus) {
printf(" CGroup: %s\n", mi.control_group ?: "/");
if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
- int flags =
- arg_all * OUTPUT_SHOW_ALL |
- (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
- on_tty() * OUTPUT_COLOR |
- !arg_quiet * OUTPUT_WARN_CUTOFF |
- arg_full * OUTPUT_FULL_WIDTH;
-
static const char prefix[] = " ";
unsigned c;
@@ -4393,7 +4391,7 @@ static int show_system_status(sd_bus *bus) {
else
c = 0;
- show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
+ show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
}
free(mi.state);
More information about the systemd-commits
mailing list