1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
6 Copyright 2013 Marc-Antoine Perennou
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <linux/reboot.h>
31 #include <sys/prctl.h>
32 #include <sys/reboot.h>
33 #include <sys/socket.h>
37 #include "sd-daemon.h"
40 #include "alloc-util.h"
42 #include "bus-common-errors.h"
43 #include "bus-error.h"
44 #include "bus-message.h"
45 #include "bus-unit-util.h"
47 #include "cgroup-show.h"
48 #include "cgroup-util.h"
54 #include "exit-status.h"
57 #include "format-util.h"
59 #include "glob-util.h"
60 #include "hostname-util.h"
61 #include "hexdecoct.h"
66 #include "locale-util.h"
68 #include "logs-show.h"
72 #include "parse-util.h"
73 #include "path-lookup.h"
74 #include "path-util.h"
75 #include "process-util.h"
76 #include "rlimit-util.h"
79 #include "signal-util.h"
80 #include "socket-util.h"
81 #include "spawn-ask-password-agent.h"
82 #include "spawn-polkit-agent.h"
84 #include "stat-util.h"
86 #include "terminal-util.h"
87 #include "unit-name.h"
88 #include "user-util.h"
90 #include "utmp-wtmp.h"
94 /* The init script exit status codes
95 0 program is running or service is OK
96 1 program is dead and /var/run pid file exists
97 2 program is dead and /var/lock lock file exists
98 3 program is not running
99 4 program or service status is unknown
100 5-99 reserved for future LSB use
101 100-149 reserved for distribution use
102 150-199 reserved for application use
106 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
107 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
108 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
109 EXIT_PROGRAM_NOT_RUNNING
= 3,
110 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
113 static char **arg_types
= NULL
;
114 static char **arg_states
= NULL
;
115 static char **arg_properties
= NULL
;
116 static bool arg_all
= false;
117 static enum dependency
{
123 } arg_dependency
= DEPENDENCY_FORWARD
;
124 static const char *arg_job_mode
= "replace";
125 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
126 static bool arg_wait
= false;
127 static bool arg_no_block
= false;
128 static bool arg_no_legend
= false;
129 static bool arg_no_pager
= false;
130 static bool arg_no_wtmp
= false;
131 static bool arg_no_sync
= false;
132 static bool arg_no_wall
= false;
133 static bool arg_no_reload
= false;
134 static bool arg_value
= false;
135 static bool arg_show_types
= false;
136 static bool arg_ignore_inhibitors
= false;
137 static bool arg_dry_run
= false;
138 static bool arg_quiet
= false;
139 static bool arg_full
= false;
140 static bool arg_recursive
= false;
141 static int arg_force
= 0;
142 static bool arg_ask_password
= false;
143 static bool arg_runtime
= false;
144 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
145 static char **arg_wall
= NULL
;
146 static const char *arg_kill_who
= NULL
;
147 static int arg_signal
= SIGTERM
;
148 static char *arg_root
= NULL
;
149 static usec_t arg_when
= 0;
150 static char *arg_esp_path
= NULL
;
151 static char *argv_cmdline
= NULL
;
172 ACTION_CANCEL_SHUTDOWN
,
175 } arg_action
= ACTION_SYSTEMCTL
;
176 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
177 static const char *arg_host
= NULL
;
178 static unsigned arg_lines
= 10;
179 static OutputMode arg_output
= OUTPUT_SHORT
;
180 static bool arg_plain
= false;
181 static bool arg_firmware_setup
= false;
182 static bool arg_now
= false;
183 static bool arg_jobs_before
= false;
184 static bool arg_jobs_after
= false;
186 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
187 static int trivial_method(int argc
, char *argv
[], void *userdata
);
188 static int halt_now(enum action a
);
189 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
191 static bool original_stdout_is_tty
;
193 typedef enum BusFocus
{
194 BUS_FULL
, /* The full bus indicated via --system or --user */
195 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
199 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
201 static UnitFileFlags
args_to_flags(void) {
202 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
203 (arg_force
? UNIT_FILE_FORCE
: 0);
206 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
209 assert(focus
< _BUS_FOCUS_MAX
);
212 /* We only go directly to the manager, if we are using a local transport */
213 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
216 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
219 if (!busses
[focus
]) {
222 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
224 if (!user
&& sd_booted() <= 0) {
225 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
226 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
230 if (focus
== BUS_MANAGER
)
231 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
233 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
235 return log_error_errno(r
, "Failed to connect to bus: %m");
237 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
240 *ret
= busses
[focus
];
244 static void release_busses(void) {
247 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
248 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
251 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
253 const char **p
= userdata
;
256 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
266 static void ask_password_agent_open_if_enabled(void) {
268 /* Open the password agent as a child process if necessary */
273 if (!arg_ask_password
)
276 if (arg_scope
!= UNIT_FILE_SYSTEM
)
279 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
282 ask_password_agent_open();
285 static void polkit_agent_open_maybe(void) {
286 /* Open the polkit agent as a child process if necessary */
288 if (arg_scope
!= UNIT_FILE_SYSTEM
)
291 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
294 static OutputFlags
get_output_flags(void) {
296 arg_all
* OUTPUT_SHOW_ALL
|
297 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
298 colors_enabled() * OUTPUT_COLOR
|
299 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
302 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
305 if (!sd_bus_error_is_set(error
))
308 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
309 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
310 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
311 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
312 return EXIT_NOPERMISSION
;
314 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
315 return EXIT_NOTINSTALLED
;
317 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
318 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
319 return EXIT_NOTIMPLEMENTED
;
321 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
322 return EXIT_NOTCONFIGURED
;
330 static bool install_client_side(void) {
332 /* Decides when to execute enable/disable/... operations
333 * client-side rather than server-side. */
335 if (running_in_chroot() > 0)
338 if (sd_booted() <= 0)
341 if (!isempty(arg_root
))
344 if (arg_scope
== UNIT_FILE_GLOBAL
)
347 /* Unsupported environment variable, mostly for debugging purposes */
348 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
354 static int compare_unit_info(const void *a
, const void *b
) {
355 const UnitInfo
*u
= a
, *v
= b
;
359 /* First, order by machine */
360 if (!u
->machine
&& v
->machine
)
362 if (u
->machine
&& !v
->machine
)
364 if (u
->machine
&& v
->machine
) {
365 r
= strcasecmp(u
->machine
, v
->machine
);
370 /* Second, order by unit type */
371 d1
= strrchr(u
->id
, '.');
372 d2
= strrchr(v
->id
, '.');
374 r
= strcasecmp(d1
, d2
);
379 /* Third, order by name */
380 return strcasecmp(u
->id
, v
->id
);
383 static const char* unit_type_suffix(const char *name
) {
386 dot
= strrchr(name
, '.');
393 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
396 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
399 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
405 /* Note that '--all' is not purely a state filter, but also a
406 * filter that hides units that "follow" other units (which is
407 * used for device units that appear under different names). */
408 if (!isempty(u
->following
))
411 if (!strv_isempty(arg_states
))
414 /* By default show all units except the ones in inactive
415 * state and with no pending job */
419 if (streq(u
->active_state
, "inactive"))
425 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
426 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
428 unsigned n_shown
= 0;
431 max_id_len
= strlen("UNIT");
432 load_len
= strlen("LOAD");
433 active_len
= strlen("ACTIVE");
434 sub_len
= strlen("SUB");
435 job_len
= strlen("JOB");
436 max_desc_len
= strlen("DESCRIPTION");
438 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
439 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
440 load_len
= MAX(load_len
, strlen(u
->load_state
));
441 active_len
= MAX(active_len
, strlen(u
->active_state
));
442 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
443 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
445 if (u
->job_id
!= 0) {
446 job_len
= MAX(job_len
, strlen(u
->job_type
));
450 if (!arg_no_legend
&&
451 (streq(u
->active_state
, "failed") ||
452 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
456 if (!arg_full
&& original_stdout_is_tty
) {
459 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
460 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
463 basic_len
+= job_len
+ 1;
465 if (basic_len
< (unsigned) columns()) {
466 unsigned extra_len
, incr
;
467 extra_len
= columns() - basic_len
;
469 /* Either UNIT already got 25, or is fully satisfied.
470 * Grant up to 25 to DESC now. */
471 incr
= MIN(extra_len
, 25u);
475 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
476 * description but not more than it needs. */
478 incr
= MIN(max_id_len
- id_len
, extra_len
);
480 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
486 desc_len
= max_desc_len
;
489 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
490 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
491 const char *on_underline
= "", *off_underline
= "";
492 const char *on_loaded
= "", *off_loaded
= "";
493 const char *on_active
= "", *off_active
= "";
494 const char *on_circle
= "", *off_circle
= "";
496 bool circle
= false, underline
= false;
498 if (!n_shown
&& !arg_no_legend
) {
503 printf("%s%-*s %-*s %-*s %-*s ",
507 active_len
, "ACTIVE",
511 printf("%-*s ", job_len
, "JOB");
515 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
522 if (u
+ 1 < unit_infos
+ c
&&
523 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
524 on_underline
= ansi_underline();
525 off_underline
= ansi_normal();
529 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
530 on_circle
= ansi_highlight_yellow();
531 off_circle
= ansi_normal();
533 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
534 off_loaded
= underline
? on_underline
: ansi_normal();
535 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
536 on_circle
= ansi_highlight_red();
537 off_circle
= ansi_normal();
539 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
540 off_active
= underline
? on_underline
: ansi_normal();
544 j
= strjoin(u
->machine
, ":", u
->id
);
553 e
= ellipsize(id
, id_len
, 33);
561 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
563 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
565 on_active
, id_len
, id
, off_active
,
566 on_loaded
, load_len
, u
->load_state
, off_loaded
,
567 on_active
, active_len
, u
->active_state
,
568 sub_len
, u
->sub_state
, off_active
,
569 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
573 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
578 if (!arg_no_legend
) {
579 const char *on
, *off
;
583 "LOAD = Reflects whether the unit definition was properly loaded.\n"
584 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
585 "SUB = The low-level unit activation state, values depend on unit type.");
586 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
587 on
= ansi_highlight();
590 on
= ansi_highlight_red();
595 printf("%s%u loaded units listed.%s\n"
596 "To show all installed unit files use 'systemctl list-unit-files'.\n",
599 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
600 "To show all installed unit files use 'systemctl list-unit-files'.\n",
607 static int get_unit_list(
611 UnitInfo
**unit_infos
,
613 sd_bus_message
**_reply
) {
615 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
616 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
617 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
621 bool fallback
= false;
627 r
= sd_bus_message_new_method_call(
630 "org.freedesktop.systemd1",
631 "/org/freedesktop/systemd1",
632 "org.freedesktop.systemd1.Manager",
633 "ListUnitsByPatterns");
635 return bus_log_create_error(r
);
637 r
= sd_bus_message_append_strv(m
, arg_states
);
639 return bus_log_create_error(r
);
641 r
= sd_bus_message_append_strv(m
, patterns
);
643 return bus_log_create_error(r
);
645 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
646 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
647 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
648 /* Fallback to legacy ListUnitsFiltered method */
650 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
651 m
= sd_bus_message_unref(m
);
652 sd_bus_error_free(&error
);
654 r
= sd_bus_message_new_method_call(
657 "org.freedesktop.systemd1",
658 "/org/freedesktop/systemd1",
659 "org.freedesktop.systemd1.Manager",
660 "ListUnitsFiltered");
662 return bus_log_create_error(r
);
664 r
= sd_bus_message_append_strv(m
, arg_states
);
666 return bus_log_create_error(r
);
668 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
671 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
673 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
675 return bus_log_parse_error(r
);
677 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
680 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
683 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
686 (*unit_infos
)[c
++] = u
;
689 return bus_log_parse_error(r
);
691 r
= sd_bus_message_exit_container(reply
);
693 return bus_log_parse_error(r
);
701 static void message_set_freep(Set
**set
) {
704 while ((m
= set_steal_first(*set
)))
705 sd_bus_message_unref(m
);
710 static int get_unit_list_recursive(
713 UnitInfo
**_unit_infos
,
717 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
718 _cleanup_(message_set_freep
) Set
*replies
;
719 sd_bus_message
*reply
;
727 replies
= set_new(NULL
);
731 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
735 r
= set_put(replies
, reply
);
737 sd_bus_message_unref(reply
);
742 _cleanup_strv_free_
char **machines
= NULL
;
745 r
= sd_get_machine_names(&machines
);
747 return log_error_errno(r
, "Failed to get machine names: %m");
749 STRV_FOREACH(i
, machines
) {
750 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
753 r
= sd_bus_open_system_machine(&container
, *i
);
755 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
759 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
765 r
= set_put(replies
, reply
);
767 sd_bus_message_unref(reply
);
772 *_machines
= machines
;
777 *_unit_infos
= unit_infos
;
786 static int list_units(int argc
, char *argv
[], void *userdata
) {
787 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
788 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
789 _cleanup_strv_free_
char **machines
= NULL
;
793 r
= acquire_bus(BUS_MANAGER
, &bus
);
797 pager_open(arg_no_pager
, false);
799 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
803 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
804 return output_units_list(unit_infos
, r
);
807 static int get_triggered_units(
812 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
819 r
= sd_bus_get_property_strv(
821 "org.freedesktop.systemd1",
823 "org.freedesktop.systemd1.Unit",
828 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
833 static int get_listening(
835 const char* unit_path
,
838 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
839 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
840 const char *type
, *path
;
843 r
= sd_bus_get_property(
845 "org.freedesktop.systemd1",
847 "org.freedesktop.systemd1.Socket",
853 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
855 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
857 return bus_log_parse_error(r
);
859 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
861 r
= strv_extend(listening
, type
);
865 r
= strv_extend(listening
, path
);
872 return bus_log_parse_error(r
);
874 r
= sd_bus_message_exit_container(reply
);
876 return bus_log_parse_error(r
);
888 /* Note: triggered is a list here, although it almost certainly
889 * will always be one unit. Nevertheless, dbus API allows for multiple
890 * values, so let's follow that. */
893 /* The strv above is shared. free is set only in the first one. */
897 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
903 if (!a
->machine
&& b
->machine
)
905 if (a
->machine
&& !b
->machine
)
907 if (a
->machine
&& b
->machine
) {
908 o
= strcasecmp(a
->machine
, b
->machine
);
913 o
= strcmp(a
->path
, b
->path
);
915 o
= strcmp(a
->type
, b
->type
);
920 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
921 struct socket_info
*s
;
922 unsigned pathlen
= strlen("LISTEN"),
923 typelen
= strlen("TYPE") * arg_show_types
,
924 socklen
= strlen("UNIT"),
925 servlen
= strlen("ACTIVATES");
926 const char *on
, *off
;
928 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
932 socklen
= MAX(socklen
, strlen(s
->id
));
934 typelen
= MAX(typelen
, strlen(s
->type
));
935 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
937 STRV_FOREACH(a
, s
->triggered
)
938 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
939 servlen
= MAX(servlen
, tmp
);
944 printf("%-*s %-*.*s%-*s %s\n",
946 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
950 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
951 _cleanup_free_
char *j
= NULL
;
956 j
= strjoin(s
->machine
, ":", s
->path
);
964 printf("%-*s %-*s %-*s",
965 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
968 pathlen
, path
, socklen
, s
->id
);
969 STRV_FOREACH(a
, s
->triggered
)
971 a
== s
->triggered
? "" : ",", *a
);
975 on
= ansi_highlight();
980 on
= ansi_highlight_red();
984 if (!arg_no_legend
) {
985 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
987 printf("Pass --all to see loaded but inactive sockets, too.\n");
993 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
994 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
995 _cleanup_strv_free_
char **machines
= NULL
;
996 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
997 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
999 struct socket_info
*s
;
1005 r
= acquire_bus(BUS_MANAGER
, &bus
);
1009 pager_open(arg_no_pager
, false);
1011 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1015 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1016 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1019 if (!endswith(u
->id
, ".socket"))
1022 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1026 c
= get_listening(bus
, u
->unit_path
, &listening
);
1032 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1037 for (i
= 0; i
< c
; i
++)
1038 socket_infos
[cs
+ i
] = (struct socket_info
) {
1039 .machine
= u
->machine
,
1041 .type
= listening
[i
*2],
1042 .path
= listening
[i
*2 + 1],
1043 .triggered
= triggered
,
1044 .own_triggered
= i
==0,
1047 /* from this point on we will cleanup those socket_infos */
1050 listening
= triggered
= NULL
; /* avoid cleanup */
1053 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1054 (__compar_fn_t
) socket_info_compare
);
1056 output_sockets_list(socket_infos
, cs
);
1059 assert(cs
== 0 || socket_infos
);
1060 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1063 if (s
->own_triggered
)
1064 strv_free(s
->triggered
);
1070 static int get_next_elapse(
1073 dual_timestamp
*next
) {
1075 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1083 r
= sd_bus_get_property_trivial(
1085 "org.freedesktop.systemd1",
1087 "org.freedesktop.systemd1.Timer",
1088 "NextElapseUSecMonotonic",
1093 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1095 r
= sd_bus_get_property_trivial(
1097 "org.freedesktop.systemd1",
1099 "org.freedesktop.systemd1.Timer",
1100 "NextElapseUSecRealtime",
1105 return log_error_errno(r
, "Failed to get next elapse time: %s", bus_error_message(&error
, r
));
1111 static int get_last_trigger(
1116 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1123 r
= sd_bus_get_property_trivial(
1125 "org.freedesktop.systemd1",
1127 "org.freedesktop.systemd1.Timer",
1133 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1139 const char* machine
;
1142 usec_t last_trigger
;
1146 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1152 if (!a
->machine
&& b
->machine
)
1154 if (a
->machine
&& !b
->machine
)
1156 if (a
->machine
&& b
->machine
) {
1157 o
= strcasecmp(a
->machine
, b
->machine
);
1162 if (a
->next_elapse
< b
->next_elapse
)
1164 if (a
->next_elapse
> b
->next_elapse
)
1167 return strcmp(a
->id
, b
->id
);
1170 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1171 struct timer_info
*t
;
1173 nextlen
= strlen("NEXT"),
1174 leftlen
= strlen("LEFT"),
1175 lastlen
= strlen("LAST"),
1176 passedlen
= strlen("PASSED"),
1177 unitlen
= strlen("UNIT"),
1178 activatelen
= strlen("ACTIVATES");
1180 const char *on
, *off
;
1182 assert(timer_infos
|| n
== 0);
1184 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1188 if (t
->next_elapse
> 0) {
1189 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1191 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1192 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1194 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1195 leftlen
= MAX(leftlen
, strlen(trel
));
1198 if (t
->last_trigger
> 0) {
1199 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1201 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1202 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1204 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1205 passedlen
= MAX(passedlen
, strlen(trel
));
1208 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1210 STRV_FOREACH(a
, t
->triggered
)
1211 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1213 activatelen
= MAX(activatelen
, ul
);
1218 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1222 passedlen
, "PASSED",
1226 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1227 _cleanup_free_
char *j
= NULL
;
1229 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1230 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1233 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1234 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1236 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1237 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1240 j
= strjoin(t
->machine
, ":", t
->id
);
1247 printf("%-*s %-*s %-*s %-*s %-*s",
1248 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1250 STRV_FOREACH(a
, t
->triggered
)
1252 a
== t
->triggered
? "" : ",", *a
);
1256 on
= ansi_highlight();
1257 off
= ansi_normal();
1261 on
= ansi_highlight_red();
1262 off
= ansi_normal();
1265 if (!arg_no_legend
) {
1266 printf("%s%u timers listed.%s\n", on
, n
, off
);
1268 printf("Pass --all to see loaded but inactive timers, too.\n");
1274 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1280 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1283 if (next
->monotonic
> nw
->monotonic
)
1284 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1286 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1288 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1289 next_elapse
= MIN(converted
, next
->realtime
);
1291 next_elapse
= converted
;
1294 next_elapse
= next
->realtime
;
1299 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1300 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1301 _cleanup_strv_free_
char **machines
= NULL
;
1302 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1303 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1304 struct timer_info
*t
;
1312 r
= acquire_bus(BUS_MANAGER
, &bus
);
1316 pager_open(arg_no_pager
, false);
1318 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1322 dual_timestamp_get(&nw
);
1324 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1325 _cleanup_strv_free_
char **triggered
= NULL
;
1326 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1329 if (!endswith(u
->id
, ".timer"))
1332 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1336 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1340 get_last_trigger(bus
, u
->unit_path
, &last
);
1342 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1347 m
= calc_next_elapse(&nw
, &next
);
1349 timer_infos
[c
++] = (struct timer_info
) {
1350 .machine
= u
->machine
,
1353 .last_trigger
= last
,
1354 .triggered
= triggered
,
1357 triggered
= NULL
; /* avoid cleanup */
1360 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1361 (__compar_fn_t
) timer_info_compare
);
1363 output_timers_list(timer_infos
, c
);
1366 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1367 strv_free(t
->triggered
);
1372 static int compare_unit_file_list(const void *a
, const void *b
) {
1373 const char *d1
, *d2
;
1374 const UnitFileList
*u
= a
, *v
= b
;
1376 d1
= strrchr(u
->path
, '.');
1377 d2
= strrchr(v
->path
, '.');
1382 r
= strcasecmp(d1
, d2
);
1387 return strcasecmp(basename(u
->path
), basename(v
->path
));
1390 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1393 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1396 if (!strv_isempty(arg_types
)) {
1399 dot
= strrchr(u
->path
, '.');
1403 if (!strv_find(arg_types
, dot
+1))
1407 if (!strv_isempty(states
) &&
1408 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1414 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1415 unsigned max_id_len
, id_cols
, state_cols
;
1416 const UnitFileList
*u
;
1418 max_id_len
= strlen("UNIT FILE");
1419 state_cols
= strlen("STATE");
1421 for (u
= units
; u
< units
+ c
; u
++) {
1422 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1423 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1427 unsigned basic_cols
;
1429 id_cols
= MIN(max_id_len
, 25u);
1430 basic_cols
= 1 + id_cols
+ state_cols
;
1431 if (basic_cols
< (unsigned) columns())
1432 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1434 id_cols
= max_id_len
;
1436 if (!arg_no_legend
&& c
> 0)
1437 printf("%s%-*s %-*s%s\n",
1439 id_cols
, "UNIT FILE",
1440 state_cols
, "STATE",
1443 for (u
= units
; u
< units
+ c
; u
++) {
1444 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1445 _cleanup_free_
char *e
= NULL
;
1448 underline
= u
+ 1 < units
+ c
&&
1449 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1452 on_underline
= ansi_underline();
1454 if (IN_SET(u
->state
,
1456 UNIT_FILE_MASKED_RUNTIME
,
1459 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1460 else if (u
->state
== UNIT_FILE_ENABLED
)
1461 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1463 if (on_underline
|| on_color
)
1464 off
= ansi_normal();
1466 id
= basename(u
->path
);
1468 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1470 printf("%s%-*s %s%-*s%s\n",
1471 strempty(on_underline
),
1472 id_cols
, e
? e
: id
,
1473 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1477 printf("\n%u unit files listed.\n", c
);
1480 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1481 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1482 _cleanup_free_ UnitFileList
*units
= NULL
;
1489 bool fallback
= false;
1491 if (install_client_side()) {
1497 h
= hashmap_new(&string_hash_ops
);
1501 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1503 unit_file_list_free(h
);
1504 return log_error_errno(r
, "Failed to get unit file list: %m");
1507 n_units
= hashmap_size(h
);
1509 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1511 unit_file_list_free(h
);
1515 HASHMAP_FOREACH(u
, h
, i
) {
1516 if (!output_show_unit_file(u
, NULL
, NULL
))
1523 assert(c
<= n_units
);
1528 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1529 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1532 r
= acquire_bus(BUS_MANAGER
, &bus
);
1536 r
= sd_bus_message_new_method_call(
1539 "org.freedesktop.systemd1",
1540 "/org/freedesktop/systemd1",
1541 "org.freedesktop.systemd1.Manager",
1542 "ListUnitFilesByPatterns");
1544 return bus_log_create_error(r
);
1546 r
= sd_bus_message_append_strv(m
, arg_states
);
1548 return bus_log_create_error(r
);
1550 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1552 return bus_log_create_error(r
);
1554 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1555 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1556 /* Fallback to legacy ListUnitFiles method */
1558 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1559 m
= sd_bus_message_unref(m
);
1560 sd_bus_error_free(&error
);
1562 r
= sd_bus_message_new_method_call(
1565 "org.freedesktop.systemd1",
1566 "/org/freedesktop/systemd1",
1567 "org.freedesktop.systemd1.Manager",
1570 return bus_log_create_error(r
);
1572 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1575 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1577 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1579 return bus_log_parse_error(r
);
1581 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1583 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1586 units
[c
] = (struct UnitFileList
) {
1588 unit_file_state_from_string(state
)
1591 if (output_show_unit_file(&units
[c
],
1592 fallback
? arg_states
: NULL
,
1593 fallback
? strv_skip(argv
, 1) : NULL
))
1598 return bus_log_parse_error(r
);
1600 r
= sd_bus_message_exit_container(reply
);
1602 return bus_log_parse_error(r
);
1605 pager_open(arg_no_pager
, false);
1607 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1608 output_unit_file_list(units
, c
);
1610 if (install_client_side())
1611 for (unit
= units
; unit
< units
+ c
; unit
++)
1617 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1618 _cleanup_free_
char *n
= NULL
;
1619 size_t max_len
= MAX(columns(),20u);
1625 for (i
= level
- 1; i
>= 0; i
--) {
1627 if (len
> max_len
- 3 && !arg_full
) {
1628 printf("%s...\n",max_len
% 2 ? "" : " ");
1631 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1635 if (len
> max_len
- 3 && !arg_full
) {
1636 printf("%s...\n",max_len
% 2 ? "" : " ");
1640 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1644 printf("%s\n", name
);
1648 n
= ellipsize(name
, max_len
-len
, 100);
1656 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1658 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1659 [DEPENDENCY_FORWARD
] = "Requires\0"
1664 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1669 [DEPENDENCY_AFTER
] = "After\0",
1670 [DEPENDENCY_BEFORE
] = "Before\0",
1673 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1674 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1675 _cleanup_strv_free_
char **ret
= NULL
;
1676 _cleanup_free_
char *path
= NULL
;
1682 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1684 path
= unit_dbus_path_from_name(name
);
1688 r
= sd_bus_call_method(
1690 "org.freedesktop.systemd1",
1692 "org.freedesktop.DBus.Properties",
1696 "s", "org.freedesktop.systemd1.Unit");
1698 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1700 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1702 return bus_log_parse_error(r
);
1704 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1707 r
= sd_bus_message_read(reply
, "s", &prop
);
1709 return bus_log_parse_error(r
);
1711 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1712 r
= sd_bus_message_skip(reply
, "v");
1714 return bus_log_parse_error(r
);
1717 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1719 return bus_log_parse_error(r
);
1721 r
= bus_message_read_strv_extend(reply
, &ret
);
1723 return bus_log_parse_error(r
);
1725 r
= sd_bus_message_exit_container(reply
);
1727 return bus_log_parse_error(r
);
1730 r
= sd_bus_message_exit_container(reply
);
1732 return bus_log_parse_error(r
);
1736 return bus_log_parse_error(r
);
1738 r
= sd_bus_message_exit_container(reply
);
1740 return bus_log_parse_error(r
);
1742 *deps
= strv_uniq(ret
);
1748 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1749 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1751 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1753 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1756 return strcasecmp(*a
, *b
);
1759 static int list_dependencies_one(
1764 unsigned int branches
) {
1766 _cleanup_strv_free_
char **deps
= NULL
;
1774 r
= strv_extend(units
, name
);
1778 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1782 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1784 STRV_FOREACH(c
, deps
) {
1785 if (strv_contains(*units
, *c
)) {
1788 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1798 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1801 (void) get_state_one_unit(bus
, *c
, &active_state
);
1803 switch (active_state
) {
1805 case UNIT_RELOADING
:
1806 case UNIT_ACTIVATING
:
1807 on
= ansi_highlight_green();
1811 case UNIT_DEACTIVATING
:
1816 on
= ansi_highlight_red();
1820 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1823 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1827 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1828 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1835 strv_remove(*units
, name
);
1840 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1841 _cleanup_strv_free_
char **units
= NULL
;
1842 _cleanup_free_
char *unit
= NULL
;
1848 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1850 return log_error_errno(r
, "Failed to mangle unit name: %m");
1854 u
= SPECIAL_DEFAULT_TARGET
;
1856 r
= acquire_bus(BUS_MANAGER
, &bus
);
1860 pager_open(arg_no_pager
, false);
1864 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1867 struct machine_info
{
1871 char *control_group
;
1872 uint32_t n_failed_units
;
1877 static const struct bus_properties_map machine_info_property_map
[] = {
1878 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1879 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1880 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1881 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1882 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1886 static void machine_info_clear(struct machine_info
*info
) {
1891 free(info
->control_group
);
1895 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1901 for (i
= 0; i
< n
; i
++)
1902 machine_info_clear(&machine_infos
[i
]);
1904 free(machine_infos
);
1907 static int compare_machine_info(const void *a
, const void *b
) {
1908 const struct machine_info
*u
= a
, *v
= b
;
1910 if (u
->is_host
!= v
->is_host
)
1911 return u
->is_host
> v
->is_host
? -1 : 1;
1913 return strcasecmp(u
->name
, v
->name
);
1916 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1917 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1923 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1930 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, mi
);
1937 static bool output_show_machine(const char *name
, char **patterns
) {
1938 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1941 static int get_machine_list(
1943 struct machine_info
**_machine_infos
,
1946 struct machine_info
*machine_infos
= NULL
;
1947 _cleanup_strv_free_
char **m
= NULL
;
1948 _cleanup_free_
char *hn
= NULL
;
1953 hn
= gethostname_malloc();
1957 if (output_show_machine(hn
, patterns
)) {
1958 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1961 machine_infos
[c
].is_host
= true;
1962 machine_infos
[c
].name
= hn
;
1965 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1969 r
= sd_get_machine_names(&m
);
1971 return log_error_errno(r
, "Failed to get machine list: %m");
1973 STRV_FOREACH(i
, m
) {
1974 _cleanup_free_
char *class = NULL
;
1976 if (!output_show_machine(*i
, patterns
))
1979 sd_machine_get_class(*i
, &class);
1980 if (!streq_ptr(class, "container"))
1983 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1984 free_machines_list(machine_infos
, c
);
1988 machine_infos
[c
].is_host
= false;
1989 machine_infos
[c
].name
= strdup(*i
);
1990 if (!machine_infos
[c
].name
) {
1991 free_machines_list(machine_infos
, c
);
1995 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1999 *_machine_infos
= machine_infos
;
2003 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
2004 struct machine_info
*m
;
2007 namelen
= sizeof("NAME") - 1,
2008 statelen
= sizeof("STATE") - 1,
2009 failedlen
= sizeof("FAILED") - 1,
2010 jobslen
= sizeof("JOBS") - 1;
2012 assert(machine_infos
|| n
== 0);
2014 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2015 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
2016 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
2017 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
2018 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
2020 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
2024 if (!arg_no_legend
) {
2028 printf("%-*s %-*s %-*s %-*s\n",
2031 failedlen
, "FAILED",
2035 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2036 const char *on_state
= "", *off_state
= "";
2037 const char *on_failed
= "", *off_failed
= "";
2038 bool circle
= false;
2040 if (streq_ptr(m
->state
, "degraded")) {
2041 on_state
= ansi_highlight_red();
2042 off_state
= ansi_normal();
2044 } else if (!streq_ptr(m
->state
, "running")) {
2045 on_state
= ansi_highlight_yellow();
2046 off_state
= ansi_normal();
2050 if (m
->n_failed_units
> 0) {
2051 on_failed
= ansi_highlight_red();
2052 off_failed
= ansi_normal();
2054 on_failed
= off_failed
= "";
2057 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2060 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2061 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2062 on_state
, statelen
, strna(m
->state
), off_state
,
2063 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2064 jobslen
, m
->n_jobs
);
2066 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2067 namelen
, strna(m
->name
),
2068 on_state
, statelen
, strna(m
->state
), off_state
,
2069 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2070 jobslen
, m
->n_jobs
);
2074 printf("\n%u machines listed.\n", n
);
2077 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2078 struct machine_info
*machine_infos
= NULL
;
2082 if (geteuid() != 0) {
2083 log_error("Must be root.");
2087 r
= acquire_bus(BUS_MANAGER
, &bus
);
2091 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2095 pager_open(arg_no_pager
, false);
2097 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2098 output_machines_list(machine_infos
, r
);
2099 free_machines_list(machine_infos
, r
);
2104 static int get_default(int argc
, char *argv
[], void *userdata
) {
2105 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2106 _cleanup_free_
char *_path
= NULL
;
2110 if (install_client_side()) {
2111 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2113 return log_error_errno(r
, "Failed to get default target: %m");
2118 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2121 r
= acquire_bus(BUS_MANAGER
, &bus
);
2125 r
= sd_bus_call_method(
2127 "org.freedesktop.systemd1",
2128 "/org/freedesktop/systemd1",
2129 "org.freedesktop.systemd1.Manager",
2135 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2137 r
= sd_bus_message_read(reply
, "s", &path
);
2139 return bus_log_parse_error(r
);
2143 printf("%s\n", path
);
2148 static int set_default(int argc
, char *argv
[], void *userdata
) {
2149 _cleanup_free_
char *unit
= NULL
;
2150 UnitFileChange
*changes
= NULL
;
2151 unsigned n_changes
= 0;
2157 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2159 return log_error_errno(r
, "Failed to mangle unit name: %m");
2161 if (install_client_side()) {
2162 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2163 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2168 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2169 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2172 polkit_agent_open_maybe();
2174 r
= acquire_bus(BUS_MANAGER
, &bus
);
2178 r
= sd_bus_call_method(
2180 "org.freedesktop.systemd1",
2181 "/org/freedesktop/systemd1",
2182 "org.freedesktop.systemd1.Manager",
2188 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2190 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2194 /* Try to reload if enabled */
2196 r
= daemon_reload(argc
, argv
, userdata
);
2202 unit_file_changes_free(changes
, n_changes
);
2207 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2208 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2209 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2210 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2216 r
= sd_bus_call_method(
2218 "org.freedesktop.systemd1",
2219 "/org/freedesktop/systemd1",
2220 "org.freedesktop.systemd1.Manager",
2226 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2228 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2230 return bus_log_parse_error(r
);
2232 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2233 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2235 return bus_log_parse_error(r
);
2237 r
= sd_bus_message_exit_container(reply
);
2239 return bus_log_parse_error(r
);
2246 const char *name
, *type
, *state
;
2249 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2250 unsigned id_len
, unit_len
, type_len
, state_len
;
2251 const struct job_info
*j
;
2252 const char *on
, *off
;
2253 bool shorten
= false;
2255 assert(n
== 0 || jobs
);
2258 if (!arg_no_legend
) {
2259 on
= ansi_highlight_green();
2260 off
= ansi_normal();
2262 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2267 pager_open(arg_no_pager
, false);
2269 id_len
= strlen("JOB");
2270 unit_len
= strlen("UNIT");
2271 type_len
= strlen("TYPE");
2272 state_len
= strlen("STATE");
2274 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2275 uint32_t id
= j
->id
;
2276 assert(j
->name
&& j
->type
&& j
->state
);
2278 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2279 unit_len
= MAX(unit_len
, strlen(j
->name
));
2280 type_len
= MAX(type_len
, strlen(j
->type
));
2281 state_len
= MAX(state_len
, strlen(j
->state
));
2284 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2285 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2290 printf("%*s %-*s %-*s %-*s\n",
2294 state_len
, "STATE");
2296 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2297 _cleanup_free_
char *e
= NULL
;
2299 if (streq(j
->state
, "running")) {
2300 on
= ansi_highlight();
2301 off
= ansi_normal();
2305 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2306 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2308 on
, unit_len
, e
? e
: j
->name
, off
,
2310 on
, state_len
, j
->state
, off
);
2313 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2314 if (arg_jobs_before
)
2315 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2318 if (!arg_no_legend
) {
2319 on
= ansi_highlight();
2320 off
= ansi_normal();
2322 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2326 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2327 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2330 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2331 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2332 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2333 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2334 _cleanup_free_
struct job_info
*jobs
= NULL
;
2340 bool skipped
= false;
2342 r
= acquire_bus(BUS_MANAGER
, &bus
);
2346 r
= sd_bus_call_method(
2348 "org.freedesktop.systemd1",
2349 "/org/freedesktop/systemd1",
2350 "org.freedesktop.systemd1.Manager",
2356 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2358 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2360 return bus_log_parse_error(r
);
2362 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2363 struct job_info job
= { id
, name
, type
, state
};
2365 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2370 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2376 return bus_log_parse_error(r
);
2378 r
= sd_bus_message_exit_container(reply
);
2380 return bus_log_parse_error(r
);
2382 pager_open(arg_no_pager
, false);
2384 output_jobs_list(bus
, jobs
, c
, skipped
);
2388 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2394 return trivial_method(argc
, argv
, userdata
);
2396 r
= acquire_bus(BUS_MANAGER
, &bus
);
2400 polkit_agent_open_maybe();
2402 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2403 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2407 q
= safe_atou32(*name
, &id
);
2409 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2411 q
= sd_bus_call_method(
2413 "org.freedesktop.systemd1",
2414 "/org/freedesktop/systemd1",
2415 "org.freedesktop.systemd1.Manager",
2421 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2430 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2431 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2435 /* We ignore all errors here, since this is used to show a
2438 /* We don't use unit_dbus_path_from_name() directly since we
2439 * don't want to load the unit if it isn't loaded. */
2441 r
= sd_bus_call_method(
2443 "org.freedesktop.systemd1",
2444 "/org/freedesktop/systemd1",
2445 "org.freedesktop.systemd1.Manager",
2453 r
= sd_bus_message_read(reply
, "o", &path
);
2457 r
= sd_bus_get_property_trivial(
2459 "org.freedesktop.systemd1",
2461 "org.freedesktop.systemd1.Unit",
2471 static void warn_unit_file_changed(const char *name
) {
2474 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2475 ansi_highlight_red(),
2478 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2481 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2487 STRV_FOREACH(p
, lp
->search_path
) {
2488 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2491 path
= path_join(NULL
, *p
, unit_name
);
2495 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2501 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2513 static int unit_find_template_path(
2514 const char *unit_name
,
2516 char **fragment_path
,
2519 _cleanup_free_
char *_template
= NULL
;
2522 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2524 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2526 return r
; /* error or found a real unit */
2528 r
= unit_name_template(unit_name
, &_template
);
2530 return 0; /* not a template, does not exist */
2532 return log_error_errno(r
, "Failed to determine template name: %m");
2534 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2539 *template = _template
;
2545 static int unit_find_paths(
2547 const char *unit_name
,
2549 char **fragment_path
,
2550 char ***dropin_paths
) {
2552 _cleanup_free_
char *path
= NULL
;
2553 _cleanup_strv_free_
char **dropins
= NULL
;
2557 * Finds where the unit is defined on disk. Returns 0 if the unit
2558 * is not found. Returns 1 if it is found, and sets
2559 * - the path to the unit in *path, if it exists on disk,
2560 * - and a strv of existing drop-ins in *dropins,
2561 * if the arg is not NULL and any dropins were found.
2565 assert(fragment_path
);
2568 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2569 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2570 _cleanup_free_
char *unit
= NULL
;
2572 unit
= unit_dbus_path_from_name(unit_name
);
2576 r
= sd_bus_get_property_string(
2578 "org.freedesktop.systemd1",
2580 "org.freedesktop.systemd1.Unit",
2585 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2588 r
= sd_bus_get_property_strv(
2590 "org.freedesktop.systemd1",
2592 "org.freedesktop.systemd1.Unit",
2597 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2600 _cleanup_set_free_ Set
*names
= NULL
;
2601 _cleanup_free_
char *template = NULL
;
2603 names
= set_new(NULL
);
2607 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2612 /* We found the unit file. If we followed symlinks, this name might be
2613 * different then the unit_name with started with. Look for dropins matching
2614 * that "final" name. */
2615 r
= set_put(names
, basename(path
));
2617 /* No unit file, let's look for dropins matching the original name.
2618 * systemd has fairly complicated rules (based on unit type and provenience),
2619 * which units are allowed not to have the main unit file. We err on the
2620 * side of including too many files, and always try to load dropins. */
2621 r
= set_put(names
, unit_name
);
2623 /* The cases where we allow a unit to exist without the main file are
2624 * never valid for templates. Don't try to load dropins in this case. */
2628 return log_error_errno(r
, "Failed to add unit name: %m");
2631 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2632 NULL
, names
, &dropins
);
2640 if (!isempty(path
)) {
2641 *fragment_path
= path
;
2646 if (dropin_paths
&& !strv_isempty(dropins
)) {
2647 *dropin_paths
= dropins
;
2652 if (r
== 0 && !arg_force
)
2653 log_error("No files found for %s.", unit_name
);
2658 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2659 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2660 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2661 _cleanup_free_
char *buf
= NULL
;
2662 UnitActiveState state
;
2667 assert(active_state
);
2669 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2671 r
= sd_bus_call_method(
2673 "org.freedesktop.systemd1",
2674 "/org/freedesktop/systemd1",
2675 "org.freedesktop.systemd1.Manager",
2681 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2682 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2684 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2685 * considered inactive. */
2686 state
= UNIT_INACTIVE
;
2689 r
= sd_bus_message_read(reply
, "o", &path
);
2691 return bus_log_parse_error(r
);
2693 r
= sd_bus_get_property_string(
2695 "org.freedesktop.systemd1",
2697 "org.freedesktop.systemd1.Unit",
2702 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2704 state
= unit_active_state_from_string(buf
);
2705 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2706 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2711 *active_state
= state
;
2715 static int check_triggering_units(
2719 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2720 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2721 _cleanup_strv_free_
char **triggered_by
= NULL
;
2722 bool print_warning_label
= true;
2723 UnitActiveState active_state
;
2727 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2729 return log_error_errno(r
, "Failed to mangle unit name: %m");
2731 path
= unit_dbus_path_from_name(n
);
2735 r
= sd_bus_get_property_string(
2737 "org.freedesktop.systemd1",
2739 "org.freedesktop.systemd1.Unit",
2744 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2746 if (streq(load_state
, "masked"))
2749 r
= sd_bus_get_property_strv(
2751 "org.freedesktop.systemd1",
2753 "org.freedesktop.systemd1.Unit",
2758 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2760 STRV_FOREACH(i
, triggered_by
) {
2761 r
= get_state_one_unit(bus
, *i
, &active_state
);
2765 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2768 if (print_warning_label
) {
2769 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2770 print_warning_label
= false;
2773 log_warning(" %s", *i
);
2779 static const struct {
2782 } unit_actions
[] = {
2783 { "start", "StartUnit" },
2784 { "stop", "StopUnit" },
2785 { "condstop", "StopUnit" },
2786 { "reload", "ReloadUnit" },
2787 { "restart", "RestartUnit" },
2788 { "try-restart", "TryRestartUnit" },
2789 { "condrestart", "TryRestartUnit" },
2790 { "reload-or-restart", "ReloadOrRestartUnit" },
2791 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2792 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2793 { "condreload", "ReloadOrTryRestartUnit" },
2794 { "force-reload", "ReloadOrTryRestartUnit" }
2797 static const char *verb_to_method(const char *verb
) {
2800 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2801 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2802 return unit_actions
[i
].method
;
2807 static const char *method_to_verb(const char *method
) {
2810 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2811 if (streq_ptr(unit_actions
[i
].method
, method
))
2812 return unit_actions
[i
].verb
;
2824 static void wait_context_free(WaitContext
*c
) {
2825 c
->match
= sd_bus_slot_unref(c
->match
);
2826 c
->event
= sd_event_unref(c
->event
);
2827 c
->unit_paths
= set_free_free(c
->unit_paths
);
2830 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2831 WaitContext
*c
= userdata
;
2835 path
= sd_bus_message_get_path(m
);
2836 if (!set_contains(c
->unit_paths
, path
))
2839 /* Check if ActiveState changed to inactive/failed */
2840 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2841 r
= sd_bus_message_skip(m
, "s");
2843 return bus_log_parse_error(r
);
2845 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2847 return bus_log_parse_error(r
);
2849 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2852 r
= sd_bus_message_read(m
, "s", &s
);
2854 return bus_log_parse_error(r
);
2856 if (streq(s
, "ActiveState")) {
2859 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2861 return bus_log_parse_error(r
);
2863 r
= sd_bus_message_read(m
, "s", &s
);
2865 return bus_log_parse_error(r
);
2867 is_failed
= streq(s
, "failed");
2868 if (streq(s
, "inactive") || is_failed
) {
2869 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2870 free(set_remove(c
->unit_paths
, path
));
2871 c
->any_failed
= c
->any_failed
|| is_failed
;
2873 log_debug("ActiveState on %s changed to %s", path
, s
);
2875 break; /* no need to dissect the rest of the message */
2877 /* other property */
2878 r
= sd_bus_message_skip(m
, "v");
2880 return bus_log_parse_error(r
);
2882 r
= sd_bus_message_exit_container(m
);
2884 return bus_log_parse_error(r
);
2887 return bus_log_parse_error(r
);
2889 if (set_isempty(c
->unit_paths
))
2890 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2895 static int start_unit_one(
2900 sd_bus_error
*error
,
2902 WaitContext
*wait_context
) {
2904 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2914 _cleanup_free_
char *unit_path
= NULL
;
2917 log_debug("Watching for property changes of %s", name
);
2918 r
= sd_bus_call_method(
2920 "org.freedesktop.systemd1",
2921 "/org/freedesktop/systemd1",
2922 "org.freedesktop.systemd1.Manager",
2928 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2930 unit_path
= unit_dbus_path_from_name(name
);
2934 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2936 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2938 mt
= strjoina("type='signal',"
2939 "interface='org.freedesktop.DBus.Properties',"
2940 "path='", unit_path
, "',"
2941 "member='PropertiesChanged'");
2942 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2944 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2947 log_debug("%s manager for %s on %s, %s",
2948 arg_dry_run
? "Would call" : "Calling",
2949 method
, name
, mode
);
2953 r
= sd_bus_call_method(
2955 "org.freedesktop.systemd1",
2956 "/org/freedesktop/systemd1",
2957 "org.freedesktop.systemd1.Manager",
2965 /* There's always a fallback possible for legacy actions. */
2966 if (arg_action
!= ACTION_SYSTEMCTL
)
2969 verb
= method_to_verb(method
);
2971 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2973 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2974 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2975 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2976 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2977 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2978 name
[0] == '-' ? " --" : "",
2984 r
= sd_bus_message_read(reply
, "o", &path
);
2986 return bus_log_parse_error(r
);
2988 if (need_daemon_reload(bus
, name
) > 0)
2989 warn_unit_file_changed(name
);
2992 log_debug("Adding %s to the set", path
);
2993 r
= bus_wait_for_jobs_add(w
, path
);
3001 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
3002 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
3009 STRV_FOREACH(name
, names
) {
3013 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
3015 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
3017 return log_error_errno(r
, "Failed to mangle name: %m");
3019 if (string_is_glob(t
))
3020 r
= strv_consume(&globs
, t
);
3022 r
= strv_consume(&mangled
, t
);
3027 /* Query the manager only if any of the names are a glob, since
3028 * this is fairly expensive */
3029 if (!strv_isempty(globs
)) {
3030 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3031 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
3032 size_t allocated
, n
;
3034 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
3038 n
= strv_length(mangled
);
3041 for (i
= 0; i
< r
; i
++) {
3042 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
3045 mangled
[n
] = strdup(unit_infos
[i
].id
);
3049 mangled
[++n
] = NULL
;
3054 mangled
= NULL
; /* do not free */
3059 static const struct {
3063 } action_table
[_ACTION_MAX
] = {
3064 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3065 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3066 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3067 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3068 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3069 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3070 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3071 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3072 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3073 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3074 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3075 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3076 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3077 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3078 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3081 static enum action
verb_to_action(const char *verb
) {
3084 for (i
= 0; i
< _ACTION_MAX
; i
++)
3085 if (streq_ptr(action_table
[i
].verb
, verb
))
3088 return _ACTION_INVALID
;
3091 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3092 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3093 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3094 _cleanup_strv_free_
char **names
= NULL
;
3096 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3100 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3101 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3105 /* we cannot do sender tracking on the private bus, so we need the full
3106 * one for RefUnit to implement --wait */
3107 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3111 ask_password_agent_open_if_enabled();
3112 polkit_agent_open_maybe();
3114 if (arg_action
== ACTION_SYSTEMCTL
) {
3117 action
= verb_to_action(argv
[0]);
3119 if (action
!= _ACTION_INVALID
) {
3120 method
= "StartUnit";
3121 mode
= action_table
[action
].mode
;
3122 one_name
= action_table
[action
].target
;
3124 if (streq(argv
[0], "isolate")) {
3125 method
= "StartUnit";
3130 method
= verb_to_method(argv
[0]);
3131 mode
= arg_job_mode
;
3136 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3137 assert(action_table
[arg_action
].target
);
3138 assert(action_table
[arg_action
].mode
);
3140 method
= "StartUnit";
3141 mode
= action_table
[arg_action
].mode
;
3142 one_name
= action_table
[arg_action
].target
;
3146 names
= strv_new(one_name
, NULL
);
3148 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3150 return log_error_errno(r
, "Failed to expand names: %m");
3153 if (!arg_no_block
) {
3154 r
= bus_wait_for_jobs_new(bus
, &w
);
3156 return log_error_errno(r
, "Could not watch jobs: %m");
3160 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3162 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3163 if (!wait_context
.unit_paths
)
3166 r
= sd_bus_call_method(
3168 "org.freedesktop.systemd1",
3169 "/org/freedesktop/systemd1",
3170 "org.freedesktop.systemd1.Manager",
3175 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3176 r
= sd_event_default(&wait_context
.event
);
3178 return log_error_errno(r
, "Failed to allocate event loop: %m");
3179 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3181 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3184 STRV_FOREACH(name
, names
) {
3185 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3188 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3189 if (r
>= 0 && q
< 0)
3190 r
= translate_bus_error_to_exit_status(q
, &error
);
3193 if (!arg_no_block
) {
3194 int q
, arg_count
= 0;
3195 const char* extra_args
[4] = {};
3197 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3198 extra_args
[arg_count
++] = "--user";
3200 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3201 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3202 extra_args
[arg_count
++] = "-H";
3203 extra_args
[arg_count
++] = arg_host
;
3204 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3205 extra_args
[arg_count
++] = "-M";
3206 extra_args
[arg_count
++] = arg_host
;
3209 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3213 /* When stopping units, warn if they can still be triggered by
3214 * another active unit (socket, path, timer) */
3215 if (!arg_quiet
&& streq(method
, "StopUnit"))
3216 STRV_FOREACH(name
, names
)
3217 check_triggering_units(bus
, *name
);
3220 if (r
>= 0 && arg_wait
) {
3222 q
= sd_event_loop(wait_context
.event
);
3224 return log_error_errno(q
, "Failed to run event loop: %m");
3225 if (wait_context
.any_failed
)
3233 static int logind_set_wall_message(void) {
3234 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3236 _cleanup_free_
char *m
= NULL
;
3239 r
= acquire_bus(BUS_FULL
, &bus
);
3243 m
= strv_join(arg_wall
, " ");
3247 r
= sd_bus_call_method(
3249 "org.freedesktop.login1",
3250 "/org/freedesktop/login1",
3251 "org.freedesktop.login1.Manager",
3260 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3265 /* Ask systemd-logind, which might grant access to unprivileged users
3266 * through PolicyKit */
3267 static int logind_reboot(enum action a
) {
3269 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3270 const char *method
, *description
;
3274 r
= acquire_bus(BUS_FULL
, &bus
);
3280 case ACTION_POWEROFF
:
3281 method
= "PowerOff";
3282 description
= "power off system";
3287 description
= "reboot system";
3292 description
= "halt system";
3295 case ACTION_SUSPEND
:
3297 description
= "suspend system";
3300 case ACTION_HIBERNATE
:
3301 method
= "Hibernate";
3302 description
= "hibernate system";
3305 case ACTION_HYBRID_SLEEP
:
3306 method
= "HybridSleep";
3307 description
= "put system into hybrid sleep";
3314 polkit_agent_open_maybe();
3315 (void) logind_set_wall_message();
3317 r
= sd_bus_call_method(
3319 "org.freedesktop.login1",
3320 "/org/freedesktop/login1",
3321 "org.freedesktop.login1.Manager",
3325 "b", arg_ask_password
);
3327 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3335 static int logind_check_inhibitors(enum action a
) {
3337 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3338 _cleanup_strv_free_
char **sessions
= NULL
;
3339 const char *what
, *who
, *why
, *mode
;
3346 if (arg_ignore_inhibitors
|| arg_force
> 0)
3358 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3361 r
= acquire_bus(BUS_FULL
, &bus
);
3365 r
= sd_bus_call_method(
3367 "org.freedesktop.login1",
3368 "/org/freedesktop/login1",
3369 "org.freedesktop.login1.Manager",
3375 /* If logind is not around, then there are no inhibitors... */
3378 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3380 return bus_log_parse_error(r
);
3382 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3383 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3384 _cleanup_strv_free_
char **sv
= NULL
;
3386 if (!streq(mode
, "block"))
3389 sv
= strv_split(what
, ":");
3393 if (!pid_is_valid((pid_t
) pid
)) {
3394 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3398 if (!strv_contains(sv
,
3403 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3406 get_process_comm(pid
, &comm
);
3407 user
= uid_to_name(uid
);
3409 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3410 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3415 return bus_log_parse_error(r
);
3417 r
= sd_bus_message_exit_container(reply
);
3419 return bus_log_parse_error(r
);
3421 /* Check for current sessions */
3422 sd_get_sessions(&sessions
);
3423 STRV_FOREACH(s
, sessions
) {
3424 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3426 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3429 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3432 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3435 sd_session_get_tty(*s
, &tty
);
3436 sd_session_get_seat(*s
, &seat
);
3437 sd_session_get_service(*s
, &service
);
3438 user
= uid_to_name(uid
);
3440 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3447 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3448 action_table
[a
].verb
);
3456 static int logind_prepare_firmware_setup(void) {
3458 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3462 r
= acquire_bus(BUS_FULL
, &bus
);
3466 r
= sd_bus_call_method(
3468 "org.freedesktop.login1",
3469 "/org/freedesktop/login1",
3470 "org.freedesktop.login1.Manager",
3471 "SetRebootToFirmwareSetup",
3476 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3480 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3485 static int prepare_firmware_setup(void) {
3488 if (!arg_firmware_setup
)
3491 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3493 r
= efi_set_reboot_to_firmware(true);
3495 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3500 return logind_prepare_firmware_setup();
3503 static int load_kexec_kernel(void) {
3504 _cleanup_(boot_config_free
) BootConfig config
= {};
3505 _cleanup_free_
char *kernel
= NULL
, *initrd
= NULL
, *options
= NULL
;
3510 if (kexec_loaded()) {
3511 log_debug("Kexec kernel already loaded.");
3515 r
= find_esp(&arg_esp_path
, NULL
, NULL
, NULL
, NULL
);
3517 return log_error_errno(r
, "Cannot find the ESP partition mount point: %m");
3519 r
= boot_entries_load_config(arg_esp_path
, &config
);
3521 return log_error_errno(r
, "Failed to load bootspec config from \"%s/loader\": %m",
3524 if (config
.default_entry
< 0) {
3525 log_error("No entry suitable as default, refusing to guess.");
3528 e
= &config
.entries
[config
.default_entry
];
3530 if (strv_length(e
->initrd
) > 1) {
3531 log_error("Boot entry specifies multiple initrds, which is not supported currently.");
3535 kernel
= path_join(NULL
, arg_esp_path
, e
->kernel
);
3536 if (!strv_isempty(e
->initrd
))
3537 initrd
= path_join(NULL
, arg_esp_path
, *e
->initrd
);
3538 options
= strv_join(e
->options
, " ");
3542 log_debug("%s kexec kernel %s initrd %s options \"%s\".",
3543 arg_dry_run
? "Would load" : "loading",
3544 kernel
, initrd
, options
);
3550 return log_error_errno(errno
, "Failed to fork: %m");
3551 else if (pid
== 0) {
3553 const char* const args
[] = {
3556 "--append", options
,
3557 initrd
? "--initrd" : NULL
, initrd
,
3562 (void) reset_all_signal_handlers();
3563 (void) reset_signal_mask();
3564 assert_se(prctl(PR_SET_PDEATHSIG
, SIGTERM
) == 0);
3566 execv(args
[0], (char * const *) args
);
3567 _exit(EXIT_FAILURE
);
3569 return wait_for_terminate_and_warn("kexec", pid
, true);
3572 static int set_exit_code(uint8_t code
) {
3573 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3577 r
= acquire_bus(BUS_MANAGER
, &bus
);
3581 r
= sd_bus_call_method(
3583 "org.freedesktop.systemd1",
3584 "/org/freedesktop/systemd1",
3585 "org.freedesktop.systemd1.Manager",
3591 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3596 static int start_special(int argc
, char *argv
[], void *userdata
) {
3599 bool termination_action
; /* an action that terminates the manager,
3600 * can be performed also by signal. */
3604 a
= verb_to_action(argv
[0]);
3606 r
= logind_check_inhibitors(a
);
3610 if (arg_force
>= 2 && geteuid() != 0) {
3611 log_error("Must be root.");
3615 r
= prepare_firmware_setup();
3619 if (a
== ACTION_REBOOT
&& argc
> 1) {
3620 r
= update_reboot_parameter_and_warn(argv
[1]);
3624 } else if (a
== ACTION_KEXEC
) {
3625 r
= load_kexec_kernel();
3629 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3632 /* If the exit code is not given on the command line,
3633 * don't reset it to zero: just keep it as it might
3634 * have been set previously. */
3636 r
= safe_atou8(argv
[1], &code
);
3638 return log_error_errno(r
, "Invalid exit code.");
3640 r
= set_exit_code(code
);
3645 termination_action
= IN_SET(a
,
3649 if (termination_action
&& arg_force
>= 2)
3652 if (arg_force
>= 1 &&
3653 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3654 r
= trivial_method(argc
, argv
, userdata
);
3656 /* First try logind, to allow authentication with polkit */
3663 ACTION_HYBRID_SLEEP
)) {
3665 r
= logind_reboot(a
);
3668 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3669 /* requested operation is not supported or already in progress */
3672 /* On all other errors, try low-level operation. In order to minimize the difference between
3673 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3674 * logind's shutdown operations are always non-blocking. */
3676 arg_no_block
= true;
3678 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3679 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3680 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3681 arg_no_block
= true;
3683 r
= start_unit(argc
, argv
, userdata
);
3686 if (termination_action
&& arg_force
< 2 &&
3687 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3688 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3693 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3694 /* Like start_special above, but raises an error when running in user mode */
3696 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3697 log_error("Bad action for %s mode.",
3698 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3702 return start_special(argc
, argv
, userdata
);
3705 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3706 _cleanup_strv_free_
char **names
= NULL
;
3707 UnitActiveState active_state
;
3713 r
= acquire_bus(BUS_MANAGER
, &bus
);
3717 r
= expand_names(bus
, args
, NULL
, &names
);
3719 return log_error_errno(r
, "Failed to expand names: %m");
3721 STRV_FOREACH(name
, names
) {
3722 r
= get_state_one_unit(bus
, *name
, &active_state
);
3727 puts(unit_active_state_to_string(active_state
));
3729 for (i
= 0; i
< nb_states
; ++i
)
3730 if (good_states
[i
] == active_state
)
3734 /* use the given return code for the case that we won't find
3735 * any unit which matches the list */
3736 return found
? 0 : code
;
3739 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3740 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3741 /* According to LSB: 3, "program is not running" */
3742 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3745 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3746 const UnitActiveState states
[] = { UNIT_FAILED
};
3747 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3750 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3751 _cleanup_strv_free_
char **names
= NULL
;
3752 char *kill_who
= NULL
, **name
;
3756 r
= acquire_bus(BUS_MANAGER
, &bus
);
3760 polkit_agent_open_maybe();
3763 arg_kill_who
= "all";
3765 /* --fail was specified */
3766 if (streq(arg_job_mode
, "fail"))
3767 kill_who
= strjoina(arg_kill_who
, "-fail");
3769 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3771 return log_error_errno(r
, "Failed to expand names: %m");
3773 STRV_FOREACH(name
, names
) {
3774 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3776 q
= sd_bus_call_method(
3778 "org.freedesktop.systemd1",
3779 "/org/freedesktop/systemd1",
3780 "org.freedesktop.systemd1.Manager",
3784 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3786 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3795 typedef struct ExecStatusInfo
{
3803 usec_t start_timestamp
;
3804 usec_t exit_timestamp
;
3809 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3812 static void exec_status_info_free(ExecStatusInfo
*i
) {
3821 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3822 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3825 int32_t code
, status
;
3831 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3833 return bus_log_parse_error(r
);
3837 r
= sd_bus_message_read(m
, "s", &path
);
3839 return bus_log_parse_error(r
);
3841 i
->path
= strdup(path
);
3845 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3847 return bus_log_parse_error(r
);
3849 r
= sd_bus_message_read(m
,
3852 &start_timestamp
, &start_timestamp_monotonic
,
3853 &exit_timestamp
, &exit_timestamp_monotonic
,
3857 return bus_log_parse_error(r
);
3860 i
->start_timestamp
= (usec_t
) start_timestamp
;
3861 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3862 i
->pid
= (pid_t
) pid
;
3866 r
= sd_bus_message_exit_container(m
);
3868 return bus_log_parse_error(r
);
3873 typedef struct UnitCondition
{
3880 LIST_FIELDS(struct UnitCondition
, conditions
);
3883 static void unit_condition_free(UnitCondition
*c
) {
3892 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3894 typedef struct UnitStatusInfo
{
3896 const char *load_state
;
3897 const char *active_state
;
3898 const char *sub_state
;
3899 const char *unit_file_state
;
3900 const char *unit_file_preset
;
3902 const char *description
;
3903 const char *following
;
3905 char **documentation
;
3907 const char *fragment_path
;
3908 const char *source_path
;
3909 const char *control_group
;
3911 char **dropin_paths
;
3913 const char *load_error
;
3916 usec_t inactive_exit_timestamp
;
3917 usec_t inactive_exit_timestamp_monotonic
;
3918 usec_t active_enter_timestamp
;
3919 usec_t active_exit_timestamp
;
3920 usec_t inactive_enter_timestamp
;
3922 bool need_daemon_reload
;
3928 const char *status_text
;
3929 const char *pid_file
;
3933 usec_t start_timestamp
;
3934 usec_t exit_timestamp
;
3936 int exit_code
, exit_status
;
3938 usec_t condition_timestamp
;
3939 bool condition_result
;
3940 LIST_HEAD(UnitCondition
, conditions
);
3942 usec_t assert_timestamp
;
3944 bool failed_assert_trigger
;
3945 bool failed_assert_negate
;
3946 const char *failed_assert
;
3947 const char *failed_assert_parameter
;
3948 usec_t next_elapse_real
;
3949 usec_t next_elapse_monotonic
;
3952 unsigned n_accepted
;
3953 unsigned n_connections
;
3956 /* Pairs of type, path */
3960 const char *sysfs_path
;
3962 /* Mount, Automount */
3969 uint64_t memory_current
;
3970 uint64_t memory_low
;
3971 uint64_t memory_high
;
3972 uint64_t memory_max
;
3973 uint64_t memory_swap_max
;
3974 uint64_t memory_limit
;
3975 uint64_t cpu_usage_nsec
;
3976 uint64_t tasks_current
;
3979 uint64_t ip_ingress_bytes
;
3980 uint64_t ip_egress_bytes
;
3982 LIST_HEAD(ExecStatusInfo
, exec
);
3985 static void unit_status_info_free(UnitStatusInfo
*info
) {
3989 strv_free(info
->documentation
);
3990 strv_free(info
->dropin_paths
);
3991 strv_free(info
->listen
);
3993 while ((c
= info
->conditions
)) {
3994 LIST_REMOVE(conditions
, info
->conditions
, c
);
3995 unit_condition_free(c
);
3998 while ((p
= info
->exec
)) {
3999 LIST_REMOVE(exec
, info
->exec
, p
);
4000 exec_status_info_free(p
);
4004 static void print_status_info(
4010 const char *active_on
, *active_off
, *on
, *off
, *ss
;
4012 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
4013 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
4020 /* This shows pretty information about a unit. See
4021 * print_property() for a low-level property printer */
4023 if (streq_ptr(i
->active_state
, "failed")) {
4024 active_on
= ansi_highlight_red();
4025 active_off
= ansi_normal();
4026 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
4027 active_on
= ansi_highlight_green();
4028 active_off
= ansi_normal();
4030 active_on
= active_off
= "";
4032 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
4034 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
4035 printf(" - %s", i
->description
);
4040 printf(" Follow: unit currently follows state of %s\n", i
->following
);
4042 if (streq_ptr(i
->load_state
, "error")) {
4043 on
= ansi_highlight_red();
4044 off
= ansi_normal();
4048 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
4050 if (i
->load_error
!= 0)
4051 printf(" Loaded: %s%s%s (Reason: %s)\n",
4052 on
, strna(i
->load_state
), off
, i
->load_error
);
4053 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
4054 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
4055 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
4056 else if (path
&& !isempty(i
->unit_file_state
))
4057 printf(" Loaded: %s%s%s (%s; %s)\n",
4058 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
4060 printf(" Loaded: %s%s%s (%s)\n",
4061 on
, strna(i
->load_state
), off
, path
);
4063 printf(" Loaded: %s%s%s\n",
4064 on
, strna(i
->load_state
), off
);
4067 printf("Transient: yes\n");
4069 if (!strv_isempty(i
->dropin_paths
)) {
4070 _cleanup_free_
char *dir
= NULL
;
4074 STRV_FOREACH(dropin
, i
->dropin_paths
) {
4075 if (! dir
|| last
) {
4076 printf(dir
? " " : " Drop-In: ");
4080 dir
= dirname_malloc(*dropin
);
4086 printf("%s\n %s", dir
,
4087 special_glyph(TREE_RIGHT
));
4090 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4092 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4096 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4098 printf(" Active: %s%s (%s)%s",
4099 active_on
, strna(i
->active_state
), ss
, active_off
);
4101 printf(" Active: %s%s%s",
4102 active_on
, strna(i
->active_state
), active_off
);
4104 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4105 printf(" (Result: %s)", i
->result
);
4107 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4108 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4109 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4110 i
->active_exit_timestamp
;
4112 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4113 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4116 printf(" since %s; %s\n", s2
, s1
);
4118 printf(" since %s\n", s2
);
4122 if (endswith(i
->id
, ".timer")) {
4123 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4124 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4125 char *next_rel_time
, *next_time
;
4126 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4127 i
->next_elapse_monotonic
};
4130 printf(" Trigger: ");
4132 dual_timestamp_get(&nw
);
4133 next_elapse
= calc_next_elapse(&nw
, &next
);
4134 next_rel_time
= format_timestamp_relative(tstamp1
,
4137 next_time
= format_timestamp(tstamp2
,
4141 if (next_time
&& next_rel_time
)
4142 printf("%s; %s\n", next_time
, next_rel_time
);
4147 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4151 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4152 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4154 printf("Condition: start %scondition failed%s at %s%s%s\n",
4155 ansi_highlight_yellow(), ansi_normal(),
4156 s2
, s1
? "; " : "", strempty(s1
));
4158 LIST_FOREACH(conditions
, c
, i
->conditions
)
4159 if (c
->tristate
< 0)
4162 LIST_FOREACH(conditions
, c
, i
->conditions
)
4163 if (c
->tristate
< 0)
4164 printf(" %s %s=%s%s%s was not met\n",
4165 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4167 c
->trigger
? "|" : "",
4168 c
->negate
? "!" : "",
4172 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4173 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4174 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4176 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4177 ansi_highlight_red(), ansi_normal(),
4178 s2
, s1
? "; " : "", strempty(s1
));
4179 if (i
->failed_assert_trigger
)
4180 printf(" none of the trigger assertions were met\n");
4181 else if (i
->failed_assert
)
4182 printf(" %s=%s%s was not met\n",
4184 i
->failed_assert_negate
? "!" : "",
4185 i
->failed_assert_parameter
);
4189 printf(" Device: %s\n", i
->sysfs_path
);
4191 printf(" Where: %s\n", i
->where
);
4193 printf(" What: %s\n", i
->what
);
4195 STRV_FOREACH(t
, i
->documentation
)
4196 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4198 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4199 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4202 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4204 LIST_FOREACH(exec
, p
, i
->exec
) {
4205 _cleanup_free_
char *argv
= NULL
;
4208 /* Only show exited processes here */
4212 argv
= strv_join(p
->argv
, " ");
4213 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4215 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4217 on
= ansi_highlight_red();
4218 off
= ansi_normal();
4222 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4224 if (p
->code
== CLD_EXITED
) {
4227 printf("status=%i", p
->status
);
4229 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4234 printf("signal=%s", signal_to_string(p
->status
));
4236 printf(")%s\n", off
);
4238 if (i
->main_pid
== p
->pid
&&
4239 i
->start_timestamp
== p
->start_timestamp
&&
4240 i
->exit_timestamp
== p
->start_timestamp
)
4241 /* Let's not show this twice */
4244 if (p
->pid
== i
->control_pid
)
4248 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4249 if (i
->main_pid
> 0) {
4250 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4253 _cleanup_free_
char *comm
= NULL
;
4254 (void) get_process_comm(i
->main_pid
, &comm
);
4256 printf(" (%s)", comm
);
4257 } else if (i
->exit_code
> 0) {
4258 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4260 if (i
->exit_code
== CLD_EXITED
) {
4263 printf("status=%i", i
->exit_status
);
4265 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4270 printf("signal=%s", signal_to_string(i
->exit_status
));
4275 if (i
->control_pid
> 0) {
4276 _cleanup_free_
char *c
= NULL
;
4278 if (i
->main_pid
> 0)
4279 fputs("; Control PID: ", stdout
);
4281 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4283 printf(PID_FMT
, i
->control_pid
);
4285 (void) get_process_comm(i
->control_pid
, &c
);
4294 printf(" Status: \"%s\"\n", i
->status_text
);
4295 if (i
->status_errno
> 0)
4296 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4298 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4299 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4301 printf(" IP: %s in, %s out\n",
4302 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4303 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4306 if (i
->tasks_current
!= (uint64_t) -1) {
4307 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4309 if (i
->tasks_max
!= (uint64_t) -1)
4310 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4315 if (i
->memory_current
!= (uint64_t) -1) {
4316 char buf
[FORMAT_BYTES_MAX
];
4318 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4320 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4321 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4322 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4323 const char *prefix
= "";
4326 if (i
->memory_low
> 0) {
4327 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4330 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4331 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4334 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4335 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4338 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4339 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4342 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4343 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4351 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4352 char buf
[FORMAT_TIMESPAN_MAX
];
4353 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4356 if (i
->control_group
) {
4357 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4358 static const char prefix
[] = " ";
4361 printf(" CGroup: %s\n", i
->control_group
);
4364 if (c
> sizeof(prefix
) - 1)
4365 c
-= sizeof(prefix
) - 1;
4369 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4374 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4376 if (i
->main_pid
> 0)
4377 extra
[k
++] = i
->main_pid
;
4379 if (i
->control_pid
> 0)
4380 extra
[k
++] = i
->control_pid
;
4382 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4384 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4387 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4388 show_journal_by_unit(
4393 i
->inactive_exit_timestamp_monotonic
,
4396 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4397 SD_JOURNAL_LOCAL_ONLY
,
4398 arg_scope
== UNIT_FILE_SYSTEM
,
4401 if (i
->need_daemon_reload
)
4402 warn_unit_file_changed(i
->id
);
4405 static void show_unit_help(UnitStatusInfo
*i
) {
4410 if (!i
->documentation
) {
4411 log_info("Documentation for %s not known.", i
->id
);
4415 STRV_FOREACH(p
, i
->documentation
)
4416 if (startswith(*p
, "man:"))
4417 show_man_page(*p
+ 4, false);
4419 log_info("Can't show: %s", *p
);
4422 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4429 switch (contents
[0]) {
4431 case SD_BUS_TYPE_STRING
: {
4434 r
= sd_bus_message_read(m
, "s", &s
);
4436 return bus_log_parse_error(r
);
4439 if (streq(name
, "Id"))
4441 else if (streq(name
, "LoadState"))
4443 else if (streq(name
, "ActiveState"))
4444 i
->active_state
= s
;
4445 else if (streq(name
, "SubState"))
4447 else if (streq(name
, "Description"))
4449 else if (streq(name
, "FragmentPath"))
4450 i
->fragment_path
= s
;
4451 else if (streq(name
, "SourcePath"))
4454 else if (streq(name
, "DefaultControlGroup")) {
4456 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4458 i
->control_group
= e
;
4461 else if (streq(name
, "ControlGroup"))
4462 i
->control_group
= s
;
4463 else if (streq(name
, "StatusText"))
4465 else if (streq(name
, "PIDFile"))
4467 else if (streq(name
, "SysFSPath"))
4469 else if (streq(name
, "Where"))
4471 else if (streq(name
, "What"))
4473 else if (streq(name
, "Following"))
4475 else if (streq(name
, "UnitFileState"))
4476 i
->unit_file_state
= s
;
4477 else if (streq(name
, "UnitFilePreset"))
4478 i
->unit_file_preset
= s
;
4479 else if (streq(name
, "Result"))
4486 case SD_BUS_TYPE_BOOLEAN
: {
4489 r
= sd_bus_message_read(m
, "b", &b
);
4491 return bus_log_parse_error(r
);
4493 if (streq(name
, "Accept"))
4495 else if (streq(name
, "NeedDaemonReload"))
4496 i
->need_daemon_reload
= b
;
4497 else if (streq(name
, "ConditionResult"))
4498 i
->condition_result
= b
;
4499 else if (streq(name
, "AssertResult"))
4500 i
->assert_result
= b
;
4501 else if (streq(name
, "Transient"))
4507 case SD_BUS_TYPE_UINT32
: {
4510 r
= sd_bus_message_read(m
, "u", &u
);
4512 return bus_log_parse_error(r
);
4514 if (streq(name
, "MainPID")) {
4516 i
->main_pid
= (pid_t
) u
;
4519 } else if (streq(name
, "ControlPID"))
4520 i
->control_pid
= (pid_t
) u
;
4521 else if (streq(name
, "ExecMainPID")) {
4523 i
->main_pid
= (pid_t
) u
;
4524 } else if (streq(name
, "NAccepted"))
4526 else if (streq(name
, "NConnections"))
4527 i
->n_connections
= u
;
4532 case SD_BUS_TYPE_INT32
: {
4535 r
= sd_bus_message_read(m
, "i", &j
);
4537 return bus_log_parse_error(r
);
4539 if (streq(name
, "ExecMainCode"))
4540 i
->exit_code
= (int) j
;
4541 else if (streq(name
, "ExecMainStatus"))
4542 i
->exit_status
= (int) j
;
4543 else if (streq(name
, "StatusErrno"))
4544 i
->status_errno
= (int) j
;
4549 case SD_BUS_TYPE_UINT64
: {
4552 r
= sd_bus_message_read(m
, "t", &u
);
4554 return bus_log_parse_error(r
);
4556 if (streq(name
, "ExecMainStartTimestamp"))
4557 i
->start_timestamp
= (usec_t
) u
;
4558 else if (streq(name
, "ExecMainExitTimestamp"))
4559 i
->exit_timestamp
= (usec_t
) u
;
4560 else if (streq(name
, "ActiveEnterTimestamp"))
4561 i
->active_enter_timestamp
= (usec_t
) u
;
4562 else if (streq(name
, "InactiveEnterTimestamp"))
4563 i
->inactive_enter_timestamp
= (usec_t
) u
;
4564 else if (streq(name
, "InactiveExitTimestamp"))
4565 i
->inactive_exit_timestamp
= (usec_t
) u
;
4566 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4567 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4568 else if (streq(name
, "ActiveExitTimestamp"))
4569 i
->active_exit_timestamp
= (usec_t
) u
;
4570 else if (streq(name
, "ConditionTimestamp"))
4571 i
->condition_timestamp
= (usec_t
) u
;
4572 else if (streq(name
, "AssertTimestamp"))
4573 i
->assert_timestamp
= (usec_t
) u
;
4574 else if (streq(name
, "MemoryCurrent"))
4575 i
->memory_current
= u
;
4576 else if (streq(name
, "MemoryLow"))
4578 else if (streq(name
, "MemoryHigh"))
4580 else if (streq(name
, "MemoryMax"))
4582 else if (streq(name
, "MemorySwapMax"))
4583 i
->memory_swap_max
= u
;
4584 else if (streq(name
, "MemoryLimit"))
4585 i
->memory_limit
= u
;
4586 else if (streq(name
, "TasksCurrent"))
4587 i
->tasks_current
= u
;
4588 else if (streq(name
, "TasksMax"))
4590 else if (streq(name
, "CPUUsageNSec"))
4591 i
->cpu_usage_nsec
= u
;
4592 else if (streq(name
, "NextElapseUSecMonotonic"))
4593 i
->next_elapse_monotonic
= u
;
4594 else if (streq(name
, "NextElapseUSecRealtime"))
4595 i
->next_elapse_real
= u
;
4596 else if (streq(name
, "IPIngressBytes"))
4597 i
->ip_ingress_bytes
= u
;
4598 else if (streq(name
, "IPEgressBytes"))
4599 i
->ip_egress_bytes
= u
;
4604 case SD_BUS_TYPE_ARRAY
:
4606 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4607 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4609 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4611 return bus_log_parse_error(r
);
4613 info
= new0(ExecStatusInfo
, 1);
4617 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4619 info
->name
= strdup(name
);
4623 LIST_PREPEND(exec
, i
->exec
, info
);
4625 info
= new0(ExecStatusInfo
, 1);
4631 return bus_log_parse_error(r
);
4633 r
= sd_bus_message_exit_container(m
);
4635 return bus_log_parse_error(r
);
4639 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4640 const char *type
, *path
;
4642 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4644 return bus_log_parse_error(r
);
4646 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4648 r
= strv_extend(&i
->listen
, type
);
4652 r
= strv_extend(&i
->listen
, path
);
4657 return bus_log_parse_error(r
);
4659 r
= sd_bus_message_exit_container(m
);
4661 return bus_log_parse_error(r
);
4665 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4667 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4669 return bus_log_parse_error(r
);
4671 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4673 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4675 return bus_log_parse_error(r
);
4677 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4678 const char *cond
, *param
;
4679 int trigger
, negate
;
4682 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4684 return bus_log_parse_error(r
);
4686 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4687 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4689 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4691 c
= new0(UnitCondition
, 1);
4695 c
->name
= strdup(cond
);
4696 c
->param
= strdup(param
);
4697 if (!c
->name
|| !c
->param
)
4700 c
->trigger
= trigger
;
4702 c
->tristate
= state
;
4704 LIST_PREPEND(conditions
, i
->conditions
, c
);
4708 return bus_log_parse_error(r
);
4710 r
= sd_bus_message_exit_container(m
);
4712 return bus_log_parse_error(r
);
4714 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4715 const char *cond
, *param
;
4716 int trigger
, negate
;
4719 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4721 return bus_log_parse_error(r
);
4723 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4724 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4725 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4726 i
->failed_assert
= cond
;
4727 i
->failed_assert_trigger
= trigger
;
4728 i
->failed_assert_negate
= negate
;
4729 i
->failed_assert_parameter
= param
;
4733 return bus_log_parse_error(r
);
4735 r
= sd_bus_message_exit_container(m
);
4737 return bus_log_parse_error(r
);
4744 case SD_BUS_TYPE_STRUCT_BEGIN
:
4746 if (streq(name
, "LoadError")) {
4747 const char *n
, *message
;
4749 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4751 return bus_log_parse_error(r
);
4753 if (!isempty(message
))
4754 i
->load_error
= message
;
4767 r
= sd_bus_message_skip(m
, contents
);
4769 return bus_log_parse_error(r
);
4774 #define print_prop(name, fmt, ...) \
4777 printf(fmt "\n", __VA_ARGS__); \
4779 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4782 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4788 /* This is a low-level property printer, see
4789 * print_status_info() for the nicer output */
4791 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4792 /* skip what we didn't read */
4793 r
= sd_bus_message_skip(m
, contents
);
4797 switch (contents
[0]) {
4799 case SD_BUS_TYPE_STRUCT_BEGIN
:
4801 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4804 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4806 return bus_log_parse_error(r
);
4809 print_prop(name
, "%"PRIu32
, u
);
4811 print_prop(name
, "%s", "");
4815 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4818 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4820 return bus_log_parse_error(r
);
4822 if (arg_all
|| !isempty(s
))
4823 print_prop(name
, "%s", s
);
4827 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4828 const char *a
= NULL
, *b
= NULL
;
4830 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4832 return bus_log_parse_error(r
);
4834 if (arg_all
|| !isempty(a
) || !isempty(b
))
4835 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4838 } else if (streq_ptr(name
, "SystemCallFilter")) {
4839 _cleanup_strv_free_
char **l
= NULL
;
4842 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4844 return bus_log_parse_error(r
);
4846 r
= sd_bus_message_read(m
, "b", &whitelist
);
4848 return bus_log_parse_error(r
);
4850 r
= sd_bus_message_read_strv(m
, &l
);
4852 return bus_log_parse_error(r
);
4854 r
= sd_bus_message_exit_container(m
);
4856 return bus_log_parse_error(r
);
4858 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4863 fputs(name
, stdout
);
4870 STRV_FOREACH(i
, l
) {
4878 fputc('\n', stdout
);
4886 case SD_BUS_TYPE_ARRAY
:
4888 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4892 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4894 return bus_log_parse_error(r
);
4896 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4897 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4900 return bus_log_parse_error(r
);
4902 r
= sd_bus_message_exit_container(m
);
4904 return bus_log_parse_error(r
);
4908 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4909 const char *type
, *path
;
4911 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4913 return bus_log_parse_error(r
);
4915 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4916 print_prop(type
, "%s", path
);
4918 return bus_log_parse_error(r
);
4920 r
= sd_bus_message_exit_container(m
);
4922 return bus_log_parse_error(r
);
4926 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4927 const char *type
, *path
;
4929 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4931 return bus_log_parse_error(r
);
4933 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4937 printf("Listen%s=%s\n", type
, path
);
4939 return bus_log_parse_error(r
);
4941 r
= sd_bus_message_exit_container(m
);
4943 return bus_log_parse_error(r
);
4947 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4949 uint64_t value
, next_elapse
;
4951 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4953 return bus_log_parse_error(r
);
4955 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4956 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4958 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4959 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4960 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4963 return bus_log_parse_error(r
);
4965 r
= sd_bus_message_exit_container(m
);
4967 return bus_log_parse_error(r
);
4971 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4972 ExecStatusInfo info
= {};
4974 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4976 return bus_log_parse_error(r
);
4978 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4979 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4980 _cleanup_free_
char *tt
;
4982 tt
= strv_join(info
.argv
, " ");
4985 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4988 yes_no(info
.ignore
),
4989 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4990 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4992 sigchld_code_to_string(info
.code
),
4994 info
.code
== CLD_EXITED
? "" : "/",
4995 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4998 strv_free(info
.argv
);
5002 r
= sd_bus_message_exit_container(m
);
5004 return bus_log_parse_error(r
);
5008 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
5009 const char *path
, *rwm
;
5011 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
5013 return bus_log_parse_error(r
);
5015 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
5016 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
5018 return bus_log_parse_error(r
);
5020 r
= sd_bus_message_exit_container(m
);
5022 return bus_log_parse_error(r
);
5026 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
5027 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
5031 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
5033 return bus_log_parse_error(r
);
5035 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
5036 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
5038 return bus_log_parse_error(r
);
5040 r
= sd_bus_message_exit_container(m
);
5042 return bus_log_parse_error(r
);
5046 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
5047 (cgroup_io_limit_type_from_string(name
) >= 0 ||
5048 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
5052 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
5054 return bus_log_parse_error(r
);
5056 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
5057 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
5059 return bus_log_parse_error(r
);
5061 r
= sd_bus_message_exit_container(m
);
5063 return bus_log_parse_error(r
);
5067 } else if (contents
[1] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
5068 _cleanup_free_
char *h
= NULL
;
5073 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
5075 return bus_log_parse_error(r
);
5077 n
= base64mem(p
, sz
, &h
);
5081 print_prop(name
, "%s", h
);
5089 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
5091 return bus_log_parse_error(r
);
5094 r
= sd_bus_message_skip(m
, contents
);
5096 return bus_log_parse_error(r
);
5099 printf("%s=[unprintable]\n", name
);
5105 static int show_one(
5110 bool show_properties
,
5114 static const struct bus_properties_map property_map
[] = {
5115 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5116 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
5120 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5121 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5122 _cleanup_set_free_ Set
*found_properties
= NULL
;
5123 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
5124 .memory_current
= (uint64_t) -1,
5125 .memory_high
= CGROUP_LIMIT_MAX
,
5126 .memory_max
= CGROUP_LIMIT_MAX
,
5127 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5128 .memory_limit
= (uint64_t) -1,
5129 .cpu_usage_nsec
= (uint64_t) -1,
5130 .tasks_current
= (uint64_t) -1,
5131 .tasks_max
= (uint64_t) -1,
5132 .ip_ingress_bytes
= (uint64_t) -1,
5133 .ip_egress_bytes
= (uint64_t) -1,
5140 log_debug("Showing one %s", path
);
5142 r
= sd_bus_call_method(
5144 "org.freedesktop.systemd1",
5146 "org.freedesktop.DBus.Properties",
5152 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5155 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
5157 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5159 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5160 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
5161 "Unit %s could not be found.", unit
);
5163 if (streq(verb
, "status"))
5164 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5166 if (!streq(verb
, "show"))
5170 r
= sd_bus_message_rewind(reply
, true);
5172 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5175 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
5177 return bus_log_parse_error(r
);
5184 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
5185 const char *name
, *contents
;
5187 r
= sd_bus_message_read(reply
, "s", &name
);
5189 return bus_log_parse_error(r
);
5191 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
5193 return bus_log_parse_error(r
);
5195 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
5197 return bus_log_parse_error(r
);
5199 if (show_properties
) {
5200 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
5204 r
= set_put(found_properties
, name
);
5205 if (r
< 0 && r
!= EEXIST
)
5208 r
= print_property(name
, reply
, contents
);
5210 r
= status_property(name
, reply
, &info
, contents
);
5214 r
= sd_bus_message_exit_container(reply
);
5216 return bus_log_parse_error(r
);
5218 r
= sd_bus_message_exit_container(reply
);
5220 return bus_log_parse_error(r
);
5223 return bus_log_parse_error(r
);
5225 r
= sd_bus_message_exit_container(reply
);
5227 return bus_log_parse_error(r
);
5230 if (show_properties
) {
5233 STRV_FOREACH(pp
, arg_properties
)
5234 if (!set_contains(found_properties
, *pp
))
5235 log_debug("Property %s does not exist.", *pp
);
5237 } else if (streq(verb
, "help"))
5238 show_unit_help(&info
);
5239 else if (streq(verb
, "status")) {
5240 print_status_info(bus
, &info
, ellipsized
);
5242 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5243 r
= EXIT_PROGRAM_NOT_RUNNING
;
5245 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5251 static int get_unit_dbus_path_by_pid(
5256 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5257 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5261 r
= sd_bus_call_method(
5263 "org.freedesktop.systemd1",
5264 "/org/freedesktop/systemd1",
5265 "org.freedesktop.systemd1.Manager",
5271 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5273 r
= sd_bus_message_read(reply
, "o", &u
);
5275 return bus_log_parse_error(r
);
5285 static int show_all(
5288 bool show_properties
,
5292 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5293 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5298 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5302 pager_open(arg_no_pager
, false);
5306 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5308 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5309 _cleanup_free_
char *p
= NULL
;
5311 p
= unit_dbus_path_from_name(u
->id
);
5315 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5318 else if (r
> 0 && ret
== 0)
5325 static int show_system_status(sd_bus
*bus
) {
5326 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5327 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5328 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5329 _cleanup_free_
char *hn
= NULL
;
5330 const char *on
, *off
;
5333 hn
= gethostname_malloc();
5337 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, &mi
);
5339 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5341 if (streq_ptr(mi
.state
, "degraded")) {
5342 on
= ansi_highlight_red();
5343 off
= ansi_normal();
5344 } else if (streq_ptr(mi
.state
, "running")) {
5345 on
= ansi_highlight_green();
5346 off
= ansi_normal();
5348 on
= ansi_highlight_yellow();
5349 off
= ansi_normal();
5352 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5354 printf(" State: %s%s%s\n",
5355 on
, strna(mi
.state
), off
);
5357 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5358 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5360 printf(" Since: %s; %s\n",
5361 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5362 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5364 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5365 if (IN_SET(arg_transport
,
5366 BUS_TRANSPORT_LOCAL
,
5367 BUS_TRANSPORT_MACHINE
)) {
5368 static const char prefix
[] = " ";
5372 if (c
> sizeof(prefix
) - 1)
5373 c
-= sizeof(prefix
) - 1;
5377 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5383 static int show(int argc
, char *argv
[], void *userdata
) {
5384 bool show_properties
, show_status
, show_help
, new_line
= false;
5385 bool ellipsized
= false;
5391 show_properties
= streq(argv
[0], "show");
5392 show_status
= streq(argv
[0], "status");
5393 show_help
= streq(argv
[0], "help");
5395 if (show_help
&& argc
<= 1) {
5396 log_error("This command expects one or more unit names. Did you mean --help?");
5400 r
= acquire_bus(BUS_MANAGER
, &bus
);
5404 pager_open(arg_no_pager
, false);
5407 /* Increase max number of open files to 16K if we can, we
5408 * might needs this when browsing journal files, which might
5409 * be split up into many files. */
5410 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5412 /* If no argument is specified inspect the manager itself */
5413 if (show_properties
&& argc
<= 1)
5414 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5416 if (show_status
&& argc
<= 1) {
5418 show_system_status(bus
);
5422 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5424 _cleanup_free_
char **patterns
= NULL
;
5427 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5428 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5431 if (safe_atou32(*name
, &id
) < 0) {
5432 if (strv_push(&patterns
, *name
) < 0)
5436 } else if (show_properties
) {
5437 /* Interpret as job id */
5438 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5442 /* Interpret as PID */
5443 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5449 r
= unit_name_from_dbus_path(path
, &unit
);
5454 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5457 else if (r
> 0 && ret
== 0)
5461 if (!strv_isempty(patterns
)) {
5462 _cleanup_strv_free_
char **names
= NULL
;
5464 r
= expand_names(bus
, patterns
, NULL
, &names
);
5466 return log_error_errno(r
, "Failed to expand names: %m");
5468 STRV_FOREACH(name
, names
) {
5469 _cleanup_free_
char *path
;
5471 path
= unit_dbus_path_from_name(*name
);
5475 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5478 if (r
> 0 && ret
== 0)
5484 if (ellipsized
&& !arg_quiet
)
5485 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5490 static int cat_file(const char *filename
, bool newline
) {
5491 _cleanup_close_
int fd
;
5493 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5497 printf("%s%s# %s%s\n",
5498 newline
? "\n" : "",
5499 ansi_highlight_blue(),
5504 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5507 static int cat(int argc
, char *argv
[], void *userdata
) {
5508 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5509 _cleanup_strv_free_
char **names
= NULL
;
5515 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5516 log_error("Cannot remotely cat units.");
5520 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5522 return log_error_errno(r
, "Failed to determine unit paths: %m");
5524 r
= acquire_bus(BUS_MANAGER
, &bus
);
5528 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5530 return log_error_errno(r
, "Failed to expand names: %m");
5532 pager_open(arg_no_pager
, false);
5534 STRV_FOREACH(name
, names
) {
5535 _cleanup_free_
char *fragment_path
= NULL
;
5536 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5539 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5550 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5552 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5553 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5554 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5555 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5556 ansi_highlight_red(),
5558 ansi_highlight_red(),
5559 ansi_highlight_red(),
5560 ansi_highlight_red(),
5561 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5564 if (fragment_path
) {
5565 r
= cat_file(fragment_path
, false);
5567 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5570 STRV_FOREACH(path
, dropin_paths
) {
5571 r
= cat_file(*path
, path
== dropin_paths
);
5573 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5580 static int set_property(int argc
, char *argv
[], void *userdata
) {
5581 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5582 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5583 _cleanup_free_
char *n
= NULL
;
5587 r
= acquire_bus(BUS_MANAGER
, &bus
);
5591 polkit_agent_open_maybe();
5593 r
= sd_bus_message_new_method_call(
5596 "org.freedesktop.systemd1",
5597 "/org/freedesktop/systemd1",
5598 "org.freedesktop.systemd1.Manager",
5599 "SetUnitProperties");
5601 return bus_log_create_error(r
);
5603 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5605 return log_error_errno(r
, "Failed to mangle unit name: %m");
5607 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5609 return bus_log_create_error(r
);
5611 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5613 return bus_log_create_error(r
);
5615 r
= bus_append_unit_property_assignment_many(m
, strv_skip(argv
, 2));
5619 r
= sd_bus_message_close_container(m
);
5621 return bus_log_create_error(r
);
5623 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5625 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5630 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5631 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5632 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5637 r
= acquire_bus(BUS_MANAGER
, &bus
);
5641 polkit_agent_open_maybe();
5643 switch (arg_action
) {
5650 method
= "Reexecute";
5653 case ACTION_SYSTEMCTL
:
5654 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5655 /* "daemon-reload" */ "Reload";
5659 assert_not_reached("Unexpected action");
5662 r
= sd_bus_message_new_method_call(
5665 "org.freedesktop.systemd1",
5666 "/org/freedesktop/systemd1",
5667 "org.freedesktop.systemd1.Manager",
5670 return bus_log_create_error(r
);
5672 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5673 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5674 * their timeout, and for everything else there's the same time budget in place. */
5676 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5678 /* On reexecution, we expect a disconnect, not a reply */
5679 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5682 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5683 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5685 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5686 * old ways of doing things, hence don't log any error in that case here. */
5688 return r
< 0 ? r
: 0;
5691 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5692 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5700 r
= acquire_bus(BUS_MANAGER
, &bus
);
5704 polkit_agent_open_maybe();
5707 streq(argv
[0], "clear-jobs") ||
5708 streq(argv
[0], "cancel") ? "ClearJobs" :
5709 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5710 streq(argv
[0], "halt") ? "Halt" :
5711 streq(argv
[0], "reboot") ? "Reboot" :
5712 streq(argv
[0], "kexec") ? "KExec" :
5713 streq(argv
[0], "exit") ? "Exit" :
5714 /* poweroff */ "PowerOff";
5716 r
= sd_bus_call_method(
5718 "org.freedesktop.systemd1",
5719 "/org/freedesktop/systemd1",
5720 "org.freedesktop.systemd1.Manager",
5725 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5726 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5728 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5729 * old ways of doing things, hence don't log any error in that case here. */
5731 return r
< 0 ? r
: 0;
5734 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5735 _cleanup_strv_free_
char **names
= NULL
;
5741 return trivial_method(argc
, argv
, userdata
);
5743 r
= acquire_bus(BUS_MANAGER
, &bus
);
5747 polkit_agent_open_maybe();
5749 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5751 return log_error_errno(r
, "Failed to expand names: %m");
5753 STRV_FOREACH(name
, names
) {
5754 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5756 q
= sd_bus_call_method(
5758 "org.freedesktop.systemd1",
5759 "/org/freedesktop/systemd1",
5760 "org.freedesktop.systemd1.Manager",
5766 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5775 static int print_variable(const char *s
) {
5777 _cleanup_free_
char *esc
= NULL
;
5779 sep
= strchr(s
, '=');
5781 log_error("Invalid environment block");
5785 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5789 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5793 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5794 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5795 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5800 r
= acquire_bus(BUS_MANAGER
, &bus
);
5804 pager_open(arg_no_pager
, false);
5806 r
= sd_bus_get_property(
5808 "org.freedesktop.systemd1",
5809 "/org/freedesktop/systemd1",
5810 "org.freedesktop.systemd1.Manager",
5816 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5818 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5820 return bus_log_parse_error(r
);
5822 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5823 r
= print_variable(text
);
5828 return bus_log_parse_error(r
);
5830 r
= sd_bus_message_exit_container(reply
);
5832 return bus_log_parse_error(r
);
5837 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5838 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5839 _cleanup_free_
char *cmdline_init
= NULL
;
5840 const char *root
, *init
;
5844 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5845 log_error("Cannot switch root remotely.");
5849 if (argc
< 2 || argc
> 3) {
5850 log_error("Wrong number of arguments.");
5859 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5860 "init", &cmdline_init
,
5863 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5865 init
= cmdline_init
;
5868 init
= empty_to_null(init
);
5870 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5872 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5873 root_init_path
= strjoina(root
, "/", init
);
5875 /* If the passed init is actually the same as the
5876 * systemd binary, then let's suppress it. */
5877 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5881 /* Instruct PID1 to exclude us from its killing spree applied during
5882 * the transition. Otherwise we would exit with a failure status even
5883 * though the switch to the new root has succeed. */
5884 argv_cmdline
[0] = '@';
5886 r
= acquire_bus(BUS_MANAGER
, &bus
);
5890 /* If we are slow to exit after the root switch, the new systemd instance
5891 * will send us a signal to terminate. Just ignore it and exit normally.
5892 * This way the unit does not end up as failed.
5894 r
= ignore_signals(SIGTERM
, -1);
5896 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5898 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5900 r
= sd_bus_call_method(
5902 "org.freedesktop.systemd1",
5903 "/org/freedesktop/systemd1",
5904 "org.freedesktop.systemd1.Manager",
5910 (void) default_signals(SIGTERM
, -1);
5912 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5918 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5919 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5920 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5928 r
= acquire_bus(BUS_MANAGER
, &bus
);
5932 polkit_agent_open_maybe();
5934 method
= streq(argv
[0], "set-environment")
5936 : "UnsetEnvironment";
5938 r
= sd_bus_message_new_method_call(
5941 "org.freedesktop.systemd1",
5942 "/org/freedesktop/systemd1",
5943 "org.freedesktop.systemd1.Manager",
5946 return bus_log_create_error(r
);
5948 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5950 return bus_log_create_error(r
);
5952 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5954 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5959 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5960 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5961 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5965 r
= acquire_bus(BUS_MANAGER
, &bus
);
5969 polkit_agent_open_maybe();
5971 r
= sd_bus_message_new_method_call(
5974 "org.freedesktop.systemd1",
5975 "/org/freedesktop/systemd1",
5976 "org.freedesktop.systemd1.Manager",
5979 return bus_log_create_error(r
);
5982 r
= sd_bus_message_append_strv(m
, environ
);
5986 r
= sd_bus_message_open_container(m
, 'a', "s");
5988 return bus_log_create_error(r
);
5990 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5992 if (!env_name_is_valid(*a
)) {
5993 log_error("Not a valid environment variable name: %s", *a
);
5997 STRV_FOREACH(b
, environ
) {
6000 eq
= startswith(*b
, *a
);
6001 if (eq
&& *eq
== '=') {
6003 r
= sd_bus_message_append(m
, "s", *b
);
6005 return bus_log_create_error(r
);
6012 r
= sd_bus_message_close_container(m
);
6015 return bus_log_create_error(r
);
6017 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
6019 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
6024 static int enable_sysv_units(const char *verb
, char **args
) {
6027 #if HAVE_SYSV_COMPAT
6028 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
6031 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
6033 if (arg_scope
!= UNIT_FILE_SYSTEM
)
6036 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
6039 if (!STR_IN_SET(verb
,
6045 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
6052 const char *argv
[] = {
6053 ROOTLIBEXECDIR
"/systemd-sysv-install",
6060 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
6061 bool found_native
= false, found_sysv
;
6070 if (!endswith(name
, ".service"))
6073 if (path_is_absolute(name
))
6076 j
= unit_file_exists(arg_scope
, &paths
, name
);
6077 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
6078 return log_error_errno(j
, "Failed to lookup unit file state: %m");
6079 found_native
= j
!= 0;
6081 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
6082 * prefer the native unit */
6083 if (found_native
&& streq(verb
, "is-enabled"))
6086 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
6090 p
[strlen(p
) - strlen(".service")] = 0;
6091 found_sysv
= access(p
, F_OK
) >= 0;
6097 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
6099 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
6102 if (!isempty(arg_root
))
6103 argv
[c
++] = q
= strappend("--root=", arg_root
);
6106 argv
[c
++] = basename(p
);
6109 l
= strv_join((char**)argv
, " ");
6114 log_info("Executing: %s", l
);
6118 return log_error_errno(errno
, "Failed to fork: %m");
6119 else if (pid
== 0) {
6122 (void) reset_all_signal_handlers();
6123 (void) reset_signal_mask();
6125 execv(argv
[0], (char**) argv
);
6126 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
6127 _exit(EXIT_FAILURE
);
6130 j
= wait_for_terminate(pid
, &status
);
6132 return log_error_errno(j
, "Failed to wait for child: %m");
6134 if (status
.si_code
== CLD_EXITED
) {
6135 if (streq(verb
, "is-enabled")) {
6136 if (status
.si_status
== 0) {
6145 } else if (status
.si_status
!= 0)
6146 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
6148 log_error("Unexpected waitid() result.");
6155 /* Remove this entry, so that we don't try enabling it as native unit */
6158 assert(args
[f
] == name
);
6159 strv_remove(args
, name
);
6166 static int mangle_names(char **original_names
, char ***mangled_names
) {
6167 char **i
, **l
, **name
;
6170 l
= i
= new(char*, strv_length(original_names
) + 1);
6174 STRV_FOREACH(name
, original_names
) {
6176 /* When enabling units qualified path names are OK,
6177 * too, hence allow them explicitly. */
6179 if (is_path(*name
)) {
6186 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
6190 return log_error_errno(r
, "Failed to mangle unit name: %m");
6203 static int normalize_filenames(char **names
) {
6207 STRV_FOREACH(u
, names
)
6208 if (!path_is_absolute(*u
)) {
6209 char* normalized_path
;
6211 if (!isempty(arg_root
)) {
6212 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6216 if (!strchr(*u
,'/')) {
6217 log_error("Link argument does contain at least one directory separator: %s", *u
);
6221 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6225 free_and_replace(*u
, normalized_path
);
6231 static int normalize_names(char **names
, bool warn_if_path
) {
6233 bool was_path
= false;
6235 STRV_FOREACH(u
, names
) {
6241 r
= free_and_strdup(u
, basename(*u
));
6243 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6248 if (warn_if_path
&& was_path
)
6249 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6254 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6255 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6256 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6257 _cleanup_free_
char *path
= NULL
;
6258 static const struct bus_properties_map property_map
[] = {
6259 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
6260 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
6263 UnitStatusInfo info
= {};
6267 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6268 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6270 path
= unit_dbus_path_from_name(unit
);
6274 r
= acquire_bus(BUS_MANAGER
, &bus
);
6278 r
= sd_bus_call_method(
6280 "org.freedesktop.systemd1",
6282 "org.freedesktop.DBus.Properties",
6288 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6290 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
6292 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
6294 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6297 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6298 _cleanup_strv_free_
char **names
= NULL
;
6299 const char *verb
= argv
[0];
6300 UnitFileChange
*changes
= NULL
;
6301 unsigned n_changes
= 0;
6302 int carries_install_info
= -1;
6303 bool ignore_carries_install_info
= arg_quiet
;
6309 r
= mangle_names(strv_skip(argv
, 1), &names
);
6313 r
= enable_sysv_units(verb
, names
);
6317 /* If the operation was fully executed by the SysV compat, let's finish early */
6318 if (strv_isempty(names
)) {
6319 if (arg_no_reload
|| install_client_side())
6321 return daemon_reload(argc
, argv
, userdata
);
6324 if (streq(verb
, "disable")) {
6325 r
= normalize_names(names
, true);
6330 if (streq(verb
, "link")) {
6331 r
= normalize_filenames(names
);
6336 if (install_client_side()) {
6337 UnitFileFlags flags
;
6339 flags
= args_to_flags();
6340 if (streq(verb
, "enable")) {
6341 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6342 carries_install_info
= r
;
6343 } else if (streq(verb
, "disable"))
6344 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6345 else if (streq(verb
, "reenable")) {
6346 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6347 carries_install_info
= r
;
6348 } else if (streq(verb
, "link"))
6349 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6350 else if (streq(verb
, "preset")) {
6351 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6352 } else if (streq(verb
, "mask"))
6353 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6354 else if (streq(verb
, "unmask"))
6355 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6356 else if (streq(verb
, "revert"))
6357 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6359 assert_not_reached("Unknown verb");
6361 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6366 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6367 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6368 bool expect_carries_install_info
= false;
6369 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6373 if (STR_IN_SET(verb
, "mask", "unmask")) {
6375 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6377 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6381 STRV_FOREACH(name
, names
) {
6382 r
= unit_exists(&lp
, *name
);
6386 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6390 r
= acquire_bus(BUS_MANAGER
, &bus
);
6394 polkit_agent_open_maybe();
6396 if (streq(verb
, "enable")) {
6397 method
= "EnableUnitFiles";
6398 expect_carries_install_info
= true;
6399 } else if (streq(verb
, "disable")) {
6400 method
= "DisableUnitFiles";
6402 } else if (streq(verb
, "reenable")) {
6403 method
= "ReenableUnitFiles";
6404 expect_carries_install_info
= true;
6405 } else if (streq(verb
, "link"))
6406 method
= "LinkUnitFiles";
6407 else if (streq(verb
, "preset")) {
6409 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6410 method
= "PresetUnitFilesWithMode";
6411 send_preset_mode
= true;
6413 method
= "PresetUnitFiles";
6415 expect_carries_install_info
= true;
6416 ignore_carries_install_info
= true;
6417 } else if (streq(verb
, "mask"))
6418 method
= "MaskUnitFiles";
6419 else if (streq(verb
, "unmask")) {
6420 method
= "UnmaskUnitFiles";
6422 } else if (streq(verb
, "revert")) {
6423 method
= "RevertUnitFiles";
6424 send_runtime
= send_force
= false;
6426 assert_not_reached("Unknown verb");
6428 r
= sd_bus_message_new_method_call(
6431 "org.freedesktop.systemd1",
6432 "/org/freedesktop/systemd1",
6433 "org.freedesktop.systemd1.Manager",
6436 return bus_log_create_error(r
);
6438 r
= sd_bus_message_append_strv(m
, names
);
6440 return bus_log_create_error(r
);
6442 if (send_preset_mode
) {
6443 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6445 return bus_log_create_error(r
);
6449 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6451 return bus_log_create_error(r
);
6455 r
= sd_bus_message_append(m
, "b", arg_force
);
6457 return bus_log_create_error(r
);
6460 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6462 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6464 if (expect_carries_install_info
) {
6465 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6467 return bus_log_parse_error(r
);
6470 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6474 /* Try to reload if enabled */
6476 r
= daemon_reload(argc
, argv
, userdata
);
6481 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6482 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6483 "settings in the [Install] section, and DefaultInstance for template units).\n"
6484 "This means they are not meant to be enabled using systemctl.\n"
6485 "Possible reasons for having this kind of units are:\n"
6486 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6487 " .wants/ or .requires/ directory.\n"
6488 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6489 " a requirement dependency on it.\n"
6490 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6491 " D-Bus, udev, scripted systemctl call, ...).\n"
6492 "4) In case of template units, the unit is meant to be enabled with some\n"
6493 " instance name specified.");
6495 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6499 r
= acquire_bus(BUS_MANAGER
, &bus
);
6503 len
= strv_length(names
);
6505 char *new_args
[len
+ 2];
6507 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6508 for (i
= 0; i
< len
; i
++)
6509 new_args
[i
+ 1] = basename(names
[i
]);
6510 new_args
[i
+ 1] = NULL
;
6512 r
= start_unit(len
+ 1, new_args
, userdata
);
6517 unit_file_changes_free(changes
, n_changes
);
6522 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6523 _cleanup_strv_free_
char **names
= NULL
;
6524 _cleanup_free_
char *target
= NULL
;
6525 const char *verb
= argv
[0];
6526 UnitFileChange
*changes
= NULL
;
6527 unsigned n_changes
= 0;
6534 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6536 return log_error_errno(r
, "Failed to mangle unit name: %m");
6538 r
= mangle_names(strv_skip(argv
, 2), &names
);
6542 if (streq(verb
, "add-wants"))
6544 else if (streq(verb
, "add-requires"))
6545 dep
= UNIT_REQUIRES
;
6547 assert_not_reached("Unknown verb");
6549 if (install_client_side()) {
6550 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6551 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6556 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6557 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6560 r
= acquire_bus(BUS_MANAGER
, &bus
);
6564 polkit_agent_open_maybe();
6566 r
= sd_bus_message_new_method_call(
6569 "org.freedesktop.systemd1",
6570 "/org/freedesktop/systemd1",
6571 "org.freedesktop.systemd1.Manager",
6572 "AddDependencyUnitFiles");
6574 return bus_log_create_error(r
);
6576 r
= sd_bus_message_append_strv(m
, names
);
6578 return bus_log_create_error(r
);
6580 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6582 return bus_log_create_error(r
);
6584 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6586 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6588 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6592 if (arg_no_reload
) {
6597 r
= daemon_reload(argc
, argv
, userdata
);
6601 unit_file_changes_free(changes
, n_changes
);
6606 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6607 UnitFileChange
*changes
= NULL
;
6608 unsigned n_changes
= 0;
6611 if (install_client_side()) {
6612 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6613 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6618 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6619 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6622 r
= acquire_bus(BUS_MANAGER
, &bus
);
6626 polkit_agent_open_maybe();
6628 r
= sd_bus_call_method(
6630 "org.freedesktop.systemd1",
6631 "/org/freedesktop/systemd1",
6632 "org.freedesktop.systemd1.Manager",
6633 "PresetAllUnitFiles",
6637 unit_file_preset_mode_to_string(arg_preset_mode
),
6641 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6643 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6647 if (arg_no_reload
) {
6652 r
= daemon_reload(argc
, argv
, userdata
);
6656 unit_file_changes_free(changes
, n_changes
);
6661 static int show_installation_targets_client_side(const char *name
) {
6662 UnitFileChange
*changes
= NULL
;
6663 unsigned n_changes
= 0, i
;
6664 UnitFileFlags flags
;
6668 p
= STRV_MAKE(name
);
6669 flags
= UNIT_FILE_DRY_RUN
|
6670 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6672 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6674 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6676 for (i
= 0; i
< n_changes
; i
++)
6677 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6678 printf(" %s\n", changes
[i
].path
);
6683 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6684 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6685 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6689 r
= sd_bus_call_method(
6691 "org.freedesktop.systemd1",
6692 "/org/freedesktop/systemd1",
6693 "org.freedesktop.systemd1.Manager",
6697 "sb", name
, arg_runtime
);
6699 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6701 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6703 return bus_log_parse_error(r
);
6705 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6706 printf(" %s\n", link
);
6709 return bus_log_parse_error(r
);
6711 r
= sd_bus_message_exit_container(reply
);
6713 return bus_log_parse_error(r
);
6718 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6720 _cleanup_strv_free_
char **names
= NULL
;
6725 r
= mangle_names(strv_skip(argv
, 1), &names
);
6729 r
= enable_sysv_units(argv
[0], names
);
6735 if (install_client_side()) {
6736 STRV_FOREACH(name
, names
) {
6737 UnitFileState state
;
6739 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6741 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6745 UNIT_FILE_ENABLED_RUNTIME
,
6748 UNIT_FILE_GENERATED
))
6752 puts(unit_file_state_to_string(state
));
6754 r
= show_installation_targets_client_side(*name
);
6763 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6766 r
= acquire_bus(BUS_MANAGER
, &bus
);
6770 STRV_FOREACH(name
, names
) {
6771 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6774 r
= sd_bus_call_method(
6776 "org.freedesktop.systemd1",
6777 "/org/freedesktop/systemd1",
6778 "org.freedesktop.systemd1.Manager",
6784 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6786 r
= sd_bus_message_read(reply
, "s", &s
);
6788 return bus_log_parse_error(r
);
6790 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6796 r
= show_installation_targets(bus
, *name
);
6804 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6807 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6808 _cleanup_free_
char *state
= NULL
;
6812 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6815 return EXIT_FAILURE
;
6818 r
= acquire_bus(BUS_MANAGER
, &bus
);
6822 r
= sd_bus_get_property_string(
6824 "org.freedesktop.systemd1",
6825 "/org/freedesktop/systemd1",
6826 "org.freedesktop.systemd1.Manager",
6839 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6842 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6843 _cleanup_free_
char *t
= NULL
;
6847 assert(original_path
);
6850 r
= tempfn_random(new_path
, NULL
, &t
);
6852 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6854 r
= mkdir_parents(new_path
, 0755);
6856 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6858 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6863 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6866 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6874 static int get_file_to_edit(
6875 const LookupPaths
*paths
,
6879 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6884 path
= strjoin(paths
->persistent_config
, "/", name
);
6889 run
= strjoin(paths
->runtime_config
, "/", name
);
6895 if (access(path
, F_OK
) >= 0) {
6896 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6910 static int unit_file_create_new(
6911 const LookupPaths
*paths
,
6912 const char *unit_name
,
6914 char **ret_new_path
,
6915 char **ret_tmp_path
) {
6917 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6921 assert(ret_new_path
);
6922 assert(ret_tmp_path
);
6924 ending
= strjoina(unit_name
, suffix
);
6925 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6929 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6935 *ret_new_path
= tmp_new_path
;
6936 *ret_tmp_path
= tmp_tmp_path
;
6941 static int unit_file_create_copy(
6942 const LookupPaths
*paths
,
6943 const char *unit_name
,
6944 const char *fragment_path
,
6945 char **ret_new_path
,
6946 char **ret_tmp_path
) {
6948 char *tmp_new_path
, *tmp_tmp_path
;
6951 assert(fragment_path
);
6953 assert(ret_new_path
);
6954 assert(ret_tmp_path
);
6956 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6960 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6963 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6968 if (response
!= 'y') {
6969 log_warning("%s ignored", unit_name
);
6971 return -EKEYREJECTED
;
6975 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6981 *ret_new_path
= tmp_new_path
;
6982 *ret_tmp_path
= tmp_tmp_path
;
6987 static int run_editor(char **paths
) {
6995 return log_error_errno(errno
, "Failed to fork: %m");
6999 char *editor
, **editor_args
= NULL
;
7000 char **tmp_path
, **original_path
, *p
;
7001 unsigned n_editor_args
= 0, i
= 1;
7004 (void) reset_all_signal_handlers();
7005 (void) reset_signal_mask();
7007 argc
= strv_length(paths
)/2 + 1;
7009 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
7010 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
7011 * we try to execute well known editors
7013 editor
= getenv("SYSTEMD_EDITOR");
7015 editor
= getenv("EDITOR");
7017 editor
= getenv("VISUAL");
7019 if (!isempty(editor
)) {
7020 editor_args
= strv_split(editor
, WHITESPACE
);
7023 _exit(EXIT_FAILURE
);
7025 n_editor_args
= strv_length(editor_args
);
7026 argc
+= n_editor_args
- 1;
7028 args
= newa(const char*, argc
+ 1);
7030 if (n_editor_args
> 0) {
7031 args
[0] = editor_args
[0];
7032 for (; i
< n_editor_args
; i
++)
7033 args
[i
] = editor_args
[i
];
7036 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
7037 args
[i
] = *tmp_path
;
7042 if (n_editor_args
> 0)
7043 execvp(args
[0], (char* const*) args
);
7045 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
7047 execvp(p
, (char* const*) args
);
7048 /* We do not fail if the editor doesn't exist
7049 * because we want to try each one of them before
7052 if (errno
!= ENOENT
) {
7053 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
7054 _exit(EXIT_FAILURE
);
7058 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
7059 _exit(EXIT_FAILURE
);
7062 r
= wait_for_terminate_and_warn("editor", pid
, true);
7064 return log_error_errno(r
, "Failed to wait for child: %m");
7069 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
7070 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
7077 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
7081 STRV_FOREACH(name
, names
) {
7082 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
7083 const char *unit_name
;
7085 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
7093 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
7094 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
7095 arg_scope
== UNIT_FILE_USER
? " --user" : "",
7100 /* Create a new unit from scratch */
7102 r
= unit_file_create_new(&lp
, unit_name
,
7103 arg_full
? NULL
: ".d/override.conf",
7104 &new_path
, &tmp_path
);
7108 unit_name
= basename(path
);
7109 /* We follow unit aliases, but we need to propagate the instance */
7110 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
7111 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
7112 _cleanup_free_
char *instance
= NULL
;
7114 r
= unit_name_to_instance(*name
, &instance
);
7118 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
7122 unit_name
= tmp_name
;
7126 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
7128 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
7133 r
= strv_push_pair(paths
, new_path
, tmp_path
);
7136 new_path
= tmp_path
= NULL
;
7142 static int edit(int argc
, char *argv
[], void *userdata
) {
7143 _cleanup_strv_free_
char **names
= NULL
;
7144 _cleanup_strv_free_
char **paths
= NULL
;
7145 char **original
, **tmp
;
7150 log_error("Cannot edit units if not on a tty.");
7154 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
7155 log_error("Cannot edit units remotely.");
7159 r
= acquire_bus(BUS_MANAGER
, &bus
);
7163 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
7165 return log_error_errno(r
, "Failed to expand names: %m");
7167 r
= find_paths_to_edit(bus
, names
, &paths
);
7171 if (strv_isempty(paths
))
7174 r
= run_editor(paths
);
7178 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7179 /* If the temporary file is empty we ignore it. It's
7180 * useful if the user wants to cancel its modification
7182 if (null_or_empty_path(*tmp
)) {
7183 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7187 r
= rename(*tmp
, *original
);
7189 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7196 if (!arg_no_reload
&& !install_client_side())
7197 r
= daemon_reload(argc
, argv
, userdata
);
7200 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7201 (void) unlink(*tmp
);
7203 /* Removing empty dropin dirs */
7205 _cleanup_free_
char *dir
;
7207 dir
= dirname_malloc(*original
);
7211 /* no need to check if the dir is empty, rmdir
7212 * does nothing if it is not the case.
7221 static void systemctl_help(void) {
7223 pager_open(arg_no_pager
, false);
7225 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7226 "Query or send control commands to the systemd manager.\n\n"
7227 " -h --help Show this help\n"
7228 " --version Show package version\n"
7229 " --system Connect to system manager\n"
7230 " --user Connect to user service manager\n"
7231 " -H --host=[USER@]HOST\n"
7232 " Operate on remote host\n"
7233 " -M --machine=CONTAINER\n"
7234 " Operate on local container\n"
7235 " -t --type=TYPE List units of a particular type\n"
7236 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7237 " -p --property=NAME Show only properties by this name\n"
7238 " -a --all Show all properties/all units currently in memory,\n"
7239 " including dead/empty ones. To list all units installed on\n"
7240 " the system, use the 'list-unit-files' command instead.\n"
7241 " --failed Same as --state=failed\n"
7242 " -l --full Don't ellipsize unit names on output\n"
7243 " -r --recursive Show unit list of host and local containers\n"
7244 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7245 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7246 " queueing a new job\n"
7247 " --show-types When showing sockets, explicitly show their type\n"
7248 " --value When showing properties, only print the value\n"
7249 " -i --ignore-inhibitors\n"
7250 " When shutting down or sleeping, ignore inhibitors\n"
7251 " --kill-who=WHO Who to send signal to\n"
7252 " -s --signal=SIGNAL Which signal to send\n"
7253 " --now Start or stop unit in addition to enabling or disabling it\n"
7254 " --dry-run Only print what would be done\n"
7255 " -q --quiet Suppress output\n"
7256 " --wait For (re)start, wait until service stopped again\n"
7257 " --no-block Do not wait until operation finished\n"
7258 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7259 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7260 " --no-legend Do not print a legend (column headers and hints)\n"
7261 " --no-pager Do not pipe output into a pager\n"
7262 " --no-ask-password\n"
7263 " Do not ask for system passwords\n"
7264 " --global Enable/disable/mask unit files globally\n"
7265 " --runtime Enable/disable/mask unit files temporarily until next\n"
7267 " -f --force When enabling unit files, override existing symlinks\n"
7268 " When shutting down, execute action immediately\n"
7269 " --preset-mode= Apply only enable, only disable, or all presets\n"
7270 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7272 " -n --lines=INTEGER Number of journal entries to show\n"
7273 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7274 " short-iso, short-iso-precise, short-full,\n"
7275 " short-monotonic, short-unix,\n"
7276 " verbose, export, json, json-pretty, json-sse, cat)\n"
7277 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7278 " --plain Print unit dependencies as a list instead of a tree\n\n"
7280 " list-units [PATTERN...] List units currently in memory\n"
7281 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
7283 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
7285 " start NAME... Start (activate) one or more units\n"
7286 " stop NAME... Stop (deactivate) one or more units\n"
7287 " reload NAME... Reload one or more units\n"
7288 " restart NAME... Start or restart one or more units\n"
7289 " try-restart NAME... Restart one or more units if active\n"
7290 " reload-or-restart NAME... Reload one or more units if possible,\n"
7291 " otherwise start or restart\n"
7292 " try-reload-or-restart NAME... If active, reload one or more units,\n"
7293 " if supported, otherwise restart\n"
7294 " isolate NAME Start one unit and stop all others\n"
7295 " kill NAME... Send signal to processes of a unit\n"
7296 " is-active PATTERN... Check whether units are active\n"
7297 " is-failed PATTERN... Check whether units are failed\n"
7298 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7299 " show [PATTERN...|JOB...] Show properties of one or more\n"
7300 " units/jobs or the manager\n"
7301 " cat PATTERN... Show files and drop-ins of one or more units\n"
7302 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
7303 " help PATTERN...|PID... Show manual for one or more units\n"
7304 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7306 " list-dependencies [NAME] Recursively show units which are required\n"
7307 " or wanted by this unit or by which this\n"
7308 " unit is required or wanted\n\n"
7309 "Unit File Commands:\n"
7310 " list-unit-files [PATTERN...] List installed unit files\n"
7311 " enable [NAME...|PATH...] Enable one or more unit files\n"
7312 " disable NAME... Disable one or more unit files\n"
7313 " reenable NAME... Reenable one or more unit files\n"
7314 " preset NAME... Enable/disable one or more unit files\n"
7315 " based on preset configuration\n"
7316 " preset-all Enable/disable all unit files based on\n"
7317 " preset configuration\n"
7318 " is-enabled NAME... Check whether unit files are enabled\n"
7319 " mask NAME... Mask one or more units\n"
7320 " unmask NAME... Unmask one or more units\n"
7321 " link PATH... Link one or more units files into\n"
7322 " the search path\n"
7323 " revert NAME... Revert one or more unit files to vendor\n"
7325 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
7326 " on specified one or more units\n"
7327 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
7328 " on specified one or more units\n"
7329 " edit NAME... Edit one or more unit files\n"
7330 " get-default Get the name of the default target\n"
7331 " set-default NAME Set the default target\n\n"
7332 "Machine Commands:\n"
7333 " list-machines [PATTERN...] List local containers and host\n\n"
7335 " list-jobs [PATTERN...] List jobs\n"
7336 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7337 "Environment Commands:\n"
7338 " show-environment Dump environment\n"
7339 " set-environment NAME=VALUE... Set one or more environment variables\n"
7340 " unset-environment NAME... Unset one or more environment variables\n"
7341 " import-environment [NAME...] Import all or some environment variables\n\n"
7342 "Manager Lifecycle Commands:\n"
7343 " daemon-reload Reload systemd manager configuration\n"
7344 " daemon-reexec Reexecute systemd manager\n\n"
7345 "System Commands:\n"
7346 " is-system-running Check whether system is fully running\n"
7347 " default Enter system default mode\n"
7348 " rescue Enter system rescue mode\n"
7349 " emergency Enter system emergency mode\n"
7350 " halt Shut down and halt the system\n"
7351 " poweroff Shut down and power-off the system\n"
7352 " reboot [ARG] Shut down and reboot the system\n"
7353 " kexec Shut down and reboot the system with kexec\n"
7354 " exit [EXIT_CODE] Request user instance or container exit\n"
7355 " switch-root ROOT [INIT] Change to a different root file system\n"
7356 " suspend Suspend the system\n"
7357 " hibernate Hibernate the system\n"
7358 " hybrid-sleep Hibernate and suspend the system\n",
7359 program_invocation_short_name
);
7362 static void halt_help(void) {
7363 printf("%s [OPTIONS...]%s\n\n"
7364 "%s the system.\n\n"
7365 " --help Show this help\n"
7366 " --halt Halt the machine\n"
7367 " -p --poweroff Switch off the machine\n"
7368 " --reboot Reboot the machine\n"
7369 " -f --force Force immediate halt/power-off/reboot\n"
7370 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7371 " -d --no-wtmp Don't write wtmp record\n"
7372 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7373 program_invocation_short_name
,
7374 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7375 arg_action
== ACTION_REBOOT
? "Reboot" :
7376 arg_action
== ACTION_POWEROFF
? "Power off" :
7380 static void shutdown_help(void) {
7381 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7382 "Shut down the system.\n\n"
7383 " --help Show this help\n"
7384 " -H --halt Halt the machine\n"
7385 " -P --poweroff Power-off the machine\n"
7386 " -r --reboot Reboot the machine\n"
7387 " -h Equivalent to --poweroff, overridden by --halt\n"
7388 " -k Don't halt/power-off/reboot, just send warnings\n"
7389 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7390 " -c Cancel a pending shutdown\n",
7391 program_invocation_short_name
);
7394 static void telinit_help(void) {
7395 printf("%s [OPTIONS...] {COMMAND}\n\n"
7396 "Send control commands to the init daemon.\n\n"
7397 " --help Show this help\n"
7398 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7400 " 0 Power-off the machine\n"
7401 " 6 Reboot the machine\n"
7402 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7403 " 1, s, S Enter rescue mode\n"
7404 " q, Q Reload init daemon configuration\n"
7405 " u, U Reexecute init daemon\n",
7406 program_invocation_short_name
);
7409 static void runlevel_help(void) {
7410 printf("%s [OPTIONS...]\n\n"
7411 "Prints the previous and current runlevel of the init system.\n\n"
7412 " --help Show this help\n",
7413 program_invocation_short_name
);
7416 static void help_types(void) {
7420 puts("Available unit types:");
7421 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7422 puts(unit_type_to_string(i
));
7425 static void help_states(void) {
7429 puts("Available unit load states:");
7430 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7431 puts(unit_load_state_to_string(i
));
7434 puts("\nAvailable unit active states:");
7435 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7436 puts(unit_active_state_to_string(i
));
7439 puts("\nAvailable automount unit substates:");
7440 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7441 puts(automount_state_to_string(i
));
7444 puts("\nAvailable device unit substates:");
7445 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7446 puts(device_state_to_string(i
));
7449 puts("\nAvailable mount unit substates:");
7450 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7451 puts(mount_state_to_string(i
));
7454 puts("\nAvailable path unit substates:");
7455 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7456 puts(path_state_to_string(i
));
7459 puts("\nAvailable scope unit substates:");
7460 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7461 puts(scope_state_to_string(i
));
7464 puts("\nAvailable service unit substates:");
7465 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7466 puts(service_state_to_string(i
));
7469 puts("\nAvailable slice unit substates:");
7470 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7471 puts(slice_state_to_string(i
));
7474 puts("\nAvailable socket unit substates:");
7475 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7476 puts(socket_state_to_string(i
));
7479 puts("\nAvailable swap unit substates:");
7480 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7481 puts(swap_state_to_string(i
));
7484 puts("\nAvailable target unit substates:");
7485 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7486 puts(target_state_to_string(i
));
7489 puts("\nAvailable timer unit substates:");
7490 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7491 puts(timer_state_to_string(i
));
7494 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7504 ARG_IGNORE_DEPENDENCIES
,
7517 ARG_NO_ASK_PASSWORD
,
7531 static const struct option options
[] = {
7532 { "help", no_argument
, NULL
, 'h' },
7533 { "version", no_argument
, NULL
, ARG_VERSION
},
7534 { "type", required_argument
, NULL
, 't' },
7535 { "property", required_argument
, NULL
, 'p' },
7536 { "all", no_argument
, NULL
, 'a' },
7537 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7538 { "after", no_argument
, NULL
, ARG_AFTER
},
7539 { "before", no_argument
, NULL
, ARG_BEFORE
},
7540 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7541 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7542 { "full", no_argument
, NULL
, 'l' },
7543 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7544 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7545 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7546 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7547 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7548 { "value", no_argument
, NULL
, ARG_VALUE
},
7549 { "user", no_argument
, NULL
, ARG_USER
},
7550 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7551 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7552 { "wait", no_argument
, NULL
, ARG_WAIT
},
7553 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7554 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7555 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7556 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7557 { "dry-run", no_argument
, NULL
, ARG_DRY_RUN
},
7558 { "quiet", no_argument
, NULL
, 'q' },
7559 { "root", required_argument
, NULL
, ARG_ROOT
},
7560 { "force", no_argument
, NULL
, ARG_FORCE
},
7561 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7562 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7563 { "signal", required_argument
, NULL
, 's' },
7564 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7565 { "host", required_argument
, NULL
, 'H' },
7566 { "machine", required_argument
, NULL
, 'M' },
7567 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7568 { "lines", required_argument
, NULL
, 'n' },
7569 { "output", required_argument
, NULL
, 'o' },
7570 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7571 { "state", required_argument
, NULL
, ARG_STATE
},
7572 { "recursive", no_argument
, NULL
, 'r' },
7573 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7574 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7575 { "now", no_argument
, NULL
, ARG_NOW
},
7576 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7586 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7587 arg_ask_password
= true;
7589 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7601 if (isempty(optarg
)) {
7602 log_error("--type= requires arguments.");
7606 for (p
= optarg
;;) {
7607 _cleanup_free_
char *type
= NULL
;
7609 r
= extract_first_word(&p
, &type
, ",", 0);
7611 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7615 if (streq(type
, "help")) {
7620 if (unit_type_from_string(type
) >= 0) {
7621 if (strv_push(&arg_types
, type
) < 0)
7627 /* It's much nicer to use --state= for
7628 * load states, but let's support this
7629 * in --types= too for compatibility
7630 * with old versions */
7631 if (unit_load_state_from_string(type
) >= 0) {
7632 if (strv_push(&arg_states
, type
) < 0)
7638 log_error("Unknown unit type or load state '%s'.", type
);
7639 log_info("Use -t help to see a list of allowed values.");
7647 /* Make sure that if the empty property list
7648 was specified, we won't show any properties. */
7649 if (isempty(optarg
) && !arg_properties
) {
7650 arg_properties
= new0(char*, 1);
7651 if (!arg_properties
)
7654 for (p
= optarg
;;) {
7655 _cleanup_free_
char *prop
= NULL
;
7657 r
= extract_first_word(&p
, &prop
, ",", 0);
7659 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7663 if (strv_push(&arg_properties
, prop
) < 0)
7669 /* If the user asked for a particular
7670 * property, show it to him, even if it is
7682 arg_dependency
= DEPENDENCY_REVERSE
;
7686 arg_dependency
= DEPENDENCY_AFTER
;
7687 arg_jobs_after
= true;
7691 arg_dependency
= DEPENDENCY_BEFORE
;
7692 arg_jobs_before
= true;
7695 case ARG_SHOW_TYPES
:
7696 arg_show_types
= true;
7704 arg_job_mode
= optarg
;
7708 arg_job_mode
= "fail";
7711 case ARG_IRREVERSIBLE
:
7712 arg_job_mode
= "replace-irreversibly";
7715 case ARG_IGNORE_DEPENDENCIES
:
7716 arg_job_mode
= "ignore-dependencies";
7720 arg_scope
= UNIT_FILE_USER
;
7724 arg_scope
= UNIT_FILE_SYSTEM
;
7728 arg_scope
= UNIT_FILE_GLOBAL
;
7736 arg_no_block
= true;
7740 arg_no_legend
= true;
7744 arg_no_pager
= true;
7752 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7762 if (strv_extend(&arg_states
, "failed") < 0)
7784 arg_no_reload
= true;
7788 arg_kill_who
= optarg
;
7792 arg_signal
= signal_from_string_try_harder(optarg
);
7793 if (arg_signal
< 0) {
7794 log_error("Failed to parse signal string %s.", optarg
);
7799 case ARG_NO_ASK_PASSWORD
:
7800 arg_ask_password
= false;
7804 arg_transport
= BUS_TRANSPORT_REMOTE
;
7809 arg_transport
= BUS_TRANSPORT_MACHINE
;
7818 if (safe_atou(optarg
, &arg_lines
) < 0) {
7819 log_error("Failed to parse lines '%s'", optarg
);
7825 arg_output
= output_mode_from_string(optarg
);
7826 if (arg_output
< 0) {
7827 log_error("Unknown output '%s'.", optarg
);
7833 arg_ignore_inhibitors
= true;
7840 case ARG_FIRMWARE_SETUP
:
7841 arg_firmware_setup
= true;
7845 if (isempty(optarg
)) {
7846 log_error("--state= requires arguments.");
7850 for (p
= optarg
;;) {
7851 _cleanup_free_
char *s
= NULL
;
7853 r
= extract_first_word(&p
, &s
, ",", 0);
7855 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7859 if (streq(s
, "help")) {
7864 if (strv_push(&arg_states
, s
) < 0)
7873 if (geteuid() != 0) {
7874 log_error("--recursive requires root privileges.");
7878 arg_recursive
= true;
7881 case ARG_PRESET_MODE
:
7883 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7884 if (arg_preset_mode
< 0) {
7885 log_error("Failed to parse preset mode: %s.", optarg
);
7896 if (strv_extend(&arg_wall
, optarg
) < 0)
7904 assert_not_reached("Unhandled option");
7907 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7908 log_error("Cannot access user instance remotely.");
7912 if (arg_wait
&& arg_no_block
) {
7913 log_error("--wait may not be combined with --no-block.");
7920 static int halt_parse_argv(int argc
, char *argv
[]) {
7929 static const struct option options
[] = {
7930 { "help", no_argument
, NULL
, ARG_HELP
},
7931 { "halt", no_argument
, NULL
, ARG_HALT
},
7932 { "poweroff", no_argument
, NULL
, 'p' },
7933 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7934 { "force", no_argument
, NULL
, 'f' },
7935 { "wtmp-only", no_argument
, NULL
, 'w' },
7936 { "no-wtmp", no_argument
, NULL
, 'd' },
7937 { "no-sync", no_argument
, NULL
, 'n' },
7938 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7947 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7948 if (IN_SET(runlevel
, '0', '6'))
7951 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7959 arg_action
= ACTION_HALT
;
7963 if (arg_action
!= ACTION_REBOOT
)
7964 arg_action
= ACTION_POWEROFF
;
7968 arg_action
= ACTION_REBOOT
;
7993 /* Compatibility nops */
8000 assert_not_reached("Unhandled option");
8003 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
8004 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
8007 } else if (optind
< argc
) {
8008 log_error("Too many arguments.");
8015 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
8019 if (streq(t
, "now"))
8021 else if (!strchr(t
, ':')) {
8024 if (safe_atou64(t
, &u
) < 0)
8027 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
8036 hour
= strtol(t
, &e
, 10);
8037 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
8040 minute
= strtol(e
+1, &e
, 10);
8041 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
8044 n
= now(CLOCK_REALTIME
);
8045 s
= (time_t) (n
/ USEC_PER_SEC
);
8047 assert_se(localtime_r(&s
, &tm
));
8049 tm
.tm_hour
= (int) hour
;
8050 tm
.tm_min
= (int) minute
;
8053 assert_se(s
= mktime(&tm
));
8055 *_u
= (usec_t
) s
* USEC_PER_SEC
;
8058 *_u
+= USEC_PER_DAY
;
8064 static int shutdown_parse_argv(int argc
, char *argv
[]) {
8071 static const struct option options
[] = {
8072 { "help", no_argument
, NULL
, ARG_HELP
},
8073 { "halt", no_argument
, NULL
, 'H' },
8074 { "poweroff", no_argument
, NULL
, 'P' },
8075 { "reboot", no_argument
, NULL
, 'r' },
8076 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
8077 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8087 while ((c
= getopt_long(argc
, argv
, "HPrhkKat:fFc", options
, NULL
)) >= 0)
8095 arg_action
= ACTION_HALT
;
8099 arg_action
= ACTION_POWEROFF
;
8104 arg_action
= ACTION_KEXEC
;
8106 arg_action
= ACTION_REBOOT
;
8110 arg_action
= ACTION_KEXEC
;
8114 if (arg_action
!= ACTION_HALT
)
8115 arg_action
= ACTION_POWEROFF
;
8127 case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */
8130 /* Compatibility nops */
8134 arg_action
= ACTION_CANCEL_SHUTDOWN
;
8141 assert_not_reached("Unhandled option");
8144 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
8145 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
8147 log_error("Failed to parse time specification: %s", argv
[optind
]);
8151 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
8153 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
8154 /* No time argument for shutdown cancel */
8155 wall
= argv
+ optind
;
8156 else if (argc
> optind
+ 1)
8157 /* We skip the time argument */
8158 wall
= argv
+ optind
+ 1;
8161 arg_wall
= strv_copy(wall
);
8171 static int telinit_parse_argv(int argc
, char *argv
[]) {
8178 static const struct option options
[] = {
8179 { "help", no_argument
, NULL
, ARG_HELP
},
8180 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8184 static const struct {
8188 { '0', ACTION_POWEROFF
},
8189 { '6', ACTION_REBOOT
},
8190 { '1', ACTION_RESCUE
},
8191 { '2', ACTION_RUNLEVEL2
},
8192 { '3', ACTION_RUNLEVEL3
},
8193 { '4', ACTION_RUNLEVEL4
},
8194 { '5', ACTION_RUNLEVEL5
},
8195 { 's', ACTION_RESCUE
},
8196 { 'S', ACTION_RESCUE
},
8197 { 'q', ACTION_RELOAD
},
8198 { 'Q', ACTION_RELOAD
},
8199 { 'u', ACTION_REEXEC
},
8200 { 'U', ACTION_REEXEC
}
8209 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8224 assert_not_reached("Unhandled option");
8227 if (optind
>= argc
) {
8228 log_error("%s: required argument missing.", program_invocation_short_name
);
8232 if (optind
+ 1 < argc
) {
8233 log_error("Too many arguments.");
8237 if (strlen(argv
[optind
]) != 1) {
8238 log_error("Expected single character argument.");
8242 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8243 if (table
[i
].from
== argv
[optind
][0])
8246 if (i
>= ELEMENTSOF(table
)) {
8247 log_error("Unknown command '%s'.", argv
[optind
]);
8251 arg_action
= table
[i
].to
;
8258 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8264 static const struct option options
[] = {
8265 { "help", no_argument
, NULL
, ARG_HELP
},
8274 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8285 assert_not_reached("Unhandled option");
8288 if (optind
< argc
) {
8289 log_error("Too many arguments.");
8296 static int parse_argv(int argc
, char *argv
[]) {
8300 if (program_invocation_short_name
) {
8302 if (strstr(program_invocation_short_name
, "halt")) {
8303 arg_action
= ACTION_HALT
;
8304 return halt_parse_argv(argc
, argv
);
8305 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8306 arg_action
= ACTION_POWEROFF
;
8307 return halt_parse_argv(argc
, argv
);
8308 } else if (strstr(program_invocation_short_name
, "reboot")) {
8310 arg_action
= ACTION_KEXEC
;
8312 arg_action
= ACTION_REBOOT
;
8313 return halt_parse_argv(argc
, argv
);
8314 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8315 arg_action
= ACTION_POWEROFF
;
8316 return shutdown_parse_argv(argc
, argv
);
8317 } else if (strstr(program_invocation_short_name
, "init")) {
8319 if (sd_booted() > 0) {
8320 arg_action
= _ACTION_INVALID
;
8321 return telinit_parse_argv(argc
, argv
);
8323 /* Hmm, so some other init system is
8324 * running, we need to forward this
8325 * request to it. For now we simply
8326 * guess that it is Upstart. */
8328 execv(TELINIT
, argv
);
8330 log_error("Couldn't find an alternative telinit implementation to spawn.");
8334 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8335 arg_action
= ACTION_RUNLEVEL
;
8336 return runlevel_parse_argv(argc
, argv
);
8340 arg_action
= ACTION_SYSTEMCTL
;
8341 return systemctl_parse_argv(argc
, argv
);
8344 #if HAVE_SYSV_COMPAT
8345 _pure_
static int action_to_runlevel(void) {
8347 static const char table
[_ACTION_MAX
] = {
8348 [ACTION_HALT
] = '0',
8349 [ACTION_POWEROFF
] = '0',
8350 [ACTION_REBOOT
] = '6',
8351 [ACTION_RUNLEVEL2
] = '2',
8352 [ACTION_RUNLEVEL3
] = '3',
8353 [ACTION_RUNLEVEL4
] = '4',
8354 [ACTION_RUNLEVEL5
] = '5',
8355 [ACTION_RESCUE
] = '1'
8358 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8360 return table
[arg_action
];
8364 static int talk_initctl(void) {
8365 #if HAVE_SYSV_COMPAT
8366 struct init_request request
= {
8367 .magic
= INIT_MAGIC
,
8369 .cmd
= INIT_CMD_RUNLVL
8372 _cleanup_close_
int fd
= -1;
8376 rl
= action_to_runlevel();
8380 request
.runlevel
= rl
;
8382 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
8384 if (errno
== ENOENT
)
8387 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8390 r
= loop_write(fd
, &request
, sizeof(request
), false);
8392 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8400 static int systemctl_main(int argc
, char *argv
[]) {
8402 static const Verb verbs
[] = {
8403 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
8404 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8405 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
8406 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
8407 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
8408 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
8409 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
8410 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
8411 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8412 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8413 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8414 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8415 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8416 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8417 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8418 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8419 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8420 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
8421 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8422 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
8423 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
8424 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
8425 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8426 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8427 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
8428 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8429 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
8430 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8431 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8432 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8433 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8434 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
8435 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8436 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8437 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
8438 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8439 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8440 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
8441 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8442 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8443 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8444 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8445 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
8446 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8447 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8448 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
8449 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
8450 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8451 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8452 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8453 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8454 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8455 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8456 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8457 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8458 { "link", 2, VERB_ANY
, 0, enable_unit
},
8459 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8460 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
8461 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
8462 { "set-default", 2, 2, 0, set_default
},
8463 { "get-default", VERB_ANY
, 1, 0, get_default
},
8464 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
8465 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8466 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8467 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8468 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
8472 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8475 static int reload_with_fallback(void) {
8477 /* First, try systemd via D-Bus. */
8478 if (daemon_reload(0, NULL
, NULL
) >= 0)
8481 /* Nothing else worked, so let's try signals */
8482 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8484 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8485 return log_error_errno(errno
, "kill() failed: %m");
8490 static int start_with_fallback(void) {
8492 /* First, try systemd via D-Bus. */
8493 if (start_unit(0, NULL
, NULL
) >= 0)
8496 /* Nothing else worked, so let's try /dev/initctl */
8497 if (talk_initctl() > 0)
8500 log_error("Failed to talk to init daemon.");
8504 static int halt_now(enum action a
) {
8507 /* The kernel will automaticall flush ATA disks and suchlike
8508 * on reboot(), but the file systems need to be synce'd
8509 * explicitly in advance. */
8510 if (!arg_no_sync
&& !arg_dry_run
)
8513 /* Make sure C-A-D is handled by the kernel from this point on... */
8515 (void) reboot(RB_ENABLE_CAD
);
8521 log_info("Halting.");
8524 (void) reboot(RB_HALT_SYSTEM
);
8527 case ACTION_POWEROFF
:
8529 log_info("Powering off.");
8532 (void) reboot(RB_POWER_OFF
);
8536 case ACTION_REBOOT
: {
8537 _cleanup_free_
char *param
= NULL
;
8539 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8540 if (r
< 0 && r
!= -ENOENT
)
8541 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8543 if (!isempty(param
)) {
8545 log_info("Rebooting with argument '%s'.", param
);
8547 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
,
8548 LINUX_REBOOT_CMD_RESTART2
, param
);
8549 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8554 log_info("Rebooting.");
8557 (void) reboot(RB_AUTOBOOT
);
8562 assert_not_reached("Unknown action.");
8566 static int logind_schedule_shutdown(void) {
8569 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8570 char date
[FORMAT_TIMESTAMP_MAX
];
8575 r
= acquire_bus(BUS_FULL
, &bus
);
8579 switch (arg_action
) {
8583 case ACTION_POWEROFF
:
8584 action
= "poweroff";
8599 action
= strjoina("dry-", action
);
8601 (void) logind_set_wall_message();
8603 r
= sd_bus_call_method(
8605 "org.freedesktop.login1",
8606 "/org/freedesktop/login1",
8607 "org.freedesktop.login1.Manager",
8615 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8618 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8621 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8626 static int halt_main(void) {
8629 r
= logind_check_inhibitors(arg_action
);
8634 return logind_schedule_shutdown();
8636 if (geteuid() != 0) {
8637 if (arg_dry_run
|| arg_force
> 0) {
8638 log_error("Must be root.");
8642 /* Try logind if we are a normal user and no special
8643 * mode applies. Maybe PolicyKit allows us to shutdown
8645 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8646 r
= logind_reboot(arg_action
);
8649 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8650 /* requested operation is not
8651 * supported on the local system or
8652 * already in progress */
8654 /* on all other errors, try low-level operation */
8658 if (!arg_dry_run
&& !arg_force
)
8659 return start_with_fallback();
8661 assert(geteuid() == 0);
8664 if (sd_booted() > 0)
8665 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8667 r
= utmp_put_shutdown();
8669 log_warning_errno(r
, "Failed to write utmp record: %m");
8676 r
= halt_now(arg_action
);
8677 return log_error_errno(r
, "Failed to reboot: %m");
8680 static int runlevel_main(void) {
8681 int r
, runlevel
, previous
;
8683 r
= utmp_get_runlevel(&runlevel
, &previous
);
8690 previous
<= 0 ? 'N' : previous
,
8691 runlevel
<= 0 ? 'N' : runlevel
);
8696 static int logind_cancel_shutdown(void) {
8698 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8702 r
= acquire_bus(BUS_FULL
, &bus
);
8706 (void) logind_set_wall_message();
8708 r
= sd_bus_call_method(
8710 "org.freedesktop.login1",
8711 "/org/freedesktop/login1",
8712 "org.freedesktop.login1.Manager",
8713 "CancelScheduledShutdown",
8717 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8721 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8726 int main(int argc
, char*argv
[]) {
8729 argv_cmdline
= argv
[0];
8731 setlocale(LC_ALL
, "");
8732 log_parse_environment();
8736 /* Explicitly not on_tty() to avoid setting cached value.
8737 * This becomes relevant for piping output which might be
8739 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8741 r
= parse_argv(argc
, argv
);
8745 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8748 log_info("Running in chroot, ignoring request.");
8753 /* systemctl_main() will print an error message for the bus
8754 * connection, but only if it needs to */
8756 switch (arg_action
) {
8758 case ACTION_SYSTEMCTL
:
8759 r
= systemctl_main(argc
, argv
);
8762 /* Legacy command aliases set arg_action. They provide some fallbacks,
8763 * e.g. to tell sysvinit to reboot after you have installed systemd
8767 case ACTION_POWEROFF
:
8773 case ACTION_RUNLEVEL2
:
8774 case ACTION_RUNLEVEL3
:
8775 case ACTION_RUNLEVEL4
:
8776 case ACTION_RUNLEVEL5
:
8778 r
= start_with_fallback();
8783 r
= reload_with_fallback();
8786 case ACTION_CANCEL_SHUTDOWN
:
8787 r
= logind_cancel_shutdown();
8790 case ACTION_RUNLEVEL
:
8791 r
= runlevel_main();
8795 case ACTION_SUSPEND
:
8796 case ACTION_HIBERNATE
:
8797 case ACTION_HYBRID_SLEEP
:
8798 case ACTION_EMERGENCY
:
8799 case ACTION_DEFAULT
:
8800 /* systemctl verbs with no equivalent in the legacy commands.
8801 * These cannot appear in arg_action. Fall through. */
8803 case _ACTION_INVALID
:
8805 assert_not_reached("Unknown action");
8812 ask_password_agent_close();
8813 polkit_agent_close();
8815 strv_free(arg_types
);
8816 strv_free(arg_states
);
8817 strv_free(arg_properties
);
8819 strv_free(arg_wall
);
8823 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8824 return r
< 0 ? EXIT_FAILURE
: r
;