mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
systemctl: add commands set-default and get-default
systemctl set-default NAME links the default.target to the given unit, get-default prints out the path to the currently set default target.
This commit is contained in:
parent
9749cd77bc
commit
99504dd4c1
@ -997,6 +997,24 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>get-default</command></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Get the default target specified
|
||||||
|
via <filename>default.target</filename> link.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><command>set-default <replaceable>NAME</replaceable></command></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Set the default target to boot into. Command links
|
||||||
|
<filename>default.target</filename> to the given unit.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><command>load <replaceable>NAME</replaceable>...</command></term>
|
<term><command>load <replaceable>NAME</replaceable>...</command></term>
|
||||||
|
|
||||||
|
@ -134,9 +134,10 @@ _systemctl () {
|
|||||||
[STANDALONE]='daemon-reexec daemon-reload default dump
|
[STANDALONE]='daemon-reexec daemon-reload default dump
|
||||||
emergency exit halt hibernate hybrid-sleep kexec list-jobs
|
emergency exit halt hibernate hybrid-sleep kexec list-jobs
|
||||||
list-units list-unit-files poweroff reboot rescue
|
list-units list-unit-files poweroff reboot rescue
|
||||||
show-environment suspend'
|
show-environment suspend get-default'
|
||||||
[NAME]='snapshot load'
|
[NAME]='snapshot load'
|
||||||
[FILE]='link'
|
[FILE]='link'
|
||||||
|
[TARGETS]='set-default'
|
||||||
)
|
)
|
||||||
|
|
||||||
for ((i=0; $i <= $COMP_CWORD; i++)); do
|
for ((i=0; $i <= $COMP_CWORD; i++)); do
|
||||||
@ -210,6 +211,9 @@ _systemctl () {
|
|||||||
elif __contains_word "$verb" ${VERBS[FILE]}; then
|
elif __contains_word "$verb" ${VERBS[FILE]}; then
|
||||||
comps=$( compgen -A file -- "$cur" )
|
comps=$( compgen -A file -- "$cur" )
|
||||||
compopt -o filenames
|
compopt -o filenames
|
||||||
|
elif __contains_word "$verb" ${VERBS[TARGETS]}; then
|
||||||
|
comps=$( __systemctl $mode list-unit-files --type target --full --all \
|
||||||
|
| { while read -r a b; do echo " $a"; done; } )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||||
|
@ -227,6 +227,13 @@
|
|||||||
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
|
||||||
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
||||||
|
" </method>\n" \
|
||||||
|
" <method name=\"SetDefaultTarget\">\n" \
|
||||||
|
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
|
||||||
|
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
|
||||||
|
" </method>\n" \
|
||||||
|
" <method name=\"GetDefaultTarget\">\n" \
|
||||||
|
" <arg name=\"name\" type=\"s\" direction=\"out\"/>\n" \
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
|
|
||||||
#define BUS_MANAGER_INTERFACE_SIGNALS \
|
#define BUS_MANAGER_INTERFACE_SIGNALS \
|
||||||
@ -1728,7 +1735,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
|||||||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
|
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
|
||||||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
|
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
|
||||||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
|
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
|
||||||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
|
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles") ||
|
||||||
|
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetDefaultTarget")) {
|
||||||
|
|
||||||
char **l = NULL;
|
char **l = NULL;
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
@ -1771,6 +1779,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
|||||||
carries_install_info = r;
|
carries_install_info = r;
|
||||||
} else if (streq(member, "MaskUnitFiles"))
|
} else if (streq(member, "MaskUnitFiles"))
|
||||||
r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
|
r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
|
||||||
|
else if (streq(member, "SetDefaultTarget"))
|
||||||
|
r = unit_file_set_default(scope, NULL, l[0], &changes, &n_changes);
|
||||||
else
|
else
|
||||||
assert_not_reached("Uh? Wrong method");
|
assert_not_reached("Uh? Wrong method");
|
||||||
|
|
||||||
@ -1838,6 +1848,22 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
|||||||
if (!reply)
|
if (!reply)
|
||||||
goto oom;
|
goto oom;
|
||||||
|
|
||||||
|
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetDefaultTarget")) {
|
||||||
|
UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
|
||||||
|
_cleanup_free_ char *default_target = NULL;
|
||||||
|
|
||||||
|
reply = dbus_message_new_method_return(message);
|
||||||
|
if (!reply)
|
||||||
|
goto oom;
|
||||||
|
|
||||||
|
r = unit_file_get_default(scope, NULL, &default_target);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
return bus_send_error_reply(connection, message, NULL, r);
|
||||||
|
|
||||||
|
if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_target, DBUS_TYPE_INVALID)) {
|
||||||
|
goto oom;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const BusBoundProperties bps[] = {
|
const BusBoundProperties bps[] = {
|
||||||
{ "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
|
{ "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
|
||||||
|
@ -86,6 +86,10 @@
|
|||||||
send_interface="org.freedesktop.systemd1.Manager"
|
send_interface="org.freedesktop.systemd1.Manager"
|
||||||
send_member="Dump"/>
|
send_member="Dump"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.systemd1"
|
||||||
|
send_interface="org.freedesktop.systemd1.Manager"
|
||||||
|
send_member="GetDefaultTarget"/>
|
||||||
|
|
||||||
<allow receive_sender="org.freedesktop.systemd1"/>
|
<allow receive_sender="org.freedesktop.systemd1"/>
|
||||||
</policy>
|
</policy>
|
||||||
|
|
||||||
|
@ -1570,6 +1570,92 @@ int unit_file_reenable(
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int unit_file_set_default(
|
||||||
|
UnitFileScope scope,
|
||||||
|
const char *root_dir,
|
||||||
|
char *file,
|
||||||
|
UnitFileChange **changes,
|
||||||
|
unsigned *n_changes) {
|
||||||
|
|
||||||
|
_cleanup_lookup_paths_free_ LookupPaths paths = {};
|
||||||
|
_cleanup_install_context_done_ InstallContext c = {};
|
||||||
|
_cleanup_free_ char *config_path = NULL;
|
||||||
|
char *path;
|
||||||
|
int r;
|
||||||
|
InstallInfo *i = NULL;
|
||||||
|
|
||||||
|
assert(scope >= 0);
|
||||||
|
assert(scope < _UNIT_FILE_SCOPE_MAX);
|
||||||
|
|
||||||
|
if (unit_name_to_type(file) != UNIT_TARGET)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
r = lookup_paths_init_from_scope(&paths, scope);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = get_config_path(scope, false, root_dir, &config_path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = install_info_add_auto(&c, file);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
i = (InstallInfo*)hashmap_first(c.will_install);
|
||||||
|
|
||||||
|
r = unit_file_search(&c, i, &paths, root_dir, false);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
path = strappenda(config_path, "/default.target");
|
||||||
|
r = create_symlink(i->path, path, true, changes, n_changes);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unit_file_get_default(
|
||||||
|
UnitFileScope scope,
|
||||||
|
const char *root_dir,
|
||||||
|
char **name) {
|
||||||
|
|
||||||
|
_cleanup_lookup_paths_free_ LookupPaths paths = {};
|
||||||
|
char **p;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = lookup_paths_init_from_scope(&paths, scope);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
STRV_FOREACH(p, paths.unit_path) {
|
||||||
|
_cleanup_free_ char *path = NULL, *tmp = NULL;
|
||||||
|
|
||||||
|
if (isempty(root_dir))
|
||||||
|
path = strappend(*p, "/default.target");
|
||||||
|
else
|
||||||
|
path = strjoin(root_dir, "/", *p, "/default.target", NULL);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = readlink_malloc(path, &tmp);
|
||||||
|
if (r == -ENOENT)
|
||||||
|
continue;
|
||||||
|
else if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
*name = strdup(path_get_file_name(tmp));
|
||||||
|
if (!*name)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
UnitFileState unit_file_get_state(
|
UnitFileState unit_file_get_state(
|
||||||
UnitFileScope scope,
|
UnitFileScope scope,
|
||||||
const char *root_dir,
|
const char *root_dir,
|
||||||
|
@ -80,6 +80,8 @@ int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char
|
|||||||
int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
|
int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
|
||||||
int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
|
int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
|
||||||
int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
|
int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
|
||||||
|
int unit_file_set_default(UnitFileScope scope, const char *root_dir, char *file, UnitFileChange **changes, unsigned *n_changes);
|
||||||
|
int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
|
||||||
|
|
||||||
UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);
|
UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);
|
||||||
|
|
||||||
|
@ -1177,6 +1177,59 @@ static int list_dependencies(DBusConnection *bus, char **args) {
|
|||||||
return list_dependencies_one(bus, u, 0, &units, 0);
|
return list_dependencies_one(bus, u, 0, &units, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_default(DBusConnection *bus, char **args) {
|
||||||
|
char *path = NULL;
|
||||||
|
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
|
||||||
|
int r;
|
||||||
|
_cleanup_dbus_error_free_ DBusError error;
|
||||||
|
|
||||||
|
dbus_error_init(&error);
|
||||||
|
|
||||||
|
if (!bus || avoid_bus()) {
|
||||||
|
r = unit_file_get_default(arg_scope, arg_root, &path);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
log_error("Operation failed: %s", strerror(-r));
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
} else {
|
||||||
|
r = bus_method_call_with_reply(
|
||||||
|
bus,
|
||||||
|
"org.freedesktop.systemd1",
|
||||||
|
"/org/freedesktop/systemd1",
|
||||||
|
"org.freedesktop.systemd1.Manager",
|
||||||
|
"GetDefaultTarget",
|
||||||
|
&reply,
|
||||||
|
NULL,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
log_error("Operation failed: %s", strerror(-r));
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dbus_message_get_args(reply, &error,
|
||||||
|
DBUS_TYPE_STRING, &path,
|
||||||
|
DBUS_TYPE_INVALID)) {
|
||||||
|
log_error("Failed to parse reply: %s", bus_error_message(&error));
|
||||||
|
dbus_error_free(&error);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
printf("%s\n", path);
|
||||||
|
|
||||||
|
finish:
|
||||||
|
if ((!bus || avoid_bus()) && path)
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct job_info {
|
struct job_info {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
char *name, *type, *state;
|
char *name, *type, *state;
|
||||||
@ -4243,6 +4296,8 @@ static int enable_unit(DBusConnection *bus, char **args) {
|
|||||||
r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
|
r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
|
||||||
else if (streq(verb, "unmask"))
|
else if (streq(verb, "unmask"))
|
||||||
r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
|
r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
|
||||||
|
else if (streq(verb, "set-default"))
|
||||||
|
r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
|
||||||
else
|
else
|
||||||
assert_not_reached("Unknown verb");
|
assert_not_reached("Unknown verb");
|
||||||
|
|
||||||
@ -4286,6 +4341,8 @@ static int enable_unit(DBusConnection *bus, char **args) {
|
|||||||
else if (streq(verb, "unmask")) {
|
else if (streq(verb, "unmask")) {
|
||||||
method = "UnmaskUnitFiles";
|
method = "UnmaskUnitFiles";
|
||||||
send_force = false;
|
send_force = false;
|
||||||
|
} else if (streq(verb, "set-default")) {
|
||||||
|
method = "SetDefaultTarget";
|
||||||
} else
|
} else
|
||||||
assert_not_reached("Unknown verb");
|
assert_not_reached("Unknown verb");
|
||||||
|
|
||||||
@ -4585,6 +4642,8 @@ static int systemctl_help(void) {
|
|||||||
" unmask [NAME...] Unmask one or more units\n"
|
" unmask [NAME...] Unmask one or more units\n"
|
||||||
" link [PATH...] Link one or more units files into\n"
|
" link [PATH...] Link one or more units files into\n"
|
||||||
" the search path\n"
|
" the search path\n"
|
||||||
|
" get-default Get the name of the default target\n"
|
||||||
|
" set-default NAME Set the default target\n"
|
||||||
" is-enabled [NAME...] Check whether unit files are enabled\n\n"
|
" is-enabled [NAME...] Check whether unit files are enabled\n\n"
|
||||||
"Job Commands:\n"
|
"Job Commands:\n"
|
||||||
" list-jobs List jobs\n"
|
" list-jobs List jobs\n"
|
||||||
@ -5646,6 +5705,8 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
|
|||||||
{ "link", MORE, 2, enable_unit },
|
{ "link", MORE, 2, enable_unit },
|
||||||
{ "switch-root", MORE, 2, switch_root },
|
{ "switch-root", MORE, 2, switch_root },
|
||||||
{ "list-dependencies", LESS, 2, list_dependencies },
|
{ "list-dependencies", LESS, 2, list_dependencies },
|
||||||
|
{ "set-default", EQUAL, 2, enable_unit },
|
||||||
|
{ "get-default", LESS, 1, get_default },
|
||||||
};
|
};
|
||||||
|
|
||||||
int left;
|
int left;
|
||||||
@ -5717,7 +5778,9 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
|
|||||||
!streq(verbs[i].verb, "preset") &&
|
!streq(verbs[i].verb, "preset") &&
|
||||||
!streq(verbs[i].verb, "mask") &&
|
!streq(verbs[i].verb, "mask") &&
|
||||||
!streq(verbs[i].verb, "unmask") &&
|
!streq(verbs[i].verb, "unmask") &&
|
||||||
!streq(verbs[i].verb, "link")) {
|
!streq(verbs[i].verb, "link") &&
|
||||||
|
!streq(verbs[i].verb, "set-default") &&
|
||||||
|
!streq(verbs[i].verb, "get-default")) {
|
||||||
|
|
||||||
if (running_in_chroot() > 0) {
|
if (running_in_chroot() > 0) {
|
||||||
log_info("Running in chroot, ignoring request.");
|
log_info("Running in chroot, ignoring request.");
|
||||||
|
Loading…
Reference in New Issue
Block a user