diff --git a/man/org.freedesktop.LogControl1.xml b/man/org.freedesktop.LogControl1.xml index 5944061f99..a51b7b01e1 100644 --- a/man/org.freedesktop.LogControl1.xml +++ b/man/org.freedesktop.LogControl1.xml @@ -24,8 +24,8 @@ Introduction org.freedesktop.LogControl1 is a generic interface that is intended - to be used by any daemon which should allow setting the log level and target over D-Bus. It is implemented - by various daemons that are part of the + to be used by any daemon which allows the log level and target to be set over D-Bus. It is implemented by + various daemons that are part of the systemd1 suite. It is assumed that those settings are global for the whole program, so a fixed object path is @@ -95,12 +95,35 @@ node /org/freedesktop/LogControl1 { It is a short string that identifies the program that is the source of log messages that is passed to the syslog3 call. - - Note: journalctl option / may - be used to filter log messages by log level, option / - may be used to by the syslog identifier, and filters like _TRANSPORT=syslog, - _TRANSPORT=journal, and _TRANSPORT=kernel may be used to filter - messages by the mechanism through which they reached systemd-journald. + + + Tools + + journalctl option / may be used + to filter log messages by log level, option / may be + used to by the syslog identifier, and filters like _TRANSPORT=syslog, + _TRANSPORT=journal, and _TRANSPORT=kernel may be used to filter + messages by the mechanism through which they reached systemd-journald. + + systemctl log-level and systemctl log-target verbs may be + used to query and set the LogLevel and LogTarget properties of the + service manager. systemctl service-log-level and systemctl + service-log-target may similarly be used for individual services. (Services must have the + BusName= property set and must implement the interface described here. See + systemd.service5 + for details about BusName=.) + + + + See Also + + systemd1, + journalctl1, + systemctl1, + systemd.service5, + syslog3 + + diff --git a/man/systemctl.xml b/man/systemctl.xml index 1c55028837..dc02fdcb86 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -50,7 +50,7 @@ The following commands are understood: - Unit Commands + Unit Commands (Introspection and Modification) @@ -151,6 +151,196 @@ Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago + + is-active PATTERN + + + Check whether any of the specified units are active + (i.e. running). Returns an exit code + 0 if at least one is active, or + non-zero otherwise. Unless is + specified, this will also print the current unit state to + standard output. + + + + + is-failed PATTERN + + + Check whether any of the specified units are in a + "failed" state. Returns an exit code + 0 if at least one has failed, + non-zero otherwise. Unless is + specified, this will also print the current unit state to + standard output. + + + + + status PATTERN…|PID…] + + + Show terse runtime status information about one or + more units, followed by most recent log data from the + journal. If no units are specified, show system status. If + combined with , also show the status of + all units (subject to limitations specified with + ). If a PID is passed, show information + about the unit the process belongs to. + + This function is intended to generate human-readable + output. If you are looking for computer-parsable output, + use show instead. By default, this + function only shows 10 lines of output and ellipsizes + lines to fit in the terminal window. This can be changed + with and , + see above. In addition, journalctl + --unit=NAME or + journalctl + --user-unit=NAME use + a similar filter for messages and might be more + convenient. + + + systemd implicitly loads units as necessary, so just running the status will + attempt to load a file. The command is thus not useful for determining if something was already loaded or + not. The units may possibly also be quickly unloaded after the operation is completed if there's no reason + to keep it in memory thereafter. + + + + Example output from systemctl status + + $ systemctl status bluetooth +● bluetooth.service - Bluetooth service + Loaded: loaded (/usr/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled) + Active: active (running) since Wed 2017-01-04 13:54:04 EST; 1 weeks 0 days ago + Docs: man:bluetoothd(8) + Main PID: 930 (bluetoothd) + Status: "Running" + Tasks: 1 + Memory: 648.0K + CPU: 435ms + CGroup: /system.slice/bluetooth.service + └─930 /usr/lib/bluetooth/bluetoothd + +Jan 12 10:46:45 example.com bluetoothd[8900]: Not enough free handles to register service +Jan 12 10:46:45 example.com bluetoothd[8900]: Current Time Service could not be registered +Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output error (5) + + + The dot ("●") uses color on supported terminals to summarize the unit state at a glance. White + indicates an inactive or deactivating state. Red indicates a + failed or error state and green indicates an + active, reloading or activating state. + + + The "Loaded:" line in the output will show loaded if the unit has been loaded into + memory. Other possible values for "Loaded:" include: error if there was a problem + loading it, not-found if no unit file was found for this unit, + bad-setting if an essential unit file setting could not be parsed and + masked if the unit file has been masked. Along with showing the path to the unit file, + this line will also show the enablement state. Enabled commands start at boot. See the full table of + possible enablement states — including the definition of masked — in the documentation + for the is-enabled command. + + + The "Active:" line shows active state. The value is usually active or + inactive. Active could mean started, bound, plugged in, etc depending on the unit type. + The unit could also be in process of changing states, reporting a state of activating or + deactivating. A special failed state is entered when the service + failed in some way, such as a crash, exiting with an error code or timing out. If the failed state is + entered the cause will be logged for later reference. + + + + + + + show PATTERN…|JOB + + + Show properties of one or more units, jobs, or the manager itself. If no argument is specified, + properties of the manager will be shown. If a unit name is specified, properties of the unit are shown, and + if a job ID is specified, properties of the job are shown. By default, empty properties are suppressed. Use + to show those too. To select specific properties to show, use + . This command is intended to be used whenever computer-parsable output is + required. Use status if you are looking for formatted human-readable output. + + Many properties shown by systemctl show map directly to configuration settings of + the system and service manager and its unit files. Note that the properties shown by the command are + generally more low-level, normalized versions of the original configuration settings and expose runtime + state in addition to configuration. For example, properties shown for service units include the service's + current main process identifier as MainPID (which is runtime state), and time settings + are always exposed as properties ending in the …USec suffix even if a matching + configuration options end in …Sec, because microseconds is the normalized time unit used + internally by the system and service manager. + + For details about many of these properties, see the documentation of the D-Bus interface + backing these properties, see + org.freedesktop.systemd15. + + + + + cat PATTERN + + + Show backing files of one or more units. Prints the + "fragment" and "drop-ins" (source files) of units. Each + file is preceded by a comment which includes the file + name. Note that this shows the contents of the backing files + on disk, which may not match the system manager's + understanding of these units if any unit files were + updated on disk and the daemon-reload + command wasn't issued since. + + + + + help PATTERN…|PID + + + Show manual pages for one or more units, if + available. If a PID is given, the manual pages for the unit + the process belongs to are shown. + + + + + + list-dependencies + UNIT... + + + + Shows units required and wanted by the specified + units. This recursively lists units following the + Requires=, + Requisite=, + ConsistsOf=, + Wants=, BindsTo= + dependencies. If no units are specified, + default.target is implied. + + By default, only target units are recursively + expanded. When is passed, all other + units are recursively expanded as well. + + Options , + , + may be used to change what types of dependencies + are shown. + + Note that this command only lists units currently loaded into memory by the service manager. In + particular, this command is not suitable to get a comprehensive list at all reverse dependencies on a + specific unit, as it won't list the dependencies declared by units currently not loaded. + + + + + start PATTERN @@ -325,148 +515,6 @@ Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago processes in the unit's cgroup. - - is-active PATTERN - - - Check whether any of the specified units are active - (i.e. running). Returns an exit code - 0 if at least one is active, or - non-zero otherwise. Unless is - specified, this will also print the current unit state to - standard output. - - - - is-failed PATTERN - - - Check whether any of the specified units are in a - "failed" state. Returns an exit code - 0 if at least one has failed, - non-zero otherwise. Unless is - specified, this will also print the current unit state to - standard output. - - - - status PATTERN…|PID…] - - - Show terse runtime status information about one or - more units, followed by most recent log data from the - journal. If no units are specified, show system status. If - combined with , also show the status of - all units (subject to limitations specified with - ). If a PID is passed, show information - about the unit the process belongs to. - - This function is intended to generate human-readable - output. If you are looking for computer-parsable output, - use show instead. By default, this - function only shows 10 lines of output and ellipsizes - lines to fit in the terminal window. This can be changed - with and , - see above. In addition, journalctl - --unit=NAME or - journalctl - --user-unit=NAME use - a similar filter for messages and might be more - convenient. - - - systemd implicitly loads units as necessary, so just running the status will - attempt to load a file. The command is thus not useful for determining if something was already loaded or - not. The units may possibly also be quickly unloaded after the operation is completed if there's no reason - to keep it in memory thereafter. - - - - Example output from systemctl status - - $ systemctl status bluetooth -● bluetooth.service - Bluetooth service - Loaded: loaded (/usr/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled) - Active: active (running) since Wed 2017-01-04 13:54:04 EST; 1 weeks 0 days ago - Docs: man:bluetoothd(8) - Main PID: 930 (bluetoothd) - Status: "Running" - Tasks: 1 - Memory: 648.0K - CPU: 435ms - CGroup: /system.slice/bluetooth.service - └─930 /usr/lib/bluetooth/bluetoothd - -Jan 12 10:46:45 example.com bluetoothd[8900]: Not enough free handles to register service -Jan 12 10:46:45 example.com bluetoothd[8900]: Current Time Service could not be registered -Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output error (5) - - - The dot ("●") uses color on supported terminals to summarize the unit state at a glance. White - indicates an inactive or deactivating state. Red indicates a - failed or error state and green indicates an - active, reloading or activating state. - - - The "Loaded:" line in the output will show loaded if the unit has been loaded into - memory. Other possible values for "Loaded:" include: error if there was a problem - loading it, not-found if no unit file was found for this unit, - bad-setting if an essential unit file setting could not be parsed and - masked if the unit file has been masked. Along with showing the path to the unit file, - this line will also show the enablement state. Enabled commands start at boot. See the full table of - possible enablement states — including the definition of masked — in the documentation - for the is-enabled command. - - - The "Active:" line shows active state. The value is usually active or - inactive. Active could mean started, bound, plugged in, etc depending on the unit type. - The unit could also be in process of changing states, reporting a state of activating or - deactivating. A special failed state is entered when the service - failed in some way, such as a crash, exiting with an error code or timing out. If the failed state is - entered the cause will be logged for later reference. - - - - - - show PATTERN…|JOB - - - Show properties of one or more units, jobs, or the manager itself. If no argument is specified, - properties of the manager will be shown. If a unit name is specified, properties of the unit are shown, and - if a job ID is specified, properties of the job are shown. By default, empty properties are suppressed. Use - to show those too. To select specific properties to show, use - . This command is intended to be used whenever computer-parsable output is - required. Use status if you are looking for formatted human-readable output. - - Many properties shown by systemctl show map directly to configuration settings of - the system and service manager and its unit files. Note that the properties shown by the command are - generally more low-level, normalized versions of the original configuration settings and expose runtime - state in addition to configuration. For example, properties shown for service units include the service's - current main process identifier as MainPID (which is runtime state), and time settings - are always exposed as properties ending in the …USec suffix even if a matching - configuration options end in …Sec, because microseconds is the normalized time unit used - internally by the system and service manager. - - For details about many of these properties, see the documentation of the D-Bus interface - backing these properties, see - org.freedesktop.systemd15. - - - - cat PATTERN - - - Show backing files of one or more units. Prints the - "fragment" and "drop-ins" (source files) of units. Each - file is preceded by a comment which includes the file - name. Note that this shows the contents of the backing files - on disk, which may not match the system manager's - understanding of these units if any unit files were - updated on disk and the daemon-reload - command wasn't issued since. - - set-property UNIT PROPERTY=VALUE @@ -503,13 +551,59 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err - help PATTERN…|PID + service-log-level SERVICE [LEVEL] - - Show manual pages for one or more units, if - available. If a PID is given, the manual pages for the unit - the process belongs to are shown. - + If the LEVEL argument is not given, print the current + log level as reported by service SERVICE. + + If the optional argument LEVEL is provided, then change the + current log level of the service to LEVEL. The log level should be a + typical syslog log level, i.e. a value in the range 0…7 or one of the strings + emerg, alert, crit, + err, warning, notice, + info, debug; see syslog3 + for details. + + The service must have the appropriate + BusName=destination property and also implement the + generic + org.freedesktop.LogControl15 + interface. (systemctl will use the generic D-Bus protocol to access the + org.freedesktop.LogControl1.LogLevel interface for the D-Bus name + destination.) + + + + service-log-target SERVICE [TARGET] + + If the TARGET argument is not given, print the current + log target as reported by service SERVICE. + + If the optional argument TARGET is provided, then change the + current log target of the service to TARGET. The log target should be + one of the strings console (for log output to the service's standard error + stream), kmsg (for log output to the kernel log buffer), + journal (for log output to + systemd-journald.service8 + using the native journal protocol), syslog (for log output to the classic + syslog socket /dev/log), null (for no log output + whatsoever) or auto (for an automatically determined choice, typically + equivalent to console if the service is invoked interactively, and + journal or syslog otherwise). + + For most services, only a small subset of log targets make sense. In particular, most + "normal" services should only implement console, journal, + and null. Anything else is only appropriate for low-level services that + are active in very early boot before proper logging is established. + + The service must have the appropriate + BusName=destination property and also implement the + generic + org.freedesktop.LogControl15 + interface. (systemctl will use the generic D-Bus protocol to access the + org.freedesktop.LogControl1.LogLevel interface for the D-Bus name + destination.) @@ -529,37 +623,6 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err to be started again, use this command to make it startable again. - - - - list-dependencies - UNIT... - - - - Shows units required and wanted by the specified - units. This recursively lists units following the - Requires=, - Requisite=, - ConsistsOf=, - Wants=, BindsTo= - dependencies. If no units are specified, - default.target is implied. - - By default, only target units are recursively - expanded. When is passed, all other - units are recursively expanded as well. - - Options , - , - may be used to change what types of dependencies - are shown. - - Note that this command only lists units currently loaded into memory by the service manager. In - particular, this command is not suitable to get a comprehensive list at all reverse dependencies on a - specific unit, as it won't list the dependencies declared by units currently not loaded. - - diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 124fa383ab..d11e37da84 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -292,10 +292,11 @@ BusName= - Takes a D-Bus bus name that this service is - reachable as. This option is mandatory for services where - Type= is set to - . + Takes a D-Bus destination name that this service shall use. This option is mandatory + for services where Type= is set to . It is recommended to + always set this property if known to make it easy to map the service name to the D-Bus destination. + In particular, systemctl service-log-level/service-log-target verbs make use of + this. diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index acf07d645f..aa046c6ada 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -81,6 +81,7 @@ #include "stat-util.h" #include "string-table.h" #include "strv.h" +#include "syslog-util.h" #include "sysv-compat.h" #include "terminal-util.h" #include "tmpfile-util.h" @@ -6298,62 +6299,139 @@ static int switch_root(int argc, char *argv[], void *userdata) { return 0; } -static int log_level(int argc, char *argv[], void *userdata) { - sd_bus *bus; +static void give_log_control1_hint(const char *name) { + _cleanup_free_ char *link = NULL; + + if (arg_quiet) + return; + + (void) terminal_urlify_man("org.freedesktop.LogControl1", "5", &link); + + log_notice("Hint: the service must declare BusName= and implement the appropriate D-Bus interface.\n" + " See the %s for details.", link ?: "org.freedesktop.LogControl1(5) man page"); +} + +static int log_setting_internal(sd_bus *bus, const BusLocator* bloc, const char *verb, const char *value) { + assert(bus); + assert(STR_IN_SET(verb, "log-level", "log-target", "service-log-level", "service-log-target")); + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + bool level = endswith(verb, "log-level"); int r; + if (value) { + if (level) { + if (log_level_from_string(value) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "\"%s\" is not a valid log level.", value); + } + + r = bus_set_property(bus, bloc, + level ? "LogLevel" : "LogTarget", + &error, "s", value); + if (r >= 0) + return 0; + + log_error_errno(r, "Failed to set log %s of %s to %s: %s", + level ? "level" : "target", + bloc->destination, value, bus_error_message(&error, r)); + } else { + _cleanup_free_ char *t = NULL; + + r = bus_get_property_string(bus, bloc, + level ? "LogLevel" : "LogTarget", + &error, &t); + if (r >= 0) { + puts(t); + return 0; + } + + log_error_errno(r, "Failed to get log %s of %s: %s", + level ? "level" : "target", + bloc->destination, bus_error_message(&error, r)); + } + + if (sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_METHOD, + SD_BUS_ERROR_UNKNOWN_OBJECT, + SD_BUS_ERROR_UNKNOWN_INTERFACE, + SD_BUS_ERROR_UNKNOWN_PROPERTY)) + give_log_control1_hint(bloc->destination); + return r; +} + +static int log_setting(int argc, char *argv[], void *userdata) { + sd_bus *bus; + int r; + + assert(argc >= 1 && argc <= 2); + r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; - if (argc == 1) { - _cleanup_free_ char *level = NULL; + return log_setting_internal(bus, bus_systemd_mgr, argv[0], argv[1]); +} - r = bus_get_property_string(bus, bus_systemd_mgr, "LogLevel", &error, &level); - if (r < 0) - return log_error_errno(r, "Failed to get log level: %s", bus_error_message(&error, r)); +static int service_name_to_dbus(sd_bus *bus, const char *name, char **ret_dbus_name) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *bus_name = NULL; + int r; - puts(level); + /* First, look for the BusName= property */ + _cleanup_free_ char *dbus_path = unit_dbus_path_from_name(name); + if (!dbus_path) + return log_oom(); - } else { - assert(argc == 2); + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Service", + "BusName", + &error, + &bus_name); + if (r < 0) + return log_error_errno(r, "Failed to obtain BusName= property of %s: %s", + name, bus_error_message(&error, r)); - r = bus_set_property(bus, bus_systemd_mgr, "LogLevel", &error, "s", argv[1]); - if (r < 0) - return log_error_errno(r, "Failed to set log level: %s", bus_error_message(&error, r)); + if (isempty(bus_name)) { + log_error("Unit %s doesn't declare BusName=.", name); + give_log_control1_hint(name); + return -ENOLINK; } + *ret_dbus_name = TAKE_PTR(bus_name); return 0; } -static int log_target(int argc, char *argv[], void *userdata) { +static int service_log_setting(int argc, char *argv[], void *userdata) { sd_bus *bus; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *unit = NULL, *dbus_name = NULL; int r; - r = acquire_bus(BUS_MANAGER, &bus); + assert(argc >= 2 && argc <= 3); + + r = acquire_bus(BUS_FULL, &bus); if (r < 0) return r; - if (argc == 1) { - _cleanup_free_ char *target = NULL; + r = unit_name_mangle_with_suffix(argv[1], argv[0], + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); - r = bus_get_property_string(bus, bus_systemd_mgr, "LogTarget", &error, &target); - if (r < 0) - return log_error_errno(r, "Failed to get log target: %s", bus_error_message(&error, r)); + r = service_name_to_dbus(bus, unit, &dbus_name); + if (r < 0) + return r; - puts(target); + const BusLocator bloc = { + .destination = dbus_name, + .path = "/org/freedesktop/LogControl1", + .interface = "org.freedesktop.LogControl1", + }; - } else { - assert(argc == 2); - - r = bus_set_property(bus, bus_systemd_mgr, "LogTarget", &error, "s", argv[1]); - if (r < 0) - return log_error_errno(r, "Failed to set log target: %s", bus_error_message(&error, r)); - } - - return 0; + return log_setting_internal(bus, &bloc, argv[0], argv[2]); } static int service_watchdogs(int argc, char *argv[], void *userdata) { @@ -7708,6 +7786,16 @@ static int systemctl_help(void) { " ordered by address\n" " list-timers [PATTERN...] List timer units currently in memory,\n" " ordered by next elapse\n" + " is-active PATTERN... Check whether units are active\n" + " is-failed PATTERN... Check whether units are failed\n" + " status [PATTERN...|PID...] Show runtime status of one or more units\n" + " show [PATTERN...|JOB...] Show properties of one or more\n" + " units/jobs or the manager\n" + " cat PATTERN... Show files and drop-ins of specified units\n" + " help PATTERN...|PID... Show manual for one or more units\n" + " list-dependencies [UNIT...] Recursively show units which are required\n" + " or wanted by the units or by which those\n" + " units are required or wanted\n" " start UNIT... Start (activate) one or more units\n" " stop UNIT... Stop (deactivate) one or more units\n" " reload UNIT... Reload one or more units\n" @@ -7723,19 +7811,11 @@ static int systemctl_help(void) { " configuration of unit\n" " freeze PATTERN... Freeze execution of unit processes\n" " thaw PATTERN... Resume execution of a frozen unit\n" - " is-active PATTERN... Check whether units are active\n" - " is-failed PATTERN... Check whether units are failed\n" - " status [PATTERN...|PID...] Show runtime status of one or more units\n" - " show [PATTERN...|JOB...] Show properties of one or more\n" - " units/jobs or the manager\n" - " cat PATTERN... Show files and drop-ins of specified units\n" " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n" - " help PATTERN...|PID... Show manual for one or more units\n" + " service-log-level SERVICE [LEVEL] Get/set logging threshold for service\n" + " service-log-target SERVICE [TARGET] Get/set logging target for service\n" " reset-failed [PATTERN...] Reset failed state for all, one, or more\n" - " units\n" - " list-dependencies [UNIT...] Recursively show units which are required\n" - " or wanted by the units or by which those\n" - " units are required or wanted" + " units" "\n%3$sUnit File Commands:%4$s\n" " list-unit-files [PATTERN...] List installed unit files\n" " enable [UNIT...|PATH...] Enable one or more unit files\n" @@ -9032,8 +9112,10 @@ static int systemctl_main(int argc, char *argv[]) { { "help", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, { "daemon-reload", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, { "daemon-reexec", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, - { "log-level", VERB_ANY, 2, VERB_ONLINE_ONLY, log_level }, - { "log-target", VERB_ANY, 2, VERB_ONLINE_ONLY, log_target }, + { "log-level", VERB_ANY, 2, VERB_ONLINE_ONLY, log_setting }, + { "log-target", VERB_ANY, 2, VERB_ONLINE_ONLY, log_setting }, + { "service-log-level", 2, 3, VERB_ONLINE_ONLY, service_log_setting }, + { "service-log-target", 2, 3, VERB_ONLINE_ONLY, service_log_setting }, { "service-watchdogs", VERB_ANY, 2, VERB_ONLINE_ONLY, service_watchdogs }, { "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment }, { "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment },