2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Marc-Antoine Perennou
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <linux/reboot.h>
30 #include <sys/reboot.h>
31 #include <sys/socket.h>
35 #include "sd-daemon.h"
38 #include "alloc-util.h"
39 #include "bus-common-errors.h"
40 #include "bus-error.h"
41 #include "bus-message.h"
42 #include "bus-unit-util.h"
44 #include "cgroup-show.h"
45 #include "cgroup-util.h"
51 #include "exit-status.h"
54 #include "format-util.h"
56 #include "glob-util.h"
57 #include "hostname-util.h"
62 #include "locale-util.h"
64 #include "logs-show.h"
68 #include "parse-util.h"
69 #include "path-lookup.h"
70 #include "path-util.h"
71 #include "process-util.h"
72 #include "rlimit-util.h"
75 #include "signal-util.h"
76 #include "socket-util.h"
77 #include "spawn-ask-password-agent.h"
78 #include "spawn-polkit-agent.h"
80 #include "stat-util.h"
82 #include "terminal-util.h"
83 #include "unit-name.h"
84 #include "user-util.h"
86 #include "utmp-wtmp.h"
90 /* The init script exit status codes
91 0 program is running or service is OK
92 1 program is dead and /var/run pid file exists
93 2 program is dead and /var/lock lock file exists
94 3 program is not running
95 4 program or service status is unknown
96 5-99 reserved for future LSB use
97 100-149 reserved for distribution use
98 150-199 reserved for application use
102 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
103 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
104 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
105 EXIT_PROGRAM_NOT_RUNNING
= 3,
106 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
109 static char **arg_types
= NULL
;
110 static char **arg_states
= NULL
;
111 static char **arg_properties
= NULL
;
112 static bool arg_all
= false;
113 static enum dependency
{
119 } arg_dependency
= DEPENDENCY_FORWARD
;
120 static const char *arg_job_mode
= "replace";
121 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
122 static bool arg_wait
= false;
123 static bool arg_no_block
= false;
124 static bool arg_no_legend
= false;
125 static bool arg_no_pager
= false;
126 static bool arg_no_wtmp
= false;
127 static bool arg_no_sync
= false;
128 static bool arg_no_wall
= false;
129 static bool arg_no_reload
= false;
130 static bool arg_value
= false;
131 static bool arg_show_types
= false;
132 static bool arg_ignore_inhibitors
= false;
133 static bool arg_dry
= false;
134 static bool arg_quiet
= false;
135 static bool arg_full
= false;
136 static bool arg_recursive
= false;
137 static int arg_force
= 0;
138 static bool arg_ask_password
= false;
139 static bool arg_runtime
= false;
140 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
141 static char **arg_wall
= NULL
;
142 static const char *arg_kill_who
= NULL
;
143 static int arg_signal
= SIGTERM
;
144 static char *arg_root
= NULL
;
145 static usec_t arg_when
= 0;
146 static char *argv_cmdline
= NULL
;
167 ACTION_CANCEL_SHUTDOWN
,
170 } arg_action
= ACTION_SYSTEMCTL
;
171 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
172 static const char *arg_host
= NULL
;
173 static unsigned arg_lines
= 10;
174 static OutputMode arg_output
= OUTPUT_SHORT
;
175 static bool arg_plain
= false;
176 static bool arg_firmware_setup
= false;
177 static bool arg_now
= false;
178 static bool arg_jobs_before
= false;
179 static bool arg_jobs_after
= false;
181 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
182 static int trivial_method(int argc
, char *argv
[], void *userdata
);
183 static int halt_now(enum action a
);
184 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
186 static bool original_stdout_is_tty
;
188 typedef enum BusFocus
{
189 BUS_FULL
, /* The full bus indicated via --system or --user */
190 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
194 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
196 static UnitFileFlags
args_to_flags(void) {
197 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
198 (arg_force
? UNIT_FILE_FORCE
: 0);
201 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
204 assert(focus
< _BUS_FOCUS_MAX
);
207 /* We only go directly to the manager, if we are using a local transport */
208 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
211 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
214 if (!busses
[focus
]) {
217 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
219 if (!user
&& sd_booted() <= 0) {
220 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
221 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
225 if (focus
== BUS_MANAGER
)
226 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
228 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
230 return log_error_errno(r
, "Failed to connect to bus: %m");
232 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
235 *ret
= busses
[focus
];
239 static void release_busses(void) {
242 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
243 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
246 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
248 const char **p
= userdata
;
251 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
261 static void ask_password_agent_open_if_enabled(void) {
263 /* Open the password agent as a child process if necessary */
265 if (!arg_ask_password
)
268 if (arg_scope
!= UNIT_FILE_SYSTEM
)
271 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
274 ask_password_agent_open();
277 static void polkit_agent_open_maybe(void) {
278 /* Open the polkit agent as a child process if necessary */
280 if (arg_scope
!= UNIT_FILE_SYSTEM
)
283 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
286 static OutputFlags
get_output_flags(void) {
288 arg_all
* OUTPUT_SHOW_ALL
|
289 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
290 colors_enabled() * OUTPUT_COLOR
|
291 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
294 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
297 if (!sd_bus_error_is_set(error
))
300 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
301 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
302 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
303 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
304 return EXIT_NOPERMISSION
;
306 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
307 return EXIT_NOTINSTALLED
;
309 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
310 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
311 return EXIT_NOTIMPLEMENTED
;
313 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
314 return EXIT_NOTCONFIGURED
;
322 static bool install_client_side(void) {
324 /* Decides when to execute enable/disable/... operations
325 * client-side rather than server-side. */
327 if (running_in_chroot() > 0)
330 if (sd_booted() <= 0)
333 if (!isempty(arg_root
))
336 if (arg_scope
== UNIT_FILE_GLOBAL
)
339 /* Unsupported environment variable, mostly for debugging purposes */
340 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
346 static int compare_unit_info(const void *a
, const void *b
) {
347 const UnitInfo
*u
= a
, *v
= b
;
351 /* First, order by machine */
352 if (!u
->machine
&& v
->machine
)
354 if (u
->machine
&& !v
->machine
)
356 if (u
->machine
&& v
->machine
) {
357 r
= strcasecmp(u
->machine
, v
->machine
);
362 /* Second, order by unit type */
363 d1
= strrchr(u
->id
, '.');
364 d2
= strrchr(v
->id
, '.');
366 r
= strcasecmp(d1
, d2
);
371 /* Third, order by name */
372 return strcasecmp(u
->id
, v
->id
);
375 static const char* unit_type_suffix(const char *name
) {
378 dot
= strrchr(name
, '.');
385 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
388 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
391 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
397 /* Note that '--all' is not purely a state filter, but also a
398 * filter that hides units that "follow" other units (which is
399 * used for device units that appear under different names). */
400 if (!isempty(u
->following
))
403 if (!strv_isempty(arg_states
))
406 /* By default show all units except the ones in inactive
407 * state and with no pending job */
411 if (streq(u
->active_state
, "inactive"))
417 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
418 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
420 unsigned n_shown
= 0;
423 max_id_len
= strlen("UNIT");
424 load_len
= strlen("LOAD");
425 active_len
= strlen("ACTIVE");
426 sub_len
= strlen("SUB");
427 job_len
= strlen("JOB");
428 max_desc_len
= strlen("DESCRIPTION");
430 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
431 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
432 load_len
= MAX(load_len
, strlen(u
->load_state
));
433 active_len
= MAX(active_len
, strlen(u
->active_state
));
434 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
435 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
437 if (u
->job_id
!= 0) {
438 job_len
= MAX(job_len
, strlen(u
->job_type
));
442 if (!arg_no_legend
&&
443 (streq(u
->active_state
, "failed") ||
444 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
448 if (!arg_full
&& original_stdout_is_tty
) {
451 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
452 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
455 basic_len
+= job_len
+ 1;
457 if (basic_len
< (unsigned) columns()) {
458 unsigned extra_len
, incr
;
459 extra_len
= columns() - basic_len
;
461 /* Either UNIT already got 25, or is fully satisfied.
462 * Grant up to 25 to DESC now. */
463 incr
= MIN(extra_len
, 25u);
467 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
468 * description but not more than it needs. */
470 incr
= MIN(max_id_len
- id_len
, extra_len
);
472 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
478 desc_len
= max_desc_len
;
481 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
482 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
483 const char *on_underline
= "", *off_underline
= "";
484 const char *on_loaded
= "", *off_loaded
= "";
485 const char *on_active
= "", *off_active
= "";
486 const char *on_circle
= "", *off_circle
= "";
488 bool circle
= false, underline
= false;
490 if (!n_shown
&& !arg_no_legend
) {
495 printf("%s%-*s %-*s %-*s %-*s ",
499 active_len
, "ACTIVE",
503 printf("%-*s ", job_len
, "JOB");
507 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
514 if (u
+ 1 < unit_infos
+ c
&&
515 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
516 on_underline
= ansi_underline();
517 off_underline
= ansi_normal();
521 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
522 on_circle
= ansi_highlight_yellow();
523 off_circle
= ansi_normal();
525 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
526 off_loaded
= underline
? on_underline
: ansi_normal();
527 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
528 on_circle
= ansi_highlight_red();
529 off_circle
= ansi_normal();
531 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
532 off_active
= underline
? on_underline
: ansi_normal();
536 j
= strjoin(u
->machine
, ":", u
->id
);
545 e
= ellipsize(id
, id_len
, 33);
553 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
555 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
557 on_active
, id_len
, id
, off_active
,
558 on_loaded
, load_len
, u
->load_state
, off_loaded
,
559 on_active
, active_len
, u
->active_state
,
560 sub_len
, u
->sub_state
, off_active
,
561 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
565 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
570 if (!arg_no_legend
) {
571 const char *on
, *off
;
575 "LOAD = Reflects whether the unit definition was properly loaded.\n"
576 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
577 "SUB = The low-level unit activation state, values depend on unit type.");
578 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
579 on
= ansi_highlight();
582 on
= ansi_highlight_red();
587 printf("%s%u loaded units listed.%s\n"
588 "To show all installed unit files use 'systemctl list-unit-files'.\n",
591 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
592 "To show all installed unit files use 'systemctl list-unit-files'.\n",
599 static int get_unit_list(
603 UnitInfo
**unit_infos
,
605 sd_bus_message
**_reply
) {
607 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
608 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
609 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
613 bool fallback
= false;
619 r
= sd_bus_message_new_method_call(
622 "org.freedesktop.systemd1",
623 "/org/freedesktop/systemd1",
624 "org.freedesktop.systemd1.Manager",
625 "ListUnitsByPatterns");
627 return bus_log_create_error(r
);
629 r
= sd_bus_message_append_strv(m
, arg_states
);
631 return bus_log_create_error(r
);
633 r
= sd_bus_message_append_strv(m
, patterns
);
635 return bus_log_create_error(r
);
637 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
638 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
639 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
640 /* Fallback to legacy ListUnitsFiltered method */
642 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
643 m
= sd_bus_message_unref(m
);
644 sd_bus_error_free(&error
);
646 r
= sd_bus_message_new_method_call(
649 "org.freedesktop.systemd1",
650 "/org/freedesktop/systemd1",
651 "org.freedesktop.systemd1.Manager",
652 "ListUnitsFiltered");
654 return bus_log_create_error(r
);
656 r
= sd_bus_message_append_strv(m
, arg_states
);
658 return bus_log_create_error(r
);
660 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
663 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
665 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
667 return bus_log_parse_error(r
);
669 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
672 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
675 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
678 (*unit_infos
)[c
++] = u
;
681 return bus_log_parse_error(r
);
683 r
= sd_bus_message_exit_container(reply
);
685 return bus_log_parse_error(r
);
693 static void message_set_freep(Set
**set
) {
696 while ((m
= set_steal_first(*set
)))
697 sd_bus_message_unref(m
);
702 static int get_unit_list_recursive(
705 UnitInfo
**_unit_infos
,
709 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
710 _cleanup_(message_set_freep
) Set
*replies
;
711 sd_bus_message
*reply
;
719 replies
= set_new(NULL
);
723 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
727 r
= set_put(replies
, reply
);
729 sd_bus_message_unref(reply
);
734 _cleanup_strv_free_
char **machines
= NULL
;
737 r
= sd_get_machine_names(&machines
);
739 return log_error_errno(r
, "Failed to get machine names: %m");
741 STRV_FOREACH(i
, machines
) {
742 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
745 r
= sd_bus_open_system_machine(&container
, *i
);
747 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
751 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
757 r
= set_put(replies
, reply
);
759 sd_bus_message_unref(reply
);
764 *_machines
= machines
;
769 *_unit_infos
= unit_infos
;
778 static int list_units(int argc
, char *argv
[], void *userdata
) {
779 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
780 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
781 _cleanup_strv_free_
char **machines
= NULL
;
785 r
= acquire_bus(BUS_MANAGER
, &bus
);
789 pager_open(arg_no_pager
, false);
791 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
795 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
796 return output_units_list(unit_infos
, r
);
799 static int get_triggered_units(
804 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
811 r
= sd_bus_get_property_strv(
813 "org.freedesktop.systemd1",
815 "org.freedesktop.systemd1.Unit",
820 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
825 static int get_listening(
827 const char* unit_path
,
830 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
831 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
832 const char *type
, *path
;
835 r
= sd_bus_get_property(
837 "org.freedesktop.systemd1",
839 "org.freedesktop.systemd1.Socket",
845 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
847 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
849 return bus_log_parse_error(r
);
851 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
853 r
= strv_extend(listening
, type
);
857 r
= strv_extend(listening
, path
);
864 return bus_log_parse_error(r
);
866 r
= sd_bus_message_exit_container(reply
);
868 return bus_log_parse_error(r
);
880 /* Note: triggered is a list here, although it almost certainly
881 * will always be one unit. Nevertheless, dbus API allows for multiple
882 * values, so let's follow that. */
885 /* The strv above is shared. free is set only in the first one. */
889 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
895 if (!a
->machine
&& b
->machine
)
897 if (a
->machine
&& !b
->machine
)
899 if (a
->machine
&& b
->machine
) {
900 o
= strcasecmp(a
->machine
, b
->machine
);
905 o
= strcmp(a
->path
, b
->path
);
907 o
= strcmp(a
->type
, b
->type
);
912 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
913 struct socket_info
*s
;
914 unsigned pathlen
= strlen("LISTEN"),
915 typelen
= strlen("TYPE") * arg_show_types
,
916 socklen
= strlen("UNIT"),
917 servlen
= strlen("ACTIVATES");
918 const char *on
, *off
;
920 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
924 socklen
= MAX(socklen
, strlen(s
->id
));
926 typelen
= MAX(typelen
, strlen(s
->type
));
927 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
929 STRV_FOREACH(a
, s
->triggered
)
930 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
931 servlen
= MAX(servlen
, tmp
);
936 printf("%-*s %-*.*s%-*s %s\n",
938 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
942 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
943 _cleanup_free_
char *j
= NULL
;
948 j
= strjoin(s
->machine
, ":", s
->path
);
956 printf("%-*s %-*s %-*s",
957 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
960 pathlen
, path
, socklen
, s
->id
);
961 STRV_FOREACH(a
, s
->triggered
)
963 a
== s
->triggered
? "" : ",", *a
);
967 on
= ansi_highlight();
972 on
= ansi_highlight_red();
976 if (!arg_no_legend
) {
977 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
979 printf("Pass --all to see loaded but inactive sockets, too.\n");
985 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
986 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
987 _cleanup_strv_free_
char **machines
= NULL
;
988 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
989 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
991 struct socket_info
*s
;
997 r
= acquire_bus(BUS_MANAGER
, &bus
);
1001 pager_open(arg_no_pager
, false);
1003 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1007 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1008 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1011 if (!endswith(u
->id
, ".socket"))
1014 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1018 c
= get_listening(bus
, u
->unit_path
, &listening
);
1024 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1029 for (i
= 0; i
< c
; i
++)
1030 socket_infos
[cs
+ i
] = (struct socket_info
) {
1031 .machine
= u
->machine
,
1033 .type
= listening
[i
*2],
1034 .path
= listening
[i
*2 + 1],
1035 .triggered
= triggered
,
1036 .own_triggered
= i
==0,
1039 /* from this point on we will cleanup those socket_infos */
1042 listening
= triggered
= NULL
; /* avoid cleanup */
1045 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1046 (__compar_fn_t
) socket_info_compare
);
1048 output_sockets_list(socket_infos
, cs
);
1051 assert(cs
== 0 || socket_infos
);
1052 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1055 if (s
->own_triggered
)
1056 strv_free(s
->triggered
);
1062 static int get_next_elapse(
1065 dual_timestamp
*next
) {
1067 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1075 r
= sd_bus_get_property_trivial(
1077 "org.freedesktop.systemd1",
1079 "org.freedesktop.systemd1.Timer",
1080 "NextElapseUSecMonotonic",
1085 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1087 r
= sd_bus_get_property_trivial(
1089 "org.freedesktop.systemd1",
1091 "org.freedesktop.systemd1.Timer",
1092 "NextElapseUSecRealtime",
1097 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1103 static int get_last_trigger(
1108 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1115 r
= sd_bus_get_property_trivial(
1117 "org.freedesktop.systemd1",
1119 "org.freedesktop.systemd1.Timer",
1125 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1131 const char* machine
;
1134 usec_t last_trigger
;
1138 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1144 if (!a
->machine
&& b
->machine
)
1146 if (a
->machine
&& !b
->machine
)
1148 if (a
->machine
&& b
->machine
) {
1149 o
= strcasecmp(a
->machine
, b
->machine
);
1154 if (a
->next_elapse
< b
->next_elapse
)
1156 if (a
->next_elapse
> b
->next_elapse
)
1159 return strcmp(a
->id
, b
->id
);
1162 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1163 struct timer_info
*t
;
1165 nextlen
= strlen("NEXT"),
1166 leftlen
= strlen("LEFT"),
1167 lastlen
= strlen("LAST"),
1168 passedlen
= strlen("PASSED"),
1169 unitlen
= strlen("UNIT"),
1170 activatelen
= strlen("ACTIVATES");
1172 const char *on
, *off
;
1174 assert(timer_infos
|| n
== 0);
1176 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1180 if (t
->next_elapse
> 0) {
1181 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1183 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1184 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1186 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1187 leftlen
= MAX(leftlen
, strlen(trel
));
1190 if (t
->last_trigger
> 0) {
1191 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1193 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1194 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1196 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1197 passedlen
= MAX(passedlen
, strlen(trel
));
1200 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1202 STRV_FOREACH(a
, t
->triggered
)
1203 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1205 activatelen
= MAX(activatelen
, ul
);
1210 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1214 passedlen
, "PASSED",
1218 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1219 _cleanup_free_
char *j
= NULL
;
1221 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1222 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1225 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1226 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1228 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1229 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1232 j
= strjoin(t
->machine
, ":", t
->id
);
1239 printf("%-*s %-*s %-*s %-*s %-*s",
1240 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1242 STRV_FOREACH(a
, t
->triggered
)
1244 a
== t
->triggered
? "" : ",", *a
);
1248 on
= ansi_highlight();
1249 off
= ansi_normal();
1253 on
= ansi_highlight_red();
1254 off
= ansi_normal();
1257 if (!arg_no_legend
) {
1258 printf("%s%u timers listed.%s\n", on
, n
, off
);
1260 printf("Pass --all to see loaded but inactive timers, too.\n");
1266 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1272 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1275 if (next
->monotonic
> nw
->monotonic
)
1276 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1278 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1280 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1281 next_elapse
= MIN(converted
, next
->realtime
);
1283 next_elapse
= converted
;
1286 next_elapse
= next
->realtime
;
1291 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1292 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1293 _cleanup_strv_free_
char **machines
= NULL
;
1294 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1295 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1296 struct timer_info
*t
;
1304 r
= acquire_bus(BUS_MANAGER
, &bus
);
1308 pager_open(arg_no_pager
, false);
1310 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1314 dual_timestamp_get(&nw
);
1316 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1317 _cleanup_strv_free_
char **triggered
= NULL
;
1318 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1321 if (!endswith(u
->id
, ".timer"))
1324 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1328 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1332 get_last_trigger(bus
, u
->unit_path
, &last
);
1334 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1339 m
= calc_next_elapse(&nw
, &next
);
1341 timer_infos
[c
++] = (struct timer_info
) {
1342 .machine
= u
->machine
,
1345 .last_trigger
= last
,
1346 .triggered
= triggered
,
1349 triggered
= NULL
; /* avoid cleanup */
1352 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1353 (__compar_fn_t
) timer_info_compare
);
1355 output_timers_list(timer_infos
, c
);
1358 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1359 strv_free(t
->triggered
);
1364 static int compare_unit_file_list(const void *a
, const void *b
) {
1365 const char *d1
, *d2
;
1366 const UnitFileList
*u
= a
, *v
= b
;
1368 d1
= strrchr(u
->path
, '.');
1369 d2
= strrchr(v
->path
, '.');
1374 r
= strcasecmp(d1
, d2
);
1379 return strcasecmp(basename(u
->path
), basename(v
->path
));
1382 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1385 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1388 if (!strv_isempty(arg_types
)) {
1391 dot
= strrchr(u
->path
, '.');
1395 if (!strv_find(arg_types
, dot
+1))
1399 if (!strv_isempty(states
) &&
1400 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1406 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1407 unsigned max_id_len
, id_cols
, state_cols
;
1408 const UnitFileList
*u
;
1410 max_id_len
= strlen("UNIT FILE");
1411 state_cols
= strlen("STATE");
1413 for (u
= units
; u
< units
+ c
; u
++) {
1414 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1415 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1419 unsigned basic_cols
;
1421 id_cols
= MIN(max_id_len
, 25u);
1422 basic_cols
= 1 + id_cols
+ state_cols
;
1423 if (basic_cols
< (unsigned) columns())
1424 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1426 id_cols
= max_id_len
;
1428 if (!arg_no_legend
&& c
> 0)
1429 printf("%s%-*s %-*s%s\n",
1431 id_cols
, "UNIT FILE",
1432 state_cols
, "STATE",
1435 for (u
= units
; u
< units
+ c
; u
++) {
1436 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1437 _cleanup_free_
char *e
= NULL
;
1440 underline
= u
+ 1 < units
+ c
&&
1441 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1444 on_underline
= ansi_underline();
1446 if (IN_SET(u
->state
,
1448 UNIT_FILE_MASKED_RUNTIME
,
1451 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1452 else if (u
->state
== UNIT_FILE_ENABLED
)
1453 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1455 if (on_underline
|| on_color
)
1456 off
= ansi_normal();
1458 id
= basename(u
->path
);
1460 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1462 printf("%s%-*s %s%-*s%s\n",
1463 strempty(on_underline
),
1464 id_cols
, e
? e
: id
,
1465 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1469 printf("\n%u unit files listed.\n", c
);
1472 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1473 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1474 _cleanup_free_ UnitFileList
*units
= NULL
;
1481 bool fallback
= false;
1483 if (install_client_side()) {
1489 h
= hashmap_new(&string_hash_ops
);
1493 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1495 unit_file_list_free(h
);
1496 return log_error_errno(r
, "Failed to get unit file list: %m");
1499 n_units
= hashmap_size(h
);
1501 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1503 unit_file_list_free(h
);
1507 HASHMAP_FOREACH(u
, h
, i
) {
1508 if (!output_show_unit_file(u
, NULL
, NULL
))
1515 assert(c
<= n_units
);
1520 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1521 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1524 r
= acquire_bus(BUS_MANAGER
, &bus
);
1528 r
= sd_bus_message_new_method_call(
1531 "org.freedesktop.systemd1",
1532 "/org/freedesktop/systemd1",
1533 "org.freedesktop.systemd1.Manager",
1534 "ListUnitFilesByPatterns");
1536 return bus_log_create_error(r
);
1538 r
= sd_bus_message_append_strv(m
, arg_states
);
1540 return bus_log_create_error(r
);
1542 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1544 return bus_log_create_error(r
);
1546 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1547 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1548 /* Fallback to legacy ListUnitFiles method */
1550 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1551 m
= sd_bus_message_unref(m
);
1552 sd_bus_error_free(&error
);
1554 r
= sd_bus_message_new_method_call(
1557 "org.freedesktop.systemd1",
1558 "/org/freedesktop/systemd1",
1559 "org.freedesktop.systemd1.Manager",
1562 return bus_log_create_error(r
);
1564 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1567 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1569 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1571 return bus_log_parse_error(r
);
1573 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1575 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1578 units
[c
] = (struct UnitFileList
) {
1580 unit_file_state_from_string(state
)
1583 if (output_show_unit_file(&units
[c
],
1584 fallback
? arg_states
: NULL
,
1585 fallback
? strv_skip(argv
, 1) : NULL
))
1590 return bus_log_parse_error(r
);
1592 r
= sd_bus_message_exit_container(reply
);
1594 return bus_log_parse_error(r
);
1597 pager_open(arg_no_pager
, false);
1599 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1600 output_unit_file_list(units
, c
);
1602 if (install_client_side())
1603 for (unit
= units
; unit
< units
+ c
; unit
++)
1609 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1610 _cleanup_free_
char *n
= NULL
;
1611 size_t max_len
= MAX(columns(),20u);
1617 for (i
= level
- 1; i
>= 0; i
--) {
1619 if (len
> max_len
- 3 && !arg_full
) {
1620 printf("%s...\n",max_len
% 2 ? "" : " ");
1623 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1627 if (len
> max_len
- 3 && !arg_full
) {
1628 printf("%s...\n",max_len
% 2 ? "" : " ");
1632 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1636 printf("%s\n", name
);
1640 n
= ellipsize(name
, max_len
-len
, 100);
1648 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1650 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1651 [DEPENDENCY_FORWARD
] = "Requires\0"
1656 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1661 [DEPENDENCY_AFTER
] = "After\0",
1662 [DEPENDENCY_BEFORE
] = "Before\0",
1665 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1666 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1667 _cleanup_strv_free_
char **ret
= NULL
;
1668 _cleanup_free_
char *path
= NULL
;
1674 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1676 path
= unit_dbus_path_from_name(name
);
1680 r
= sd_bus_call_method(
1682 "org.freedesktop.systemd1",
1684 "org.freedesktop.DBus.Properties",
1688 "s", "org.freedesktop.systemd1.Unit");
1690 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1692 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1694 return bus_log_parse_error(r
);
1696 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1699 r
= sd_bus_message_read(reply
, "s", &prop
);
1701 return bus_log_parse_error(r
);
1703 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1704 r
= sd_bus_message_skip(reply
, "v");
1706 return bus_log_parse_error(r
);
1709 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1711 return bus_log_parse_error(r
);
1713 r
= bus_message_read_strv_extend(reply
, &ret
);
1715 return bus_log_parse_error(r
);
1717 r
= sd_bus_message_exit_container(reply
);
1719 return bus_log_parse_error(r
);
1722 r
= sd_bus_message_exit_container(reply
);
1724 return bus_log_parse_error(r
);
1728 return bus_log_parse_error(r
);
1730 r
= sd_bus_message_exit_container(reply
);
1732 return bus_log_parse_error(r
);
1734 *deps
= strv_uniq(ret
);
1740 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1741 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1743 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1745 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1748 return strcasecmp(*a
, *b
);
1751 static int list_dependencies_one(
1756 unsigned int branches
) {
1758 _cleanup_strv_free_
char **deps
= NULL
;
1766 r
= strv_extend(units
, name
);
1770 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1774 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1776 STRV_FOREACH(c
, deps
) {
1777 if (strv_contains(*units
, *c
)) {
1780 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1790 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1793 (void) get_state_one_unit(bus
, *c
, &active_state
);
1795 switch (active_state
) {
1797 case UNIT_RELOADING
:
1798 case UNIT_ACTIVATING
:
1799 on
= ansi_highlight_green();
1803 case UNIT_DEACTIVATING
:
1808 on
= ansi_highlight_red();
1812 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1815 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1819 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1820 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1827 strv_remove(*units
, name
);
1832 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1833 _cleanup_strv_free_
char **units
= NULL
;
1834 _cleanup_free_
char *unit
= NULL
;
1840 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1842 return log_error_errno(r
, "Failed to mangle unit name: %m");
1846 u
= SPECIAL_DEFAULT_TARGET
;
1848 r
= acquire_bus(BUS_MANAGER
, &bus
);
1852 pager_open(arg_no_pager
, false);
1856 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1859 struct machine_info
{
1863 char *control_group
;
1864 uint32_t n_failed_units
;
1869 static const struct bus_properties_map machine_info_property_map
[] = {
1870 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1871 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1872 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1873 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1874 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1878 static void machine_info_clear(struct machine_info
*info
) {
1883 free(info
->control_group
);
1887 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1893 for (i
= 0; i
< n
; i
++)
1894 machine_info_clear(&machine_infos
[i
]);
1896 free(machine_infos
);
1899 static int compare_machine_info(const void *a
, const void *b
) {
1900 const struct machine_info
*u
= a
, *v
= b
;
1902 if (u
->is_host
!= v
->is_host
)
1903 return u
->is_host
> v
->is_host
? -1 : 1;
1905 return strcasecmp(u
->name
, v
->name
);
1908 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1909 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1915 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1922 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, mi
);
1929 static bool output_show_machine(const char *name
, char **patterns
) {
1930 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1933 static int get_machine_list(
1935 struct machine_info
**_machine_infos
,
1938 struct machine_info
*machine_infos
= NULL
;
1939 _cleanup_strv_free_
char **m
= NULL
;
1940 _cleanup_free_
char *hn
= NULL
;
1945 hn
= gethostname_malloc();
1949 if (output_show_machine(hn
, patterns
)) {
1950 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1953 machine_infos
[c
].is_host
= true;
1954 machine_infos
[c
].name
= hn
;
1957 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1961 r
= sd_get_machine_names(&m
);
1963 return log_error_errno(r
, "Failed to get machine list: %m");
1965 STRV_FOREACH(i
, m
) {
1966 _cleanup_free_
char *class = NULL
;
1968 if (!output_show_machine(*i
, patterns
))
1971 sd_machine_get_class(*i
, &class);
1972 if (!streq_ptr(class, "container"))
1975 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1976 free_machines_list(machine_infos
, c
);
1980 machine_infos
[c
].is_host
= false;
1981 machine_infos
[c
].name
= strdup(*i
);
1982 if (!machine_infos
[c
].name
) {
1983 free_machines_list(machine_infos
, c
);
1987 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1991 *_machine_infos
= machine_infos
;
1995 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1996 struct machine_info
*m
;
1999 namelen
= sizeof("NAME") - 1,
2000 statelen
= sizeof("STATE") - 1,
2001 failedlen
= sizeof("FAILED") - 1,
2002 jobslen
= sizeof("JOBS") - 1;
2004 assert(machine_infos
|| n
== 0);
2006 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2007 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
2008 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
2009 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
2010 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
2012 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
2016 if (!arg_no_legend
) {
2020 printf("%-*s %-*s %-*s %-*s\n",
2023 failedlen
, "FAILED",
2027 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2028 const char *on_state
= "", *off_state
= "";
2029 const char *on_failed
= "", *off_failed
= "";
2030 bool circle
= false;
2032 if (streq_ptr(m
->state
, "degraded")) {
2033 on_state
= ansi_highlight_red();
2034 off_state
= ansi_normal();
2036 } else if (!streq_ptr(m
->state
, "running")) {
2037 on_state
= ansi_highlight_yellow();
2038 off_state
= ansi_normal();
2042 if (m
->n_failed_units
> 0) {
2043 on_failed
= ansi_highlight_red();
2044 off_failed
= ansi_normal();
2046 on_failed
= off_failed
= "";
2049 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2052 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2053 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2054 on_state
, statelen
, strna(m
->state
), off_state
,
2055 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2056 jobslen
, m
->n_jobs
);
2058 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2059 namelen
, strna(m
->name
),
2060 on_state
, statelen
, strna(m
->state
), off_state
,
2061 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2062 jobslen
, m
->n_jobs
);
2066 printf("\n%u machines listed.\n", n
);
2069 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2070 struct machine_info
*machine_infos
= NULL
;
2074 if (geteuid() != 0) {
2075 log_error("Must be root.");
2079 r
= acquire_bus(BUS_MANAGER
, &bus
);
2083 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2087 pager_open(arg_no_pager
, false);
2089 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2090 output_machines_list(machine_infos
, r
);
2091 free_machines_list(machine_infos
, r
);
2096 static int get_default(int argc
, char *argv
[], void *userdata
) {
2097 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2098 _cleanup_free_
char *_path
= NULL
;
2102 if (install_client_side()) {
2103 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2105 return log_error_errno(r
, "Failed to get default target: %m");
2110 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2113 r
= acquire_bus(BUS_MANAGER
, &bus
);
2117 r
= sd_bus_call_method(
2119 "org.freedesktop.systemd1",
2120 "/org/freedesktop/systemd1",
2121 "org.freedesktop.systemd1.Manager",
2127 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2129 r
= sd_bus_message_read(reply
, "s", &path
);
2131 return bus_log_parse_error(r
);
2135 printf("%s\n", path
);
2140 static int set_default(int argc
, char *argv
[], void *userdata
) {
2141 _cleanup_free_
char *unit
= NULL
;
2142 UnitFileChange
*changes
= NULL
;
2143 unsigned n_changes
= 0;
2149 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2151 return log_error_errno(r
, "Failed to mangle unit name: %m");
2153 if (install_client_side()) {
2154 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2155 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2160 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2161 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2164 polkit_agent_open_maybe();
2166 r
= acquire_bus(BUS_MANAGER
, &bus
);
2170 r
= sd_bus_call_method(
2172 "org.freedesktop.systemd1",
2173 "/org/freedesktop/systemd1",
2174 "org.freedesktop.systemd1.Manager",
2180 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2182 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2186 /* Try to reload if enabled */
2188 r
= daemon_reload(argc
, argv
, userdata
);
2194 unit_file_changes_free(changes
, n_changes
);
2199 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2200 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2201 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2202 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2208 r
= sd_bus_call_method(
2210 "org.freedesktop.systemd1",
2211 "/org/freedesktop/systemd1",
2212 "org.freedesktop.systemd1.Manager",
2218 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2220 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2222 return bus_log_parse_error(r
);
2224 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2225 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2227 return bus_log_parse_error(r
);
2229 r
= sd_bus_message_exit_container(reply
);
2231 return bus_log_parse_error(r
);
2238 const char *name
, *type
, *state
;
2241 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2242 unsigned id_len
, unit_len
, type_len
, state_len
;
2243 const struct job_info
*j
;
2244 const char *on
, *off
;
2245 bool shorten
= false;
2247 assert(n
== 0 || jobs
);
2250 if (!arg_no_legend
) {
2251 on
= ansi_highlight_green();
2252 off
= ansi_normal();
2254 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2259 pager_open(arg_no_pager
, false);
2261 id_len
= strlen("JOB");
2262 unit_len
= strlen("UNIT");
2263 type_len
= strlen("TYPE");
2264 state_len
= strlen("STATE");
2266 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2267 uint32_t id
= j
->id
;
2268 assert(j
->name
&& j
->type
&& j
->state
);
2270 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2271 unit_len
= MAX(unit_len
, strlen(j
->name
));
2272 type_len
= MAX(type_len
, strlen(j
->type
));
2273 state_len
= MAX(state_len
, strlen(j
->state
));
2276 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2277 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2282 printf("%*s %-*s %-*s %-*s\n",
2286 state_len
, "STATE");
2288 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2289 _cleanup_free_
char *e
= NULL
;
2291 if (streq(j
->state
, "running")) {
2292 on
= ansi_highlight();
2293 off
= ansi_normal();
2297 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2298 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2300 on
, unit_len
, e
? e
: j
->name
, off
,
2302 on
, state_len
, j
->state
, off
);
2305 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2306 if (arg_jobs_before
)
2307 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2310 if (!arg_no_legend
) {
2311 on
= ansi_highlight();
2312 off
= ansi_normal();
2314 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2318 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2319 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2322 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2323 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2324 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2325 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2326 _cleanup_free_
struct job_info
*jobs
= NULL
;
2332 bool skipped
= false;
2334 r
= acquire_bus(BUS_MANAGER
, &bus
);
2338 r
= sd_bus_call_method(
2340 "org.freedesktop.systemd1",
2341 "/org/freedesktop/systemd1",
2342 "org.freedesktop.systemd1.Manager",
2348 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2350 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2352 return bus_log_parse_error(r
);
2354 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2355 struct job_info job
= { id
, name
, type
, state
};
2357 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2362 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2368 return bus_log_parse_error(r
);
2370 r
= sd_bus_message_exit_container(reply
);
2372 return bus_log_parse_error(r
);
2374 pager_open(arg_no_pager
, false);
2376 output_jobs_list(bus
, jobs
, c
, skipped
);
2380 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2386 return trivial_method(argc
, argv
, userdata
);
2388 r
= acquire_bus(BUS_MANAGER
, &bus
);
2392 polkit_agent_open_maybe();
2394 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2395 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2399 q
= safe_atou32(*name
, &id
);
2401 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2403 q
= sd_bus_call_method(
2405 "org.freedesktop.systemd1",
2406 "/org/freedesktop/systemd1",
2407 "org.freedesktop.systemd1.Manager",
2413 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2422 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2423 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2427 /* We ignore all errors here, since this is used to show a
2430 /* We don't use unit_dbus_path_from_name() directly since we
2431 * don't want to load the unit if it isn't loaded. */
2433 r
= sd_bus_call_method(
2435 "org.freedesktop.systemd1",
2436 "/org/freedesktop/systemd1",
2437 "org.freedesktop.systemd1.Manager",
2445 r
= sd_bus_message_read(reply
, "o", &path
);
2449 r
= sd_bus_get_property_trivial(
2451 "org.freedesktop.systemd1",
2453 "org.freedesktop.systemd1.Unit",
2463 static void warn_unit_file_changed(const char *name
) {
2466 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2467 ansi_highlight_red(),
2470 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2473 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2479 STRV_FOREACH(p
, lp
->search_path
) {
2480 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2483 path
= path_join(NULL
, *p
, unit_name
);
2487 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2493 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2505 static int unit_find_template_path(
2506 const char *unit_name
,
2508 char **fragment_path
,
2511 _cleanup_free_
char *_template
= NULL
;
2514 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2516 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2518 return r
; /* error or found a real unit */
2520 r
= unit_name_template(unit_name
, &_template
);
2522 return 0; /* not a template, does not exist */
2524 return log_error_errno(r
, "Failed to determine template name: %m");
2526 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2531 *template = _template
;
2537 static int unit_find_paths(
2539 const char *unit_name
,
2541 char **fragment_path
,
2542 char ***dropin_paths
) {
2544 _cleanup_free_
char *path
= NULL
;
2545 _cleanup_strv_free_
char **dropins
= NULL
;
2549 * Finds where the unit is defined on disk. Returns 0 if the unit
2550 * is not found. Returns 1 if it is found, and sets
2551 * - the path to the unit in *path, if it exists on disk,
2552 * - and a strv of existing drop-ins in *dropins,
2553 * if the arg is not NULL and any dropins were found.
2557 assert(fragment_path
);
2560 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2561 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2562 _cleanup_free_
char *unit
= NULL
;
2564 unit
= unit_dbus_path_from_name(unit_name
);
2568 r
= sd_bus_get_property_string(
2570 "org.freedesktop.systemd1",
2572 "org.freedesktop.systemd1.Unit",
2577 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2580 r
= sd_bus_get_property_strv(
2582 "org.freedesktop.systemd1",
2584 "org.freedesktop.systemd1.Unit",
2589 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2592 _cleanup_set_free_ Set
*names
= NULL
;
2593 _cleanup_free_
char *template = NULL
;
2595 names
= set_new(NULL
);
2599 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2604 /* We found the unit file. If we followed symlinks, this name might be
2605 * different then the unit_name with started with. Look for dropins matching
2606 * that "final" name. */
2607 r
= set_put(names
, basename(path
));
2609 /* No unit file, let's look for dropins matching the original name.
2610 * systemd has fairly complicated rules (based on unit type and provenience),
2611 * which units are allowed not to have the main unit file. We err on the
2612 * side of including too many files, and always try to load dropins. */
2613 r
= set_put(names
, unit_name
);
2615 /* The cases where we allow a unit to exist without the main file are
2616 * never valid for templates. Don't try to load dropins in this case. */
2620 return log_error_errno(r
, "Failed to add unit name: %m");
2623 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2624 NULL
, names
, &dropins
);
2632 if (!isempty(path
)) {
2633 *fragment_path
= path
;
2638 if (dropin_paths
&& !strv_isempty(dropins
)) {
2639 *dropin_paths
= dropins
;
2644 if (r
== 0 && !arg_force
)
2645 log_error("No files found for %s.", unit_name
);
2650 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2651 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2652 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2653 _cleanup_free_
char *buf
= NULL
;
2654 UnitActiveState state
;
2659 assert(active_state
);
2661 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2663 r
= sd_bus_call_method(
2665 "org.freedesktop.systemd1",
2666 "/org/freedesktop/systemd1",
2667 "org.freedesktop.systemd1.Manager",
2673 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2674 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2676 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2677 * considered inactive. */
2678 state
= UNIT_INACTIVE
;
2681 r
= sd_bus_message_read(reply
, "o", &path
);
2683 return bus_log_parse_error(r
);
2685 r
= sd_bus_get_property_string(
2687 "org.freedesktop.systemd1",
2689 "org.freedesktop.systemd1.Unit",
2694 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2696 state
= unit_active_state_from_string(buf
);
2697 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2698 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2703 *active_state
= state
;
2707 static int check_triggering_units(
2711 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2712 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2713 _cleanup_strv_free_
char **triggered_by
= NULL
;
2714 bool print_warning_label
= true;
2715 UnitActiveState active_state
;
2719 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2721 return log_error_errno(r
, "Failed to mangle unit name: %m");
2723 path
= unit_dbus_path_from_name(n
);
2727 r
= sd_bus_get_property_string(
2729 "org.freedesktop.systemd1",
2731 "org.freedesktop.systemd1.Unit",
2736 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2738 if (streq(load_state
, "masked"))
2741 r
= sd_bus_get_property_strv(
2743 "org.freedesktop.systemd1",
2745 "org.freedesktop.systemd1.Unit",
2750 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2752 STRV_FOREACH(i
, triggered_by
) {
2753 r
= get_state_one_unit(bus
, *i
, &active_state
);
2757 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2760 if (print_warning_label
) {
2761 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2762 print_warning_label
= false;
2765 log_warning(" %s", *i
);
2771 static const struct {
2774 } unit_actions
[] = {
2775 { "start", "StartUnit" },
2776 { "stop", "StopUnit" },
2777 { "condstop", "StopUnit" },
2778 { "reload", "ReloadUnit" },
2779 { "restart", "RestartUnit" },
2780 { "try-restart", "TryRestartUnit" },
2781 { "condrestart", "TryRestartUnit" },
2782 { "reload-or-restart", "ReloadOrRestartUnit" },
2783 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2784 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2785 { "condreload", "ReloadOrTryRestartUnit" },
2786 { "force-reload", "ReloadOrTryRestartUnit" }
2789 static const char *verb_to_method(const char *verb
) {
2792 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2793 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2794 return unit_actions
[i
].method
;
2799 static const char *method_to_verb(const char *method
) {
2802 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2803 if (streq_ptr(unit_actions
[i
].method
, method
))
2804 return unit_actions
[i
].verb
;
2816 static void wait_context_free(WaitContext
*c
) {
2817 c
->match
= sd_bus_slot_unref(c
->match
);
2818 c
->event
= sd_event_unref(c
->event
);
2819 c
->unit_paths
= set_free_free(c
->unit_paths
);
2822 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2823 WaitContext
*c
= userdata
;
2827 path
= sd_bus_message_get_path(m
);
2828 if (!set_contains(c
->unit_paths
, path
))
2831 /* Check if ActiveState changed to inactive/failed */
2832 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2833 r
= sd_bus_message_skip(m
, "s");
2835 return bus_log_parse_error(r
);
2837 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2839 return bus_log_parse_error(r
);
2841 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2844 r
= sd_bus_message_read(m
, "s", &s
);
2846 return bus_log_parse_error(r
);
2848 if (streq(s
, "ActiveState")) {
2851 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2853 return bus_log_parse_error(r
);
2855 r
= sd_bus_message_read(m
, "s", &s
);
2857 return bus_log_parse_error(r
);
2859 is_failed
= streq(s
, "failed");
2860 if (streq(s
, "inactive") || is_failed
) {
2861 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2862 free(set_remove(c
->unit_paths
, path
));
2863 c
->any_failed
= c
->any_failed
|| is_failed
;
2865 log_debug("ActiveState on %s changed to %s", path
, s
);
2867 break; /* no need to dissect the rest of the message */
2869 /* other property */
2870 r
= sd_bus_message_skip(m
, "v");
2872 return bus_log_parse_error(r
);
2874 r
= sd_bus_message_exit_container(m
);
2876 return bus_log_parse_error(r
);
2879 return bus_log_parse_error(r
);
2881 if (set_isempty(c
->unit_paths
))
2882 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2887 static int start_unit_one(
2892 sd_bus_error
*error
,
2894 WaitContext
*wait_context
) {
2896 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2906 _cleanup_free_
char *unit_path
= NULL
;
2909 log_debug("Watching for property changes of %s", name
);
2910 r
= sd_bus_call_method(
2912 "org.freedesktop.systemd1",
2913 "/org/freedesktop/systemd1",
2914 "org.freedesktop.systemd1.Manager",
2920 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2922 unit_path
= unit_dbus_path_from_name(name
);
2926 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2928 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2930 mt
= strjoina("type='signal',"
2931 "interface='org.freedesktop.DBus.Properties',"
2932 "path='", unit_path
, "',"
2933 "member='PropertiesChanged'");
2934 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2936 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2939 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2941 r
= sd_bus_call_method(
2943 "org.freedesktop.systemd1",
2944 "/org/freedesktop/systemd1",
2945 "org.freedesktop.systemd1.Manager",
2953 /* There's always a fallback possible for legacy actions. */
2954 if (arg_action
!= ACTION_SYSTEMCTL
)
2957 verb
= method_to_verb(method
);
2959 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2961 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2962 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2963 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2964 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2965 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2966 name
[0] == '-' ? " --" : "",
2972 r
= sd_bus_message_read(reply
, "o", &path
);
2974 return bus_log_parse_error(r
);
2976 if (need_daemon_reload(bus
, name
) > 0)
2977 warn_unit_file_changed(name
);
2980 log_debug("Adding %s to the set", path
);
2981 r
= bus_wait_for_jobs_add(w
, path
);
2989 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2990 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2997 STRV_FOREACH(name
, names
) {
3001 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
3003 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
3005 return log_error_errno(r
, "Failed to mangle name: %m");
3007 if (string_is_glob(t
))
3008 r
= strv_consume(&globs
, t
);
3010 r
= strv_consume(&mangled
, t
);
3015 /* Query the manager only if any of the names are a glob, since
3016 * this is fairly expensive */
3017 if (!strv_isempty(globs
)) {
3018 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3019 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
3020 size_t allocated
, n
;
3022 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
3026 n
= strv_length(mangled
);
3029 for (i
= 0; i
< r
; i
++) {
3030 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
3033 mangled
[n
] = strdup(unit_infos
[i
].id
);
3037 mangled
[++n
] = NULL
;
3042 mangled
= NULL
; /* do not free */
3047 static const struct {
3051 } action_table
[_ACTION_MAX
] = {
3052 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3053 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3054 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3055 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3056 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3057 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3058 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3059 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3060 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3061 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3062 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3063 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3064 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3065 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3066 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3069 static enum action
verb_to_action(const char *verb
) {
3072 for (i
= 0; i
< _ACTION_MAX
; i
++)
3073 if (streq_ptr(action_table
[i
].verb
, verb
))
3076 return _ACTION_INVALID
;
3079 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3080 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3081 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3082 _cleanup_strv_free_
char **names
= NULL
;
3084 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3088 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3089 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3093 /* we cannot do sender tracking on the private bus, so we need the full
3094 * one for RefUnit to implement --wait */
3095 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3099 ask_password_agent_open_if_enabled();
3100 polkit_agent_open_maybe();
3102 if (arg_action
== ACTION_SYSTEMCTL
) {
3105 action
= verb_to_action(argv
[0]);
3107 if (action
!= _ACTION_INVALID
) {
3108 method
= "StartUnit";
3109 mode
= action_table
[action
].mode
;
3110 one_name
= action_table
[action
].target
;
3112 if (streq(argv
[0], "isolate")) {
3113 method
= "StartUnit";
3118 method
= verb_to_method(argv
[0]);
3119 mode
= arg_job_mode
;
3124 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3125 assert(action_table
[arg_action
].target
);
3126 assert(action_table
[arg_action
].mode
);
3128 method
= "StartUnit";
3129 mode
= action_table
[arg_action
].mode
;
3130 one_name
= action_table
[arg_action
].target
;
3134 names
= strv_new(one_name
, NULL
);
3136 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3138 return log_error_errno(r
, "Failed to expand names: %m");
3141 if (!arg_no_block
) {
3142 r
= bus_wait_for_jobs_new(bus
, &w
);
3144 return log_error_errno(r
, "Could not watch jobs: %m");
3148 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3150 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3151 if (!wait_context
.unit_paths
)
3154 r
= sd_bus_call_method(
3156 "org.freedesktop.systemd1",
3157 "/org/freedesktop/systemd1",
3158 "org.freedesktop.systemd1.Manager",
3163 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3164 r
= sd_event_default(&wait_context
.event
);
3166 return log_error_errno(r
, "Failed to allocate event loop: %m");
3167 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3169 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3172 STRV_FOREACH(name
, names
) {
3173 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3176 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3177 if (r
>= 0 && q
< 0)
3178 r
= translate_bus_error_to_exit_status(q
, &error
);
3181 if (!arg_no_block
) {
3182 int q
, arg_count
= 0;
3183 const char* extra_args
[4] = {};
3185 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3186 extra_args
[arg_count
++] = "--user";
3188 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3189 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3190 extra_args
[arg_count
++] = "-H";
3191 extra_args
[arg_count
++] = arg_host
;
3192 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3193 extra_args
[arg_count
++] = "-M";
3194 extra_args
[arg_count
++] = arg_host
;
3197 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3201 /* When stopping units, warn if they can still be triggered by
3202 * another active unit (socket, path, timer) */
3203 if (!arg_quiet
&& streq(method
, "StopUnit"))
3204 STRV_FOREACH(name
, names
)
3205 check_triggering_units(bus
, *name
);
3208 if (r
>= 0 && arg_wait
) {
3210 q
= sd_event_loop(wait_context
.event
);
3212 return log_error_errno(q
, "Failed to run event loop: %m");
3213 if (wait_context
.any_failed
)
3221 static int logind_set_wall_message(void) {
3222 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3224 _cleanup_free_
char *m
= NULL
;
3227 r
= acquire_bus(BUS_FULL
, &bus
);
3231 m
= strv_join(arg_wall
, " ");
3235 r
= sd_bus_call_method(
3237 "org.freedesktop.login1",
3238 "/org/freedesktop/login1",
3239 "org.freedesktop.login1.Manager",
3248 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3253 /* Ask systemd-logind, which might grant access to unprivileged users
3254 * through PolicyKit */
3255 static int logind_reboot(enum action a
) {
3257 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3258 const char *method
, *description
;
3262 r
= acquire_bus(BUS_FULL
, &bus
);
3268 case ACTION_POWEROFF
:
3269 method
= "PowerOff";
3270 description
= "power off system";
3275 description
= "reboot system";
3280 description
= "halt system";
3283 case ACTION_SUSPEND
:
3285 description
= "suspend system";
3288 case ACTION_HIBERNATE
:
3289 method
= "Hibernate";
3290 description
= "hibernate system";
3293 case ACTION_HYBRID_SLEEP
:
3294 method
= "HybridSleep";
3295 description
= "put system into hybrid sleep";
3302 polkit_agent_open_maybe();
3303 (void) logind_set_wall_message();
3305 r
= sd_bus_call_method(
3307 "org.freedesktop.login1",
3308 "/org/freedesktop/login1",
3309 "org.freedesktop.login1.Manager",
3313 "b", arg_ask_password
);
3315 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3323 static int logind_check_inhibitors(enum action a
) {
3325 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3326 _cleanup_strv_free_
char **sessions
= NULL
;
3327 const char *what
, *who
, *why
, *mode
;
3334 if (arg_ignore_inhibitors
|| arg_force
> 0)
3346 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3349 r
= acquire_bus(BUS_FULL
, &bus
);
3353 r
= sd_bus_call_method(
3355 "org.freedesktop.login1",
3356 "/org/freedesktop/login1",
3357 "org.freedesktop.login1.Manager",
3363 /* If logind is not around, then there are no inhibitors... */
3366 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3368 return bus_log_parse_error(r
);
3370 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3371 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3372 _cleanup_strv_free_
char **sv
= NULL
;
3374 if (!streq(mode
, "block"))
3377 sv
= strv_split(what
, ":");
3381 if (!pid_is_valid((pid_t
) pid
)) {
3382 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3386 if (!strv_contains(sv
,
3391 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3394 get_process_comm(pid
, &comm
);
3395 user
= uid_to_name(uid
);
3397 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3398 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3403 return bus_log_parse_error(r
);
3405 r
= sd_bus_message_exit_container(reply
);
3407 return bus_log_parse_error(r
);
3409 /* Check for current sessions */
3410 sd_get_sessions(&sessions
);
3411 STRV_FOREACH(s
, sessions
) {
3412 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3414 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3417 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3420 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "tty"))
3423 sd_session_get_tty(*s
, &tty
);
3424 sd_session_get_seat(*s
, &seat
);
3425 sd_session_get_service(*s
, &service
);
3426 user
= uid_to_name(uid
);
3428 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3435 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3436 action_table
[a
].verb
);
3444 static int logind_prepare_firmware_setup(void) {
3446 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3450 r
= acquire_bus(BUS_FULL
, &bus
);
3454 r
= sd_bus_call_method(
3456 "org.freedesktop.login1",
3457 "/org/freedesktop/login1",
3458 "org.freedesktop.login1.Manager",
3459 "SetRebootToFirmwareSetup",
3464 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3468 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3473 static int prepare_firmware_setup(void) {
3476 if (!arg_firmware_setup
)
3479 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3481 r
= efi_set_reboot_to_firmware(true);
3483 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3488 return logind_prepare_firmware_setup();
3491 static int set_exit_code(uint8_t code
) {
3492 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3496 r
= acquire_bus(BUS_MANAGER
, &bus
);
3500 r
= sd_bus_call_method(
3502 "org.freedesktop.systemd1",
3503 "/org/freedesktop/systemd1",
3504 "org.freedesktop.systemd1.Manager",
3510 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3515 static int start_special(int argc
, char *argv
[], void *userdata
) {
3518 bool termination_action
; /* an action that terminates the manager,
3519 * can be performed also by signal. */
3523 a
= verb_to_action(argv
[0]);
3525 r
= logind_check_inhibitors(a
);
3529 if (arg_force
>= 2 && geteuid() != 0) {
3530 log_error("Must be root.");
3534 r
= prepare_firmware_setup();
3538 if (a
== ACTION_REBOOT
&& argc
> 1) {
3539 r
= update_reboot_parameter_and_warn(argv
[1]);
3543 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3546 /* If the exit code is not given on the command line,
3547 * don't reset it to zero: just keep it as it might
3548 * have been set previously. */
3550 r
= safe_atou8(argv
[1], &code
);
3552 return log_error_errno(r
, "Invalid exit code.");
3554 r
= set_exit_code(code
);
3559 termination_action
= IN_SET(a
,
3563 if (termination_action
&& arg_force
>= 2)
3566 if (arg_force
>= 1 &&
3567 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3568 r
= trivial_method(argc
, argv
, userdata
);
3570 /* First try logind, to allow authentication with polkit */
3577 ACTION_HYBRID_SLEEP
)) {
3579 r
= logind_reboot(a
);
3582 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3583 /* requested operation is not supported or already in progress */
3586 /* On all other errors, try low-level operation. In order to minimize the difference between
3587 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3588 * logind's shutdown operations are always non-blocking. */
3590 arg_no_block
= true;
3592 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3593 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3594 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3595 arg_no_block
= true;
3597 r
= start_unit(argc
, argv
, userdata
);
3600 if (termination_action
&& arg_force
< 2 &&
3601 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3602 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3607 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3608 /* Like start_special above, but raises an error when running in user mode */
3610 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3611 log_error("Bad action for %s mode.",
3612 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3616 return start_special(argc
, argv
, userdata
);
3619 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3620 _cleanup_strv_free_
char **names
= NULL
;
3621 UnitActiveState active_state
;
3627 r
= acquire_bus(BUS_MANAGER
, &bus
);
3631 r
= expand_names(bus
, args
, NULL
, &names
);
3633 return log_error_errno(r
, "Failed to expand names: %m");
3635 STRV_FOREACH(name
, names
) {
3636 r
= get_state_one_unit(bus
, *name
, &active_state
);
3641 puts(unit_active_state_to_string(active_state
));
3643 for (i
= 0; i
< nb_states
; ++i
)
3644 if (good_states
[i
] == active_state
)
3648 /* use the given return code for the case that we won't find
3649 * any unit which matches the list */
3650 return found
? 0 : code
;
3653 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3654 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3655 /* According to LSB: 3, "program is not running" */
3656 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3659 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3660 const UnitActiveState states
[] = { UNIT_FAILED
};
3661 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3664 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3665 _cleanup_strv_free_
char **names
= NULL
;
3666 char *kill_who
= NULL
, **name
;
3670 r
= acquire_bus(BUS_MANAGER
, &bus
);
3674 polkit_agent_open_maybe();
3677 arg_kill_who
= "all";
3679 /* --fail was specified */
3680 if (streq(arg_job_mode
, "fail"))
3681 kill_who
= strjoina(arg_kill_who
, "-fail");
3683 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3685 return log_error_errno(r
, "Failed to expand names: %m");
3687 STRV_FOREACH(name
, names
) {
3688 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3690 q
= sd_bus_call_method(
3692 "org.freedesktop.systemd1",
3693 "/org/freedesktop/systemd1",
3694 "org.freedesktop.systemd1.Manager",
3698 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3700 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3709 typedef struct ExecStatusInfo
{
3717 usec_t start_timestamp
;
3718 usec_t exit_timestamp
;
3723 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3726 static void exec_status_info_free(ExecStatusInfo
*i
) {
3735 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3736 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3739 int32_t code
, status
;
3745 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3747 return bus_log_parse_error(r
);
3751 r
= sd_bus_message_read(m
, "s", &path
);
3753 return bus_log_parse_error(r
);
3755 i
->path
= strdup(path
);
3759 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3761 return bus_log_parse_error(r
);
3763 r
= sd_bus_message_read(m
,
3766 &start_timestamp
, &start_timestamp_monotonic
,
3767 &exit_timestamp
, &exit_timestamp_monotonic
,
3771 return bus_log_parse_error(r
);
3774 i
->start_timestamp
= (usec_t
) start_timestamp
;
3775 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3776 i
->pid
= (pid_t
) pid
;
3780 r
= sd_bus_message_exit_container(m
);
3782 return bus_log_parse_error(r
);
3787 typedef struct UnitCondition
{
3794 LIST_FIELDS(struct UnitCondition
, conditions
);
3797 static void unit_condition_free(UnitCondition
*c
) {
3806 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3808 typedef struct UnitStatusInfo
{
3810 const char *load_state
;
3811 const char *active_state
;
3812 const char *sub_state
;
3813 const char *unit_file_state
;
3814 const char *unit_file_preset
;
3816 const char *description
;
3817 const char *following
;
3819 char **documentation
;
3821 const char *fragment_path
;
3822 const char *source_path
;
3823 const char *control_group
;
3825 char **dropin_paths
;
3827 const char *load_error
;
3830 usec_t inactive_exit_timestamp
;
3831 usec_t inactive_exit_timestamp_monotonic
;
3832 usec_t active_enter_timestamp
;
3833 usec_t active_exit_timestamp
;
3834 usec_t inactive_enter_timestamp
;
3836 bool need_daemon_reload
;
3842 const char *status_text
;
3843 const char *pid_file
;
3847 usec_t start_timestamp
;
3848 usec_t exit_timestamp
;
3850 int exit_code
, exit_status
;
3852 usec_t condition_timestamp
;
3853 bool condition_result
;
3854 LIST_HEAD(UnitCondition
, conditions
);
3856 usec_t assert_timestamp
;
3858 bool failed_assert_trigger
;
3859 bool failed_assert_negate
;
3860 const char *failed_assert
;
3861 const char *failed_assert_parameter
;
3862 usec_t next_elapse_real
;
3863 usec_t next_elapse_monotonic
;
3866 unsigned n_accepted
;
3867 unsigned n_connections
;
3870 /* Pairs of type, path */
3874 const char *sysfs_path
;
3876 /* Mount, Automount */
3883 uint64_t memory_current
;
3884 uint64_t memory_low
;
3885 uint64_t memory_high
;
3886 uint64_t memory_max
;
3887 uint64_t memory_swap_max
;
3888 uint64_t memory_limit
;
3889 uint64_t cpu_usage_nsec
;
3890 uint64_t tasks_current
;
3893 uint64_t ip_ingress_bytes
;
3894 uint64_t ip_egress_bytes
;
3896 LIST_HEAD(ExecStatusInfo
, exec
);
3899 static void unit_status_info_free(UnitStatusInfo
*info
) {
3903 strv_free(info
->documentation
);
3904 strv_free(info
->dropin_paths
);
3905 strv_free(info
->listen
);
3907 while ((c
= info
->conditions
)) {
3908 LIST_REMOVE(conditions
, info
->conditions
, c
);
3909 unit_condition_free(c
);
3912 while ((p
= info
->exec
)) {
3913 LIST_REMOVE(exec
, info
->exec
, p
);
3914 exec_status_info_free(p
);
3918 static void print_status_info(
3924 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3926 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3927 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3934 /* This shows pretty information about a unit. See
3935 * print_property() for a low-level property printer */
3937 if (streq_ptr(i
->active_state
, "failed")) {
3938 active_on
= ansi_highlight_red();
3939 active_off
= ansi_normal();
3940 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
3941 active_on
= ansi_highlight_green();
3942 active_off
= ansi_normal();
3944 active_on
= active_off
= "";
3946 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3948 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3949 printf(" - %s", i
->description
);
3954 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3956 if (streq_ptr(i
->load_state
, "error")) {
3957 on
= ansi_highlight_red();
3958 off
= ansi_normal();
3962 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3964 if (i
->load_error
!= 0)
3965 printf(" Loaded: %s%s%s (Reason: %s)\n",
3966 on
, strna(i
->load_state
), off
, i
->load_error
);
3967 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3968 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3969 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3970 else if (path
&& !isempty(i
->unit_file_state
))
3971 printf(" Loaded: %s%s%s (%s; %s)\n",
3972 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3974 printf(" Loaded: %s%s%s (%s)\n",
3975 on
, strna(i
->load_state
), off
, path
);
3977 printf(" Loaded: %s%s%s\n",
3978 on
, strna(i
->load_state
), off
);
3981 printf("Transient: yes\n");
3983 if (!strv_isempty(i
->dropin_paths
)) {
3984 _cleanup_free_
char *dir
= NULL
;
3988 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3989 if (! dir
|| last
) {
3990 printf(dir
? " " : " Drop-In: ");
3994 dir
= dirname_malloc(*dropin
);
4000 printf("%s\n %s", dir
,
4001 special_glyph(TREE_RIGHT
));
4004 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4006 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4010 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4012 printf(" Active: %s%s (%s)%s",
4013 active_on
, strna(i
->active_state
), ss
, active_off
);
4015 printf(" Active: %s%s%s",
4016 active_on
, strna(i
->active_state
), active_off
);
4018 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4019 printf(" (Result: %s)", i
->result
);
4021 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4022 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4023 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4024 i
->active_exit_timestamp
;
4026 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4027 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4030 printf(" since %s; %s\n", s2
, s1
);
4032 printf(" since %s\n", s2
);
4036 if (endswith(i
->id
, ".timer")) {
4037 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4038 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4039 char *next_rel_time
, *next_time
;
4040 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4041 i
->next_elapse_monotonic
};
4044 printf(" Trigger: ");
4046 dual_timestamp_get(&nw
);
4047 next_elapse
= calc_next_elapse(&nw
, &next
);
4048 next_rel_time
= format_timestamp_relative(tstamp1
,
4051 next_time
= format_timestamp(tstamp2
,
4055 if (next_time
&& next_rel_time
)
4056 printf("%s; %s\n", next_time
, next_rel_time
);
4061 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4065 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4066 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4068 printf("Condition: start %scondition failed%s at %s%s%s\n",
4069 ansi_highlight_yellow(), ansi_normal(),
4070 s2
, s1
? "; " : "", strempty(s1
));
4072 LIST_FOREACH(conditions
, c
, i
->conditions
)
4073 if (c
->tristate
< 0)
4076 LIST_FOREACH(conditions
, c
, i
->conditions
)
4077 if (c
->tristate
< 0)
4078 printf(" %s %s=%s%s%s was not met\n",
4079 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4081 c
->trigger
? "|" : "",
4082 c
->negate
? "!" : "",
4086 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4087 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4088 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4090 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4091 ansi_highlight_red(), ansi_normal(),
4092 s2
, s1
? "; " : "", strempty(s1
));
4093 if (i
->failed_assert_trigger
)
4094 printf(" none of the trigger assertions were met\n");
4095 else if (i
->failed_assert
)
4096 printf(" %s=%s%s was not met\n",
4098 i
->failed_assert_negate
? "!" : "",
4099 i
->failed_assert_parameter
);
4103 printf(" Device: %s\n", i
->sysfs_path
);
4105 printf(" Where: %s\n", i
->where
);
4107 printf(" What: %s\n", i
->what
);
4109 STRV_FOREACH(t
, i
->documentation
)
4110 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4112 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4113 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4116 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4118 LIST_FOREACH(exec
, p
, i
->exec
) {
4119 _cleanup_free_
char *argv
= NULL
;
4122 /* Only show exited processes here */
4126 argv
= strv_join(p
->argv
, " ");
4127 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4129 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4131 on
= ansi_highlight_red();
4132 off
= ansi_normal();
4136 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4138 if (p
->code
== CLD_EXITED
) {
4141 printf("status=%i", p
->status
);
4143 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4148 printf("signal=%s", signal_to_string(p
->status
));
4150 printf(")%s\n", off
);
4152 if (i
->main_pid
== p
->pid
&&
4153 i
->start_timestamp
== p
->start_timestamp
&&
4154 i
->exit_timestamp
== p
->start_timestamp
)
4155 /* Let's not show this twice */
4158 if (p
->pid
== i
->control_pid
)
4162 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4163 if (i
->main_pid
> 0) {
4164 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4167 _cleanup_free_
char *comm
= NULL
;
4168 (void) get_process_comm(i
->main_pid
, &comm
);
4170 printf(" (%s)", comm
);
4171 } else if (i
->exit_code
> 0) {
4172 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4174 if (i
->exit_code
== CLD_EXITED
) {
4177 printf("status=%i", i
->exit_status
);
4179 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4184 printf("signal=%s", signal_to_string(i
->exit_status
));
4189 if (i
->control_pid
> 0) {
4190 _cleanup_free_
char *c
= NULL
;
4192 if (i
->main_pid
> 0)
4193 fputs("; Control PID: ", stdout
);
4195 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4197 printf(PID_FMT
, i
->control_pid
);
4199 (void) get_process_comm(i
->control_pid
, &c
);
4208 printf(" Status: \"%s\"\n", i
->status_text
);
4209 if (i
->status_errno
> 0)
4210 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4212 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4213 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4215 printf(" IP: %s in, %s out\n",
4216 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4217 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4220 if (i
->tasks_current
!= (uint64_t) -1) {
4221 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4223 if (i
->tasks_max
!= (uint64_t) -1)
4224 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4229 if (i
->memory_current
!= (uint64_t) -1) {
4230 char buf
[FORMAT_BYTES_MAX
];
4232 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4234 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4235 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4236 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4237 const char *prefix
= "";
4240 if (i
->memory_low
> 0) {
4241 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4244 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4245 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4248 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4249 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4252 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4253 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4256 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4257 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4265 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4266 char buf
[FORMAT_TIMESPAN_MAX
];
4267 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4270 if (i
->control_group
) {
4271 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4272 static const char prefix
[] = " ";
4275 printf(" CGroup: %s\n", i
->control_group
);
4278 if (c
> sizeof(prefix
) - 1)
4279 c
-= sizeof(prefix
) - 1;
4283 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4288 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4290 if (i
->main_pid
> 0)
4291 extra
[k
++] = i
->main_pid
;
4293 if (i
->control_pid
> 0)
4294 extra
[k
++] = i
->control_pid
;
4296 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4298 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4301 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4302 show_journal_by_unit(
4307 i
->inactive_exit_timestamp_monotonic
,
4310 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4311 SD_JOURNAL_LOCAL_ONLY
,
4312 arg_scope
== UNIT_FILE_SYSTEM
,
4315 if (i
->need_daemon_reload
)
4316 warn_unit_file_changed(i
->id
);
4319 static void show_unit_help(UnitStatusInfo
*i
) {
4324 if (!i
->documentation
) {
4325 log_info("Documentation for %s not known.", i
->id
);
4329 STRV_FOREACH(p
, i
->documentation
)
4330 if (startswith(*p
, "man:"))
4331 show_man_page(*p
+ 4, false);
4333 log_info("Can't show: %s", *p
);
4336 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4343 switch (contents
[0]) {
4345 case SD_BUS_TYPE_STRING
: {
4348 r
= sd_bus_message_read(m
, "s", &s
);
4350 return bus_log_parse_error(r
);
4353 if (streq(name
, "Id"))
4355 else if (streq(name
, "LoadState"))
4357 else if (streq(name
, "ActiveState"))
4358 i
->active_state
= s
;
4359 else if (streq(name
, "SubState"))
4361 else if (streq(name
, "Description"))
4363 else if (streq(name
, "FragmentPath"))
4364 i
->fragment_path
= s
;
4365 else if (streq(name
, "SourcePath"))
4368 else if (streq(name
, "DefaultControlGroup")) {
4370 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4372 i
->control_group
= e
;
4375 else if (streq(name
, "ControlGroup"))
4376 i
->control_group
= s
;
4377 else if (streq(name
, "StatusText"))
4379 else if (streq(name
, "PIDFile"))
4381 else if (streq(name
, "SysFSPath"))
4383 else if (streq(name
, "Where"))
4385 else if (streq(name
, "What"))
4387 else if (streq(name
, "Following"))
4389 else if (streq(name
, "UnitFileState"))
4390 i
->unit_file_state
= s
;
4391 else if (streq(name
, "UnitFilePreset"))
4392 i
->unit_file_preset
= s
;
4393 else if (streq(name
, "Result"))
4400 case SD_BUS_TYPE_BOOLEAN
: {
4403 r
= sd_bus_message_read(m
, "b", &b
);
4405 return bus_log_parse_error(r
);
4407 if (streq(name
, "Accept"))
4409 else if (streq(name
, "NeedDaemonReload"))
4410 i
->need_daemon_reload
= b
;
4411 else if (streq(name
, "ConditionResult"))
4412 i
->condition_result
= b
;
4413 else if (streq(name
, "AssertResult"))
4414 i
->assert_result
= b
;
4415 else if (streq(name
, "Transient"))
4421 case SD_BUS_TYPE_UINT32
: {
4424 r
= sd_bus_message_read(m
, "u", &u
);
4426 return bus_log_parse_error(r
);
4428 if (streq(name
, "MainPID")) {
4430 i
->main_pid
= (pid_t
) u
;
4433 } else if (streq(name
, "ControlPID"))
4434 i
->control_pid
= (pid_t
) u
;
4435 else if (streq(name
, "ExecMainPID")) {
4437 i
->main_pid
= (pid_t
) u
;
4438 } else if (streq(name
, "NAccepted"))
4440 else if (streq(name
, "NConnections"))
4441 i
->n_connections
= u
;
4446 case SD_BUS_TYPE_INT32
: {
4449 r
= sd_bus_message_read(m
, "i", &j
);
4451 return bus_log_parse_error(r
);
4453 if (streq(name
, "ExecMainCode"))
4454 i
->exit_code
= (int) j
;
4455 else if (streq(name
, "ExecMainStatus"))
4456 i
->exit_status
= (int) j
;
4457 else if (streq(name
, "StatusErrno"))
4458 i
->status_errno
= (int) j
;
4463 case SD_BUS_TYPE_UINT64
: {
4466 r
= sd_bus_message_read(m
, "t", &u
);
4468 return bus_log_parse_error(r
);
4470 if (streq(name
, "ExecMainStartTimestamp"))
4471 i
->start_timestamp
= (usec_t
) u
;
4472 else if (streq(name
, "ExecMainExitTimestamp"))
4473 i
->exit_timestamp
= (usec_t
) u
;
4474 else if (streq(name
, "ActiveEnterTimestamp"))
4475 i
->active_enter_timestamp
= (usec_t
) u
;
4476 else if (streq(name
, "InactiveEnterTimestamp"))
4477 i
->inactive_enter_timestamp
= (usec_t
) u
;
4478 else if (streq(name
, "InactiveExitTimestamp"))
4479 i
->inactive_exit_timestamp
= (usec_t
) u
;
4480 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4481 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4482 else if (streq(name
, "ActiveExitTimestamp"))
4483 i
->active_exit_timestamp
= (usec_t
) u
;
4484 else if (streq(name
, "ConditionTimestamp"))
4485 i
->condition_timestamp
= (usec_t
) u
;
4486 else if (streq(name
, "AssertTimestamp"))
4487 i
->assert_timestamp
= (usec_t
) u
;
4488 else if (streq(name
, "MemoryCurrent"))
4489 i
->memory_current
= u
;
4490 else if (streq(name
, "MemoryLow"))
4492 else if (streq(name
, "MemoryHigh"))
4494 else if (streq(name
, "MemoryMax"))
4496 else if (streq(name
, "MemorySwapMax"))
4497 i
->memory_swap_max
= u
;
4498 else if (streq(name
, "MemoryLimit"))
4499 i
->memory_limit
= u
;
4500 else if (streq(name
, "TasksCurrent"))
4501 i
->tasks_current
= u
;
4502 else if (streq(name
, "TasksMax"))
4504 else if (streq(name
, "CPUUsageNSec"))
4505 i
->cpu_usage_nsec
= u
;
4506 else if (streq(name
, "NextElapseUSecMonotonic"))
4507 i
->next_elapse_monotonic
= u
;
4508 else if (streq(name
, "NextElapseUSecRealtime"))
4509 i
->next_elapse_real
= u
;
4510 else if (streq(name
, "IPIngressBytes"))
4511 i
->ip_ingress_bytes
= u
;
4512 else if (streq(name
, "IPEgressBytes"))
4513 i
->ip_egress_bytes
= u
;
4518 case SD_BUS_TYPE_ARRAY
:
4520 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4521 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4523 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4525 return bus_log_parse_error(r
);
4527 info
= new0(ExecStatusInfo
, 1);
4531 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4533 info
->name
= strdup(name
);
4537 LIST_PREPEND(exec
, i
->exec
, info
);
4539 info
= new0(ExecStatusInfo
, 1);
4545 return bus_log_parse_error(r
);
4547 r
= sd_bus_message_exit_container(m
);
4549 return bus_log_parse_error(r
);
4553 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4554 const char *type
, *path
;
4556 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4558 return bus_log_parse_error(r
);
4560 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4562 r
= strv_extend(&i
->listen
, type
);
4566 r
= strv_extend(&i
->listen
, path
);
4571 return bus_log_parse_error(r
);
4573 r
= sd_bus_message_exit_container(m
);
4575 return bus_log_parse_error(r
);
4579 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4581 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4583 return bus_log_parse_error(r
);
4585 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4587 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4589 return bus_log_parse_error(r
);
4591 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4592 const char *cond
, *param
;
4593 int trigger
, negate
;
4596 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4598 return bus_log_parse_error(r
);
4600 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4601 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4603 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4605 c
= new0(UnitCondition
, 1);
4609 c
->name
= strdup(cond
);
4610 c
->param
= strdup(param
);
4611 if (!c
->name
|| !c
->param
)
4614 c
->trigger
= trigger
;
4616 c
->tristate
= state
;
4618 LIST_PREPEND(conditions
, i
->conditions
, c
);
4622 return bus_log_parse_error(r
);
4624 r
= sd_bus_message_exit_container(m
);
4626 return bus_log_parse_error(r
);
4628 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4629 const char *cond
, *param
;
4630 int trigger
, negate
;
4633 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4635 return bus_log_parse_error(r
);
4637 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4638 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4639 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4640 i
->failed_assert
= cond
;
4641 i
->failed_assert_trigger
= trigger
;
4642 i
->failed_assert_negate
= negate
;
4643 i
->failed_assert_parameter
= param
;
4647 return bus_log_parse_error(r
);
4649 r
= sd_bus_message_exit_container(m
);
4651 return bus_log_parse_error(r
);
4658 case SD_BUS_TYPE_STRUCT_BEGIN
:
4660 if (streq(name
, "LoadError")) {
4661 const char *n
, *message
;
4663 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4665 return bus_log_parse_error(r
);
4667 if (!isempty(message
))
4668 i
->load_error
= message
;
4681 r
= sd_bus_message_skip(m
, contents
);
4683 return bus_log_parse_error(r
);
4688 #define print_prop(name, fmt, ...) \
4691 printf(fmt "\n", __VA_ARGS__); \
4693 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4696 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4702 /* This is a low-level property printer, see
4703 * print_status_info() for the nicer output */
4705 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4706 /* skip what we didn't read */
4707 r
= sd_bus_message_skip(m
, contents
);
4711 switch (contents
[0]) {
4713 case SD_BUS_TYPE_STRUCT_BEGIN
:
4715 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4718 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4720 return bus_log_parse_error(r
);
4723 print_prop(name
, "%"PRIu32
, u
);
4725 print_prop(name
, "%s", "");
4729 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4732 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4734 return bus_log_parse_error(r
);
4736 if (arg_all
|| !isempty(s
))
4737 print_prop(name
, "%s", s
);
4741 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4742 const char *a
= NULL
, *b
= NULL
;
4744 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4746 return bus_log_parse_error(r
);
4748 if (arg_all
|| !isempty(a
) || !isempty(b
))
4749 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4752 } else if (streq_ptr(name
, "SystemCallFilter")) {
4753 _cleanup_strv_free_
char **l
= NULL
;
4756 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4758 return bus_log_parse_error(r
);
4760 r
= sd_bus_message_read(m
, "b", &whitelist
);
4762 return bus_log_parse_error(r
);
4764 r
= sd_bus_message_read_strv(m
, &l
);
4766 return bus_log_parse_error(r
);
4768 r
= sd_bus_message_exit_container(m
);
4770 return bus_log_parse_error(r
);
4772 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4777 fputs(name
, stdout
);
4784 STRV_FOREACH(i
, l
) {
4792 fputc('\n', stdout
);
4800 case SD_BUS_TYPE_ARRAY
:
4802 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4806 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4808 return bus_log_parse_error(r
);
4810 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4811 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4814 return bus_log_parse_error(r
);
4816 r
= sd_bus_message_exit_container(m
);
4818 return bus_log_parse_error(r
);
4822 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4823 const char *type
, *path
;
4825 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4827 return bus_log_parse_error(r
);
4829 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4830 print_prop(type
, "%s", path
);
4832 return bus_log_parse_error(r
);
4834 r
= sd_bus_message_exit_container(m
);
4836 return bus_log_parse_error(r
);
4840 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4841 const char *type
, *path
;
4843 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4845 return bus_log_parse_error(r
);
4847 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4851 printf("Listen%s=%s\n", type
, path
);
4853 return bus_log_parse_error(r
);
4855 r
= sd_bus_message_exit_container(m
);
4857 return bus_log_parse_error(r
);
4861 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4863 uint64_t value
, next_elapse
;
4865 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4867 return bus_log_parse_error(r
);
4869 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4870 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4872 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4873 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4874 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4877 return bus_log_parse_error(r
);
4879 r
= sd_bus_message_exit_container(m
);
4881 return bus_log_parse_error(r
);
4885 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4886 ExecStatusInfo info
= {};
4888 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4890 return bus_log_parse_error(r
);
4892 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4893 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4894 _cleanup_free_
char *tt
;
4896 tt
= strv_join(info
.argv
, " ");
4899 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4902 yes_no(info
.ignore
),
4903 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4904 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4906 sigchld_code_to_string(info
.code
),
4908 info
.code
== CLD_EXITED
? "" : "/",
4909 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4912 strv_free(info
.argv
);
4916 r
= sd_bus_message_exit_container(m
);
4918 return bus_log_parse_error(r
);
4922 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4923 const char *path
, *rwm
;
4925 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4927 return bus_log_parse_error(r
);
4929 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4930 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4932 return bus_log_parse_error(r
);
4934 r
= sd_bus_message_exit_container(m
);
4936 return bus_log_parse_error(r
);
4940 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4941 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4945 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4947 return bus_log_parse_error(r
);
4949 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4950 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4952 return bus_log_parse_error(r
);
4954 r
= sd_bus_message_exit_container(m
);
4956 return bus_log_parse_error(r
);
4960 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4961 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4962 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4966 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4968 return bus_log_parse_error(r
);
4970 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4971 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4973 return bus_log_parse_error(r
);
4975 r
= sd_bus_message_exit_container(m
);
4977 return bus_log_parse_error(r
);
4985 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
4987 return bus_log_parse_error(r
);
4990 r
= sd_bus_message_skip(m
, contents
);
4992 return bus_log_parse_error(r
);
4995 printf("%s=[unprintable]\n", name
);
5001 static int show_one(
5006 bool show_properties
,
5010 static const struct bus_properties_map property_map
[] = {
5011 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5012 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
5016 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5017 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5018 _cleanup_set_free_ Set
*found_properties
= NULL
;
5019 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
5020 .memory_current
= (uint64_t) -1,
5021 .memory_high
= CGROUP_LIMIT_MAX
,
5022 .memory_max
= CGROUP_LIMIT_MAX
,
5023 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5024 .memory_limit
= (uint64_t) -1,
5025 .cpu_usage_nsec
= (uint64_t) -1,
5026 .tasks_current
= (uint64_t) -1,
5027 .tasks_max
= (uint64_t) -1,
5028 .ip_ingress_bytes
= (uint64_t) -1,
5029 .ip_egress_bytes
= (uint64_t) -1,
5036 log_debug("Showing one %s", path
);
5038 r
= sd_bus_call_method(
5040 "org.freedesktop.systemd1",
5042 "org.freedesktop.DBus.Properties",
5048 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5051 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
5053 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5055 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5056 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
5057 "Unit %s could not be found.", unit
);
5059 if (streq(verb
, "status"))
5060 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5062 if (!streq(verb
, "show"))
5066 r
= sd_bus_message_rewind(reply
, true);
5068 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5071 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
5073 return bus_log_parse_error(r
);
5080 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
5081 const char *name
, *contents
;
5083 r
= sd_bus_message_read(reply
, "s", &name
);
5085 return bus_log_parse_error(r
);
5087 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
5089 return bus_log_parse_error(r
);
5091 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
5093 return bus_log_parse_error(r
);
5095 if (show_properties
) {
5096 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
5100 r
= set_put(found_properties
, name
);
5101 if (r
< 0 && r
!= EEXIST
)
5104 r
= print_property(name
, reply
, contents
);
5106 r
= status_property(name
, reply
, &info
, contents
);
5110 r
= sd_bus_message_exit_container(reply
);
5112 return bus_log_parse_error(r
);
5114 r
= sd_bus_message_exit_container(reply
);
5116 return bus_log_parse_error(r
);
5119 return bus_log_parse_error(r
);
5121 r
= sd_bus_message_exit_container(reply
);
5123 return bus_log_parse_error(r
);
5126 if (show_properties
) {
5129 STRV_FOREACH(pp
, arg_properties
)
5130 if (!set_contains(found_properties
, *pp
))
5131 log_debug("Property %s does not exist.", *pp
);
5133 } else if (streq(verb
, "help"))
5134 show_unit_help(&info
);
5135 else if (streq(verb
, "status")) {
5136 print_status_info(bus
, &info
, ellipsized
);
5138 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5139 r
= EXIT_PROGRAM_NOT_RUNNING
;
5141 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5147 static int get_unit_dbus_path_by_pid(
5152 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5153 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5157 r
= sd_bus_call_method(
5159 "org.freedesktop.systemd1",
5160 "/org/freedesktop/systemd1",
5161 "org.freedesktop.systemd1.Manager",
5167 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5169 r
= sd_bus_message_read(reply
, "o", &u
);
5171 return bus_log_parse_error(r
);
5181 static int show_all(
5184 bool show_properties
,
5188 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5189 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5194 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5198 pager_open(arg_no_pager
, false);
5202 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5204 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5205 _cleanup_free_
char *p
= NULL
;
5207 p
= unit_dbus_path_from_name(u
->id
);
5211 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5214 else if (r
> 0 && ret
== 0)
5221 static int show_system_status(sd_bus
*bus
) {
5222 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5223 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5224 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5225 _cleanup_free_
char *hn
= NULL
;
5226 const char *on
, *off
;
5229 hn
= gethostname_malloc();
5233 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, &mi
);
5235 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5237 if (streq_ptr(mi
.state
, "degraded")) {
5238 on
= ansi_highlight_red();
5239 off
= ansi_normal();
5240 } else if (streq_ptr(mi
.state
, "running")) {
5241 on
= ansi_highlight_green();
5242 off
= ansi_normal();
5244 on
= ansi_highlight_yellow();
5245 off
= ansi_normal();
5248 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5250 printf(" State: %s%s%s\n",
5251 on
, strna(mi
.state
), off
);
5253 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5254 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5256 printf(" Since: %s; %s\n",
5257 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5258 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5260 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5261 if (IN_SET(arg_transport
,
5262 BUS_TRANSPORT_LOCAL
,
5263 BUS_TRANSPORT_MACHINE
)) {
5264 static const char prefix
[] = " ";
5268 if (c
> sizeof(prefix
) - 1)
5269 c
-= sizeof(prefix
) - 1;
5273 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5279 static int show(int argc
, char *argv
[], void *userdata
) {
5280 bool show_properties
, show_status
, show_help
, new_line
= false;
5281 bool ellipsized
= false;
5287 show_properties
= streq(argv
[0], "show");
5288 show_status
= streq(argv
[0], "status");
5289 show_help
= streq(argv
[0], "help");
5291 if (show_help
&& argc
<= 1) {
5292 log_error("This command expects one or more unit names. Did you mean --help?");
5296 r
= acquire_bus(BUS_MANAGER
, &bus
);
5300 pager_open(arg_no_pager
, false);
5303 /* Increase max number of open files to 16K if we can, we
5304 * might needs this when browsing journal files, which might
5305 * be split up into many files. */
5306 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5308 /* If no argument is specified inspect the manager itself */
5309 if (show_properties
&& argc
<= 1)
5310 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5312 if (show_status
&& argc
<= 1) {
5314 show_system_status(bus
);
5318 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5320 _cleanup_free_
char **patterns
= NULL
;
5323 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5324 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5327 if (safe_atou32(*name
, &id
) < 0) {
5328 if (strv_push(&patterns
, *name
) < 0)
5332 } else if (show_properties
) {
5333 /* Interpret as job id */
5334 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5338 /* Interpret as PID */
5339 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5345 r
= unit_name_from_dbus_path(path
, &unit
);
5350 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5353 else if (r
> 0 && ret
== 0)
5357 if (!strv_isempty(patterns
)) {
5358 _cleanup_strv_free_
char **names
= NULL
;
5360 r
= expand_names(bus
, patterns
, NULL
, &names
);
5362 return log_error_errno(r
, "Failed to expand names: %m");
5364 STRV_FOREACH(name
, names
) {
5365 _cleanup_free_
char *path
;
5367 path
= unit_dbus_path_from_name(*name
);
5371 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5374 if (r
> 0 && ret
== 0)
5380 if (ellipsized
&& !arg_quiet
)
5381 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5386 static int cat_file(const char *filename
, bool newline
) {
5387 _cleanup_close_
int fd
;
5389 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5393 printf("%s%s# %s%s\n",
5394 newline
? "\n" : "",
5395 ansi_highlight_blue(),
5400 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5403 static int cat(int argc
, char *argv
[], void *userdata
) {
5404 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5405 _cleanup_strv_free_
char **names
= NULL
;
5411 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5412 log_error("Cannot remotely cat units.");
5416 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5418 return log_error_errno(r
, "Failed to determine unit paths: %m");
5420 r
= acquire_bus(BUS_MANAGER
, &bus
);
5424 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5426 return log_error_errno(r
, "Failed to expand names: %m");
5428 pager_open(arg_no_pager
, false);
5430 STRV_FOREACH(name
, names
) {
5431 _cleanup_free_
char *fragment_path
= NULL
;
5432 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5435 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5446 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5448 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5449 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5450 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5451 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5452 ansi_highlight_red(),
5454 ansi_highlight_red(),
5455 ansi_highlight_red(),
5456 ansi_highlight_red(),
5457 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5460 if (fragment_path
) {
5461 r
= cat_file(fragment_path
, false);
5463 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5466 STRV_FOREACH(path
, dropin_paths
) {
5467 r
= cat_file(*path
, path
== dropin_paths
);
5469 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5476 static int set_property(int argc
, char *argv
[], void *userdata
) {
5477 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5478 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5479 _cleanup_free_
char *n
= NULL
;
5483 r
= acquire_bus(BUS_MANAGER
, &bus
);
5487 polkit_agent_open_maybe();
5489 r
= sd_bus_message_new_method_call(
5492 "org.freedesktop.systemd1",
5493 "/org/freedesktop/systemd1",
5494 "org.freedesktop.systemd1.Manager",
5495 "SetUnitProperties");
5497 return bus_log_create_error(r
);
5499 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5501 return log_error_errno(r
, "Failed to mangle unit name: %m");
5503 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5505 return bus_log_create_error(r
);
5507 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5509 return bus_log_create_error(r
);
5511 r
= bus_append_unit_property_assignment_many(m
, strv_skip(argv
, 2));
5515 r
= sd_bus_message_close_container(m
);
5517 return bus_log_create_error(r
);
5519 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5521 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5526 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5527 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5528 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5533 r
= acquire_bus(BUS_MANAGER
, &bus
);
5537 polkit_agent_open_maybe();
5539 switch (arg_action
) {
5546 method
= "Reexecute";
5549 case ACTION_SYSTEMCTL
:
5550 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5551 /* "daemon-reload" */ "Reload";
5555 assert_not_reached("Unexpected action");
5558 r
= sd_bus_message_new_method_call(
5561 "org.freedesktop.systemd1",
5562 "/org/freedesktop/systemd1",
5563 "org.freedesktop.systemd1.Manager",
5566 return bus_log_create_error(r
);
5568 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5569 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5570 * their timeout, and for everything else there's the same time budget in place. */
5572 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5574 /* On reexecution, we expect a disconnect, not a reply */
5575 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5578 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5579 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5581 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5582 * old ways of doing things, hence don't log any error in that case here. */
5584 return r
< 0 ? r
: 0;
5587 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5588 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5593 r
= acquire_bus(BUS_MANAGER
, &bus
);
5597 polkit_agent_open_maybe();
5600 streq(argv
[0], "clear-jobs") ||
5601 streq(argv
[0], "cancel") ? "ClearJobs" :
5602 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5603 streq(argv
[0], "halt") ? "Halt" :
5604 streq(argv
[0], "reboot") ? "Reboot" :
5605 streq(argv
[0], "kexec") ? "KExec" :
5606 streq(argv
[0], "exit") ? "Exit" :
5607 /* poweroff */ "PowerOff";
5609 r
= sd_bus_call_method(
5611 "org.freedesktop.systemd1",
5612 "/org/freedesktop/systemd1",
5613 "org.freedesktop.systemd1.Manager",
5618 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5619 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5621 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5622 * old ways of doing things, hence don't log any error in that case here. */
5624 return r
< 0 ? r
: 0;
5627 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5628 _cleanup_strv_free_
char **names
= NULL
;
5634 return trivial_method(argc
, argv
, userdata
);
5636 r
= acquire_bus(BUS_MANAGER
, &bus
);
5640 polkit_agent_open_maybe();
5642 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5644 return log_error_errno(r
, "Failed to expand names: %m");
5646 STRV_FOREACH(name
, names
) {
5647 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5649 q
= sd_bus_call_method(
5651 "org.freedesktop.systemd1",
5652 "/org/freedesktop/systemd1",
5653 "org.freedesktop.systemd1.Manager",
5659 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5668 static int print_variable(const char *s
) {
5670 _cleanup_free_
char *esc
= NULL
;
5672 sep
= strchr(s
, '=');
5674 log_error("Invalid environment block");
5678 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5682 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5686 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5687 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5688 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5693 r
= acquire_bus(BUS_MANAGER
, &bus
);
5697 pager_open(arg_no_pager
, false);
5699 r
= sd_bus_get_property(
5701 "org.freedesktop.systemd1",
5702 "/org/freedesktop/systemd1",
5703 "org.freedesktop.systemd1.Manager",
5709 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5711 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5713 return bus_log_parse_error(r
);
5715 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5716 r
= print_variable(text
);
5721 return bus_log_parse_error(r
);
5723 r
= sd_bus_message_exit_container(reply
);
5725 return bus_log_parse_error(r
);
5730 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5731 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5732 _cleanup_free_
char *cmdline_init
= NULL
;
5733 const char *root
, *init
;
5737 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5738 log_error("Cannot switch root remotely.");
5742 if (argc
< 2 || argc
> 3) {
5743 log_error("Wrong number of arguments.");
5752 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5753 "init", &cmdline_init
,
5756 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5758 init
= cmdline_init
;
5761 init
= empty_to_null(init
);
5763 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5765 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5766 root_init_path
= strjoina(root
, "/", init
);
5768 /* If the passed init is actually the same as the
5769 * systemd binary, then let's suppress it. */
5770 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5774 /* Instruct PID1 to exclude us from its killing spree applied during
5775 * the transition. Otherwise we would exit with a failure status even
5776 * though the switch to the new root has succeed. */
5777 argv_cmdline
[0] = '@';
5779 r
= acquire_bus(BUS_MANAGER
, &bus
);
5783 /* If we are slow to exit after the root switch, the new systemd instance
5784 * will send us a signal to terminate. Just ignore it and exit normally.
5785 * This way the unit does not end up as failed.
5787 r
= ignore_signals(SIGTERM
, -1);
5789 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5791 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5793 r
= sd_bus_call_method(
5795 "org.freedesktop.systemd1",
5796 "/org/freedesktop/systemd1",
5797 "org.freedesktop.systemd1.Manager",
5803 (void) default_signals(SIGTERM
, -1);
5805 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5811 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5812 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5813 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5821 r
= acquire_bus(BUS_MANAGER
, &bus
);
5825 polkit_agent_open_maybe();
5827 method
= streq(argv
[0], "set-environment")
5829 : "UnsetEnvironment";
5831 r
= sd_bus_message_new_method_call(
5834 "org.freedesktop.systemd1",
5835 "/org/freedesktop/systemd1",
5836 "org.freedesktop.systemd1.Manager",
5839 return bus_log_create_error(r
);
5841 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5843 return bus_log_create_error(r
);
5845 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5847 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5852 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5853 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5854 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5858 r
= acquire_bus(BUS_MANAGER
, &bus
);
5862 polkit_agent_open_maybe();
5864 r
= sd_bus_message_new_method_call(
5867 "org.freedesktop.systemd1",
5868 "/org/freedesktop/systemd1",
5869 "org.freedesktop.systemd1.Manager",
5872 return bus_log_create_error(r
);
5875 r
= sd_bus_message_append_strv(m
, environ
);
5879 r
= sd_bus_message_open_container(m
, 'a', "s");
5881 return bus_log_create_error(r
);
5883 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5885 if (!env_name_is_valid(*a
)) {
5886 log_error("Not a valid environment variable name: %s", *a
);
5890 STRV_FOREACH(b
, environ
) {
5893 eq
= startswith(*b
, *a
);
5894 if (eq
&& *eq
== '=') {
5896 r
= sd_bus_message_append(m
, "s", *b
);
5898 return bus_log_create_error(r
);
5905 r
= sd_bus_message_close_container(m
);
5908 return bus_log_create_error(r
);
5910 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5912 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5917 static int enable_sysv_units(const char *verb
, char **args
) {
5920 #if HAVE_SYSV_COMPAT
5921 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5924 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5926 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5929 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5932 if (!STR_IN_SET(verb
,
5938 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5945 const char *argv
[] = {
5946 ROOTLIBEXECDIR
"/systemd-sysv-install",
5953 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5954 bool found_native
= false, found_sysv
;
5963 if (!endswith(name
, ".service"))
5966 if (path_is_absolute(name
))
5969 j
= unit_file_exists(arg_scope
, &paths
, name
);
5970 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5971 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5972 found_native
= j
!= 0;
5974 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5975 * prefer the native unit */
5976 if (found_native
&& streq(verb
, "is-enabled"))
5979 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
5983 p
[strlen(p
) - strlen(".service")] = 0;
5984 found_sysv
= access(p
, F_OK
) >= 0;
5990 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
5992 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
5995 if (!isempty(arg_root
))
5996 argv
[c
++] = q
= strappend("--root=", arg_root
);
5999 argv
[c
++] = basename(p
);
6002 l
= strv_join((char**)argv
, " ");
6007 log_info("Executing: %s", l
);
6011 return log_error_errno(errno
, "Failed to fork: %m");
6012 else if (pid
== 0) {
6015 (void) reset_all_signal_handlers();
6016 (void) reset_signal_mask();
6018 execv(argv
[0], (char**) argv
);
6019 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
6020 _exit(EXIT_FAILURE
);
6023 j
= wait_for_terminate(pid
, &status
);
6025 return log_error_errno(j
, "Failed to wait for child: %m");
6027 if (status
.si_code
== CLD_EXITED
) {
6028 if (streq(verb
, "is-enabled")) {
6029 if (status
.si_status
== 0) {
6038 } else if (status
.si_status
!= 0)
6039 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
6041 log_error("Unexpected waitid() result.");
6048 /* Remove this entry, so that we don't try enabling it as native unit */
6051 assert(args
[f
] == name
);
6052 strv_remove(args
, name
);
6059 static int mangle_names(char **original_names
, char ***mangled_names
) {
6060 char **i
, **l
, **name
;
6063 l
= i
= new(char*, strv_length(original_names
) + 1);
6067 STRV_FOREACH(name
, original_names
) {
6069 /* When enabling units qualified path names are OK,
6070 * too, hence allow them explicitly. */
6072 if (is_path(*name
)) {
6079 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
6083 return log_error_errno(r
, "Failed to mangle unit name: %m");
6096 static int normalize_filenames(char **names
) {
6100 STRV_FOREACH(u
, names
)
6101 if (!path_is_absolute(*u
)) {
6102 char* normalized_path
;
6104 if (!isempty(arg_root
)) {
6105 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6109 if (!strchr(*u
,'/')) {
6110 log_error("Link argument does contain at least one directory separator: %s", *u
);
6114 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6118 free_and_replace(*u
, normalized_path
);
6124 static int normalize_names(char **names
, bool warn_if_path
) {
6126 bool was_path
= false;
6128 STRV_FOREACH(u
, names
) {
6134 r
= free_and_strdup(u
, basename(*u
));
6136 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6141 if (warn_if_path
&& was_path
)
6142 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6147 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6148 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6149 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6150 _cleanup_free_
char *path
= NULL
;
6151 static const struct bus_properties_map property_map
[] = {
6152 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
6153 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
6156 UnitStatusInfo info
= {};
6160 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6161 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6163 path
= unit_dbus_path_from_name(unit
);
6167 r
= acquire_bus(BUS_MANAGER
, &bus
);
6171 r
= sd_bus_call_method(
6173 "org.freedesktop.systemd1",
6175 "org.freedesktop.DBus.Properties",
6181 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6183 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
6185 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
6187 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6190 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6191 _cleanup_strv_free_
char **names
= NULL
;
6192 const char *verb
= argv
[0];
6193 UnitFileChange
*changes
= NULL
;
6194 unsigned n_changes
= 0;
6195 int carries_install_info
= -1;
6196 bool ignore_carries_install_info
= arg_quiet
;
6202 r
= mangle_names(strv_skip(argv
, 1), &names
);
6206 r
= enable_sysv_units(verb
, names
);
6210 /* If the operation was fully executed by the SysV compat, let's finish early */
6211 if (strv_isempty(names
)) {
6212 if (arg_no_reload
|| install_client_side())
6214 return daemon_reload(argc
, argv
, userdata
);
6217 if (streq(verb
, "disable")) {
6218 r
= normalize_names(names
, true);
6223 if (streq(verb
, "link")) {
6224 r
= normalize_filenames(names
);
6229 if (install_client_side()) {
6230 UnitFileFlags flags
;
6232 flags
= args_to_flags();
6233 if (streq(verb
, "enable")) {
6234 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6235 carries_install_info
= r
;
6236 } else if (streq(verb
, "disable"))
6237 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6238 else if (streq(verb
, "reenable")) {
6239 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6240 carries_install_info
= r
;
6241 } else if (streq(verb
, "link"))
6242 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6243 else if (streq(verb
, "preset")) {
6244 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6245 } else if (streq(verb
, "mask"))
6246 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6247 else if (streq(verb
, "unmask"))
6248 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6249 else if (streq(verb
, "revert"))
6250 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6252 assert_not_reached("Unknown verb");
6254 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6259 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6260 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6261 bool expect_carries_install_info
= false;
6262 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6266 if (STR_IN_SET(verb
, "mask", "unmask")) {
6268 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6270 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6274 STRV_FOREACH(name
, names
) {
6275 r
= unit_exists(&lp
, *name
);
6279 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6283 r
= acquire_bus(BUS_MANAGER
, &bus
);
6287 polkit_agent_open_maybe();
6289 if (streq(verb
, "enable")) {
6290 method
= "EnableUnitFiles";
6291 expect_carries_install_info
= true;
6292 } else if (streq(verb
, "disable")) {
6293 method
= "DisableUnitFiles";
6295 } else if (streq(verb
, "reenable")) {
6296 method
= "ReenableUnitFiles";
6297 expect_carries_install_info
= true;
6298 } else if (streq(verb
, "link"))
6299 method
= "LinkUnitFiles";
6300 else if (streq(verb
, "preset")) {
6302 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6303 method
= "PresetUnitFilesWithMode";
6304 send_preset_mode
= true;
6306 method
= "PresetUnitFiles";
6308 expect_carries_install_info
= true;
6309 ignore_carries_install_info
= true;
6310 } else if (streq(verb
, "mask"))
6311 method
= "MaskUnitFiles";
6312 else if (streq(verb
, "unmask")) {
6313 method
= "UnmaskUnitFiles";
6315 } else if (streq(verb
, "revert")) {
6316 method
= "RevertUnitFiles";
6317 send_runtime
= send_force
= false;
6319 assert_not_reached("Unknown verb");
6321 r
= sd_bus_message_new_method_call(
6324 "org.freedesktop.systemd1",
6325 "/org/freedesktop/systemd1",
6326 "org.freedesktop.systemd1.Manager",
6329 return bus_log_create_error(r
);
6331 r
= sd_bus_message_append_strv(m
, names
);
6333 return bus_log_create_error(r
);
6335 if (send_preset_mode
) {
6336 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6338 return bus_log_create_error(r
);
6342 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6344 return bus_log_create_error(r
);
6348 r
= sd_bus_message_append(m
, "b", arg_force
);
6350 return bus_log_create_error(r
);
6353 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6355 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6357 if (expect_carries_install_info
) {
6358 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6360 return bus_log_parse_error(r
);
6363 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6367 /* Try to reload if enabled */
6369 r
= daemon_reload(argc
, argv
, userdata
);
6374 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6375 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6376 "settings in the [Install] section, and DefaultInstance for template units).\n"
6377 "This means they are not meant to be enabled using systemctl.\n"
6378 "Possible reasons for having this kind of units are:\n"
6379 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6380 " .wants/ or .requires/ directory.\n"
6381 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6382 " a requirement dependency on it.\n"
6383 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6384 " D-Bus, udev, scripted systemctl call, ...).\n"
6385 "4) In case of template units, the unit is meant to be enabled with some\n"
6386 " instance name specified.");
6388 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6392 r
= acquire_bus(BUS_MANAGER
, &bus
);
6396 len
= strv_length(names
);
6398 char *new_args
[len
+ 2];
6400 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6401 for (i
= 0; i
< len
; i
++)
6402 new_args
[i
+ 1] = basename(names
[i
]);
6403 new_args
[i
+ 1] = NULL
;
6405 r
= start_unit(len
+ 1, new_args
, userdata
);
6410 unit_file_changes_free(changes
, n_changes
);
6415 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6416 _cleanup_strv_free_
char **names
= NULL
;
6417 _cleanup_free_
char *target
= NULL
;
6418 const char *verb
= argv
[0];
6419 UnitFileChange
*changes
= NULL
;
6420 unsigned n_changes
= 0;
6427 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6429 return log_error_errno(r
, "Failed to mangle unit name: %m");
6431 r
= mangle_names(strv_skip(argv
, 2), &names
);
6435 if (streq(verb
, "add-wants"))
6437 else if (streq(verb
, "add-requires"))
6438 dep
= UNIT_REQUIRES
;
6440 assert_not_reached("Unknown verb");
6442 if (install_client_side()) {
6443 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6444 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6449 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6450 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6453 r
= acquire_bus(BUS_MANAGER
, &bus
);
6457 polkit_agent_open_maybe();
6459 r
= sd_bus_message_new_method_call(
6462 "org.freedesktop.systemd1",
6463 "/org/freedesktop/systemd1",
6464 "org.freedesktop.systemd1.Manager",
6465 "AddDependencyUnitFiles");
6467 return bus_log_create_error(r
);
6469 r
= sd_bus_message_append_strv(m
, names
);
6471 return bus_log_create_error(r
);
6473 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6475 return bus_log_create_error(r
);
6477 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6479 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6481 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6485 if (arg_no_reload
) {
6490 r
= daemon_reload(argc
, argv
, userdata
);
6494 unit_file_changes_free(changes
, n_changes
);
6499 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6500 UnitFileChange
*changes
= NULL
;
6501 unsigned n_changes
= 0;
6504 if (install_client_side()) {
6505 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6506 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6511 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6512 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6515 r
= acquire_bus(BUS_MANAGER
, &bus
);
6519 polkit_agent_open_maybe();
6521 r
= sd_bus_call_method(
6523 "org.freedesktop.systemd1",
6524 "/org/freedesktop/systemd1",
6525 "org.freedesktop.systemd1.Manager",
6526 "PresetAllUnitFiles",
6530 unit_file_preset_mode_to_string(arg_preset_mode
),
6534 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6536 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6540 if (arg_no_reload
) {
6545 r
= daemon_reload(argc
, argv
, userdata
);
6549 unit_file_changes_free(changes
, n_changes
);
6554 static int show_installation_targets_client_side(const char *name
) {
6555 UnitFileChange
*changes
= NULL
;
6556 unsigned n_changes
= 0, i
;
6557 UnitFileFlags flags
;
6561 p
= STRV_MAKE(name
);
6562 flags
= UNIT_FILE_DRY_RUN
|
6563 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6565 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6567 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6569 for (i
= 0; i
< n_changes
; i
++)
6570 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6571 printf(" %s\n", changes
[i
].path
);
6576 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6577 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6578 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6582 r
= sd_bus_call_method(
6584 "org.freedesktop.systemd1",
6585 "/org/freedesktop/systemd1",
6586 "org.freedesktop.systemd1.Manager",
6590 "sb", name
, arg_runtime
);
6592 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6594 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6596 return bus_log_parse_error(r
);
6598 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6599 printf(" %s\n", link
);
6602 return bus_log_parse_error(r
);
6604 r
= sd_bus_message_exit_container(reply
);
6606 return bus_log_parse_error(r
);
6611 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6613 _cleanup_strv_free_
char **names
= NULL
;
6618 r
= mangle_names(strv_skip(argv
, 1), &names
);
6622 r
= enable_sysv_units(argv
[0], names
);
6628 if (install_client_side()) {
6629 STRV_FOREACH(name
, names
) {
6630 UnitFileState state
;
6632 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6634 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6638 UNIT_FILE_ENABLED_RUNTIME
,
6641 UNIT_FILE_GENERATED
))
6645 puts(unit_file_state_to_string(state
));
6647 r
= show_installation_targets_client_side(*name
);
6656 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6659 r
= acquire_bus(BUS_MANAGER
, &bus
);
6663 STRV_FOREACH(name
, names
) {
6664 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6667 r
= sd_bus_call_method(
6669 "org.freedesktop.systemd1",
6670 "/org/freedesktop/systemd1",
6671 "org.freedesktop.systemd1.Manager",
6677 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6679 r
= sd_bus_message_read(reply
, "s", &s
);
6681 return bus_log_parse_error(r
);
6683 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6689 r
= show_installation_targets(bus
, *name
);
6697 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6700 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6701 _cleanup_free_
char *state
= NULL
;
6705 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6708 return EXIT_FAILURE
;
6711 r
= acquire_bus(BUS_MANAGER
, &bus
);
6715 r
= sd_bus_get_property_string(
6717 "org.freedesktop.systemd1",
6718 "/org/freedesktop/systemd1",
6719 "org.freedesktop.systemd1.Manager",
6732 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6735 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6736 _cleanup_free_
char *t
= NULL
;
6740 assert(original_path
);
6743 r
= tempfn_random(new_path
, NULL
, &t
);
6745 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6747 r
= mkdir_parents(new_path
, 0755);
6749 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6751 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6756 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6759 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6767 static int get_file_to_edit(
6768 const LookupPaths
*paths
,
6772 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6777 path
= strjoin(paths
->persistent_config
, "/", name
);
6782 run
= strjoin(paths
->runtime_config
, "/", name
);
6788 if (access(path
, F_OK
) >= 0) {
6789 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6803 static int unit_file_create_new(
6804 const LookupPaths
*paths
,
6805 const char *unit_name
,
6807 char **ret_new_path
,
6808 char **ret_tmp_path
) {
6810 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6814 assert(ret_new_path
);
6815 assert(ret_tmp_path
);
6817 ending
= strjoina(unit_name
, suffix
);
6818 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6822 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6828 *ret_new_path
= tmp_new_path
;
6829 *ret_tmp_path
= tmp_tmp_path
;
6834 static int unit_file_create_copy(
6835 const LookupPaths
*paths
,
6836 const char *unit_name
,
6837 const char *fragment_path
,
6838 char **ret_new_path
,
6839 char **ret_tmp_path
) {
6841 char *tmp_new_path
, *tmp_tmp_path
;
6844 assert(fragment_path
);
6846 assert(ret_new_path
);
6847 assert(ret_tmp_path
);
6849 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6853 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6856 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6861 if (response
!= 'y') {
6862 log_warning("%s ignored", unit_name
);
6864 return -EKEYREJECTED
;
6868 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6874 *ret_new_path
= tmp_new_path
;
6875 *ret_tmp_path
= tmp_tmp_path
;
6880 static int run_editor(char **paths
) {
6888 return log_error_errno(errno
, "Failed to fork: %m");
6892 char *editor
, **editor_args
= NULL
;
6893 char **tmp_path
, **original_path
, *p
;
6894 unsigned n_editor_args
= 0, i
= 1;
6897 (void) reset_all_signal_handlers();
6898 (void) reset_signal_mask();
6900 argc
= strv_length(paths
)/2 + 1;
6902 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6903 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6904 * we try to execute well known editors
6906 editor
= getenv("SYSTEMD_EDITOR");
6908 editor
= getenv("EDITOR");
6910 editor
= getenv("VISUAL");
6912 if (!isempty(editor
)) {
6913 editor_args
= strv_split(editor
, WHITESPACE
);
6916 _exit(EXIT_FAILURE
);
6918 n_editor_args
= strv_length(editor_args
);
6919 argc
+= n_editor_args
- 1;
6921 args
= newa(const char*, argc
+ 1);
6923 if (n_editor_args
> 0) {
6924 args
[0] = editor_args
[0];
6925 for (; i
< n_editor_args
; i
++)
6926 args
[i
] = editor_args
[i
];
6929 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6930 args
[i
] = *tmp_path
;
6935 if (n_editor_args
> 0)
6936 execvp(args
[0], (char* const*) args
);
6938 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6940 execvp(p
, (char* const*) args
);
6941 /* We do not fail if the editor doesn't exist
6942 * because we want to try each one of them before
6945 if (errno
!= ENOENT
) {
6946 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6947 _exit(EXIT_FAILURE
);
6951 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6952 _exit(EXIT_FAILURE
);
6955 r
= wait_for_terminate_and_warn("editor", pid
, true);
6957 return log_error_errno(r
, "Failed to wait for child: %m");
6962 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6963 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6970 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6974 STRV_FOREACH(name
, names
) {
6975 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
6976 const char *unit_name
;
6978 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
6986 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
6987 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
6988 arg_scope
== UNIT_FILE_USER
? " --user" : "",
6993 /* Create a new unit from scratch */
6995 r
= unit_file_create_new(&lp
, unit_name
,
6996 arg_full
? NULL
: ".d/override.conf",
6997 &new_path
, &tmp_path
);
7001 unit_name
= basename(path
);
7002 /* We follow unit aliases, but we need to propagate the instance */
7003 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
7004 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
7005 _cleanup_free_
char *instance
= NULL
;
7007 r
= unit_name_to_instance(*name
, &instance
);
7011 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
7015 unit_name
= tmp_name
;
7019 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
7021 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
7026 r
= strv_push_pair(paths
, new_path
, tmp_path
);
7029 new_path
= tmp_path
= NULL
;
7035 static int edit(int argc
, char *argv
[], void *userdata
) {
7036 _cleanup_strv_free_
char **names
= NULL
;
7037 _cleanup_strv_free_
char **paths
= NULL
;
7038 char **original
, **tmp
;
7043 log_error("Cannot edit units if not on a tty.");
7047 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
7048 log_error("Cannot edit units remotely.");
7052 r
= acquire_bus(BUS_MANAGER
, &bus
);
7056 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
7058 return log_error_errno(r
, "Failed to expand names: %m");
7060 r
= find_paths_to_edit(bus
, names
, &paths
);
7064 if (strv_isempty(paths
))
7067 r
= run_editor(paths
);
7071 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7072 /* If the temporary file is empty we ignore it. It's
7073 * useful if the user wants to cancel its modification
7075 if (null_or_empty_path(*tmp
)) {
7076 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7080 r
= rename(*tmp
, *original
);
7082 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7089 if (!arg_no_reload
&& !install_client_side())
7090 r
= daemon_reload(argc
, argv
, userdata
);
7093 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7094 (void) unlink(*tmp
);
7096 /* Removing empty dropin dirs */
7098 _cleanup_free_
char *dir
;
7100 dir
= dirname_malloc(*original
);
7104 /* no need to check if the dir is empty, rmdir
7105 * does nothing if it is not the case.
7114 static void systemctl_help(void) {
7116 pager_open(arg_no_pager
, false);
7118 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7119 "Query or send control commands to the systemd manager.\n\n"
7120 " -h --help Show this help\n"
7121 " --version Show package version\n"
7122 " --system Connect to system manager\n"
7123 " --user Connect to user service manager\n"
7124 " -H --host=[USER@]HOST\n"
7125 " Operate on remote host\n"
7126 " -M --machine=CONTAINER\n"
7127 " Operate on local container\n"
7128 " -t --type=TYPE List units of a particular type\n"
7129 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7130 " -p --property=NAME Show only properties by this name\n"
7131 " -a --all Show all properties/all units currently in memory,\n"
7132 " including dead/empty ones. To list all units installed on\n"
7133 " the system, use the 'list-unit-files' command instead.\n"
7134 " --failed Same as --state=failed\n"
7135 " -l --full Don't ellipsize unit names on output\n"
7136 " -r --recursive Show unit list of host and local containers\n"
7137 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7138 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7139 " queueing a new job\n"
7140 " --show-types When showing sockets, explicitly show their type\n"
7141 " --value When showing properties, only print the value\n"
7142 " -i --ignore-inhibitors\n"
7143 " When shutting down or sleeping, ignore inhibitors\n"
7144 " --kill-who=WHO Who to send signal to\n"
7145 " -s --signal=SIGNAL Which signal to send\n"
7146 " --now Start or stop unit in addition to enabling or disabling it\n"
7147 " -q --quiet Suppress output\n"
7148 " --wait For (re)start, wait until service stopped again\n"
7149 " --no-block Do not wait until operation finished\n"
7150 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7151 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7152 " --no-legend Do not print a legend (column headers and hints)\n"
7153 " --no-pager Do not pipe output into a pager\n"
7154 " --no-ask-password\n"
7155 " Do not ask for system passwords\n"
7156 " --global Enable/disable/mask unit files globally\n"
7157 " --runtime Enable/disable/mask unit files temporarily until next\n"
7159 " -f --force When enabling unit files, override existing symlinks\n"
7160 " When shutting down, execute action immediately\n"
7161 " --preset-mode= Apply only enable, only disable, or all presets\n"
7162 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7164 " -n --lines=INTEGER Number of journal entries to show\n"
7165 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7166 " short-iso, short-iso-precise, short-full,\n"
7167 " short-monotonic, short-unix,\n"
7168 " verbose, export, json, json-pretty, json-sse, cat)\n"
7169 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7170 " --plain Print unit dependencies as a list instead of a tree\n\n"
7172 " list-units [PATTERN...] List units currently in memory\n"
7173 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
7175 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
7177 " start NAME... Start (activate) one or more units\n"
7178 " stop NAME... Stop (deactivate) one or more units\n"
7179 " reload NAME... Reload one or more units\n"
7180 " restart NAME... Start or restart one or more units\n"
7181 " try-restart NAME... Restart one or more units if active\n"
7182 " reload-or-restart NAME... Reload one or more units if possible,\n"
7183 " otherwise start or restart\n"
7184 " try-reload-or-restart NAME... If active, reload one or more units,\n"
7185 " if supported, otherwise restart\n"
7186 " isolate NAME Start one unit and stop all others\n"
7187 " kill NAME... Send signal to processes of a unit\n"
7188 " is-active PATTERN... Check whether units are active\n"
7189 " is-failed PATTERN... Check whether units are failed\n"
7190 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7191 " show [PATTERN...|JOB...] Show properties of one or more\n"
7192 " units/jobs or the manager\n"
7193 " cat PATTERN... Show files and drop-ins of one or more units\n"
7194 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
7195 " help PATTERN...|PID... Show manual for one or more units\n"
7196 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7198 " list-dependencies [NAME] Recursively show units which are required\n"
7199 " or wanted by this unit or by which this\n"
7200 " unit is required or wanted\n\n"
7201 "Unit File Commands:\n"
7202 " list-unit-files [PATTERN...] List installed unit files\n"
7203 " enable [NAME...|PATH...] Enable one or more unit files\n"
7204 " disable NAME... Disable one or more unit files\n"
7205 " reenable NAME... Reenable one or more unit files\n"
7206 " preset NAME... Enable/disable one or more unit files\n"
7207 " based on preset configuration\n"
7208 " preset-all Enable/disable all unit files based on\n"
7209 " preset configuration\n"
7210 " is-enabled NAME... Check whether unit files are enabled\n"
7211 " mask NAME... Mask one or more units\n"
7212 " unmask NAME... Unmask one or more units\n"
7213 " link PATH... Link one or more units files into\n"
7214 " the search path\n"
7215 " revert NAME... Revert one or more unit files to vendor\n"
7217 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
7218 " on specified one or more units\n"
7219 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
7220 " on specified one or more units\n"
7221 " edit NAME... Edit one or more unit files\n"
7222 " get-default Get the name of the default target\n"
7223 " set-default NAME Set the default target\n\n"
7224 "Machine Commands:\n"
7225 " list-machines [PATTERN...] List local containers and host\n\n"
7227 " list-jobs [PATTERN...] List jobs\n"
7228 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7229 "Environment Commands:\n"
7230 " show-environment Dump environment\n"
7231 " set-environment NAME=VALUE... Set one or more environment variables\n"
7232 " unset-environment NAME... Unset one or more environment variables\n"
7233 " import-environment [NAME...] Import all or some environment variables\n\n"
7234 "Manager Lifecycle Commands:\n"
7235 " daemon-reload Reload systemd manager configuration\n"
7236 " daemon-reexec Reexecute systemd manager\n\n"
7237 "System Commands:\n"
7238 " is-system-running Check whether system is fully running\n"
7239 " default Enter system default mode\n"
7240 " rescue Enter system rescue mode\n"
7241 " emergency Enter system emergency mode\n"
7242 " halt Shut down and halt the system\n"
7243 " poweroff Shut down and power-off the system\n"
7244 " reboot [ARG] Shut down and reboot the system\n"
7245 " kexec Shut down and reboot the system with kexec\n"
7246 " exit [EXIT_CODE] Request user instance or container exit\n"
7247 " switch-root ROOT [INIT] Change to a different root file system\n"
7248 " suspend Suspend the system\n"
7249 " hibernate Hibernate the system\n"
7250 " hybrid-sleep Hibernate and suspend the system\n",
7251 program_invocation_short_name
);
7254 static void halt_help(void) {
7255 printf("%s [OPTIONS...]%s\n\n"
7256 "%s the system.\n\n"
7257 " --help Show this help\n"
7258 " --halt Halt the machine\n"
7259 " -p --poweroff Switch off the machine\n"
7260 " --reboot Reboot the machine\n"
7261 " -f --force Force immediate halt/power-off/reboot\n"
7262 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7263 " -d --no-wtmp Don't write wtmp record\n"
7264 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7265 program_invocation_short_name
,
7266 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7267 arg_action
== ACTION_REBOOT
? "Reboot" :
7268 arg_action
== ACTION_POWEROFF
? "Power off" :
7272 static void shutdown_help(void) {
7273 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7274 "Shut down the system.\n\n"
7275 " --help Show this help\n"
7276 " -H --halt Halt the machine\n"
7277 " -P --poweroff Power-off the machine\n"
7278 " -r --reboot Reboot the machine\n"
7279 " -h Equivalent to --poweroff, overridden by --halt\n"
7280 " -k Don't halt/power-off/reboot, just send warnings\n"
7281 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7282 " -c Cancel a pending shutdown\n",
7283 program_invocation_short_name
);
7286 static void telinit_help(void) {
7287 printf("%s [OPTIONS...] {COMMAND}\n\n"
7288 "Send control commands to the init daemon.\n\n"
7289 " --help Show this help\n"
7290 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7292 " 0 Power-off the machine\n"
7293 " 6 Reboot the machine\n"
7294 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7295 " 1, s, S Enter rescue mode\n"
7296 " q, Q Reload init daemon configuration\n"
7297 " u, U Reexecute init daemon\n",
7298 program_invocation_short_name
);
7301 static void runlevel_help(void) {
7302 printf("%s [OPTIONS...]\n\n"
7303 "Prints the previous and current runlevel of the init system.\n\n"
7304 " --help Show this help\n",
7305 program_invocation_short_name
);
7308 static void help_types(void) {
7312 puts("Available unit types:");
7313 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7314 puts(unit_type_to_string(i
));
7317 static void help_states(void) {
7321 puts("Available unit load states:");
7322 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7323 puts(unit_load_state_to_string(i
));
7326 puts("\nAvailable unit active states:");
7327 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7328 puts(unit_active_state_to_string(i
));
7331 puts("\nAvailable automount unit substates:");
7332 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7333 puts(automount_state_to_string(i
));
7336 puts("\nAvailable device unit substates:");
7337 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7338 puts(device_state_to_string(i
));
7341 puts("\nAvailable mount unit substates:");
7342 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7343 puts(mount_state_to_string(i
));
7346 puts("\nAvailable path unit substates:");
7347 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7348 puts(path_state_to_string(i
));
7351 puts("\nAvailable scope unit substates:");
7352 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7353 puts(scope_state_to_string(i
));
7356 puts("\nAvailable service unit substates:");
7357 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7358 puts(service_state_to_string(i
));
7361 puts("\nAvailable slice unit substates:");
7362 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7363 puts(slice_state_to_string(i
));
7366 puts("\nAvailable socket unit substates:");
7367 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7368 puts(socket_state_to_string(i
));
7371 puts("\nAvailable swap unit substates:");
7372 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7373 puts(swap_state_to_string(i
));
7376 puts("\nAvailable target unit substates:");
7377 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7378 puts(target_state_to_string(i
));
7381 puts("\nAvailable timer unit substates:");
7382 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7383 puts(timer_state_to_string(i
));
7386 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7395 ARG_IGNORE_DEPENDENCIES
,
7408 ARG_NO_ASK_PASSWORD
,
7422 static const struct option options
[] = {
7423 { "help", no_argument
, NULL
, 'h' },
7424 { "version", no_argument
, NULL
, ARG_VERSION
},
7425 { "type", required_argument
, NULL
, 't' },
7426 { "property", required_argument
, NULL
, 'p' },
7427 { "all", no_argument
, NULL
, 'a' },
7428 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7429 { "after", no_argument
, NULL
, ARG_AFTER
},
7430 { "before", no_argument
, NULL
, ARG_BEFORE
},
7431 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7432 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7433 { "full", no_argument
, NULL
, 'l' },
7434 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7435 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7436 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7437 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7438 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7439 { "value", no_argument
, NULL
, ARG_VALUE
},
7440 { "user", no_argument
, NULL
, ARG_USER
},
7441 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7442 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7443 { "wait", no_argument
, NULL
, ARG_WAIT
},
7444 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7445 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7446 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7447 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7448 { "quiet", no_argument
, NULL
, 'q' },
7449 { "root", required_argument
, NULL
, ARG_ROOT
},
7450 { "force", no_argument
, NULL
, ARG_FORCE
},
7451 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7452 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7453 { "signal", required_argument
, NULL
, 's' },
7454 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7455 { "host", required_argument
, NULL
, 'H' },
7456 { "machine", required_argument
, NULL
, 'M' },
7457 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7458 { "lines", required_argument
, NULL
, 'n' },
7459 { "output", required_argument
, NULL
, 'o' },
7460 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7461 { "state", required_argument
, NULL
, ARG_STATE
},
7462 { "recursive", no_argument
, NULL
, 'r' },
7463 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7464 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7465 { "now", no_argument
, NULL
, ARG_NOW
},
7466 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7476 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7477 arg_ask_password
= true;
7479 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7491 if (isempty(optarg
)) {
7492 log_error("--type= requires arguments.");
7496 for (p
= optarg
;;) {
7497 _cleanup_free_
char *type
= NULL
;
7499 r
= extract_first_word(&p
, &type
, ",", 0);
7501 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7505 if (streq(type
, "help")) {
7510 if (unit_type_from_string(type
) >= 0) {
7511 if (strv_push(&arg_types
, type
) < 0)
7517 /* It's much nicer to use --state= for
7518 * load states, but let's support this
7519 * in --types= too for compatibility
7520 * with old versions */
7521 if (unit_load_state_from_string(type
) >= 0) {
7522 if (strv_push(&arg_states
, type
) < 0)
7528 log_error("Unknown unit type or load state '%s'.", type
);
7529 log_info("Use -t help to see a list of allowed values.");
7537 /* Make sure that if the empty property list
7538 was specified, we won't show any properties. */
7539 if (isempty(optarg
) && !arg_properties
) {
7540 arg_properties
= new0(char*, 1);
7541 if (!arg_properties
)
7544 for (p
= optarg
;;) {
7545 _cleanup_free_
char *prop
= NULL
;
7547 r
= extract_first_word(&p
, &prop
, ",", 0);
7549 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7553 if (strv_push(&arg_properties
, prop
) < 0)
7559 /* If the user asked for a particular
7560 * property, show it to him, even if it is
7572 arg_dependency
= DEPENDENCY_REVERSE
;
7576 arg_dependency
= DEPENDENCY_AFTER
;
7577 arg_jobs_after
= true;
7581 arg_dependency
= DEPENDENCY_BEFORE
;
7582 arg_jobs_before
= true;
7585 case ARG_SHOW_TYPES
:
7586 arg_show_types
= true;
7594 arg_job_mode
= optarg
;
7598 arg_job_mode
= "fail";
7601 case ARG_IRREVERSIBLE
:
7602 arg_job_mode
= "replace-irreversibly";
7605 case ARG_IGNORE_DEPENDENCIES
:
7606 arg_job_mode
= "ignore-dependencies";
7610 arg_scope
= UNIT_FILE_USER
;
7614 arg_scope
= UNIT_FILE_SYSTEM
;
7618 arg_scope
= UNIT_FILE_GLOBAL
;
7626 arg_no_block
= true;
7630 arg_no_legend
= true;
7634 arg_no_pager
= true;
7642 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7652 if (strv_extend(&arg_states
, "failed") < 0)
7670 arg_no_reload
= true;
7674 arg_kill_who
= optarg
;
7678 arg_signal
= signal_from_string_try_harder(optarg
);
7679 if (arg_signal
< 0) {
7680 log_error("Failed to parse signal string %s.", optarg
);
7685 case ARG_NO_ASK_PASSWORD
:
7686 arg_ask_password
= false;
7690 arg_transport
= BUS_TRANSPORT_REMOTE
;
7695 arg_transport
= BUS_TRANSPORT_MACHINE
;
7704 if (safe_atou(optarg
, &arg_lines
) < 0) {
7705 log_error("Failed to parse lines '%s'", optarg
);
7711 arg_output
= output_mode_from_string(optarg
);
7712 if (arg_output
< 0) {
7713 log_error("Unknown output '%s'.", optarg
);
7719 arg_ignore_inhibitors
= true;
7726 case ARG_FIRMWARE_SETUP
:
7727 arg_firmware_setup
= true;
7731 if (isempty(optarg
)) {
7732 log_error("--state= requires arguments.");
7736 for (p
= optarg
;;) {
7737 _cleanup_free_
char *s
= NULL
;
7739 r
= extract_first_word(&p
, &s
, ",", 0);
7741 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7745 if (streq(s
, "help")) {
7750 if (strv_push(&arg_states
, s
) < 0)
7759 if (geteuid() != 0) {
7760 log_error("--recursive requires root privileges.");
7764 arg_recursive
= true;
7767 case ARG_PRESET_MODE
:
7769 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7770 if (arg_preset_mode
< 0) {
7771 log_error("Failed to parse preset mode: %s.", optarg
);
7782 if (strv_extend(&arg_wall
, optarg
) < 0)
7790 assert_not_reached("Unhandled option");
7793 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7794 log_error("Cannot access user instance remotely.");
7798 if (arg_wait
&& arg_no_block
) {
7799 log_error("--wait may not be combined with --no-block.");
7806 static int halt_parse_argv(int argc
, char *argv
[]) {
7815 static const struct option options
[] = {
7816 { "help", no_argument
, NULL
, ARG_HELP
},
7817 { "halt", no_argument
, NULL
, ARG_HALT
},
7818 { "poweroff", no_argument
, NULL
, 'p' },
7819 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7820 { "force", no_argument
, NULL
, 'f' },
7821 { "wtmp-only", no_argument
, NULL
, 'w' },
7822 { "no-wtmp", no_argument
, NULL
, 'd' },
7823 { "no-sync", no_argument
, NULL
, 'n' },
7824 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7833 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7834 if (IN_SET(runlevel
, '0', '6'))
7837 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7845 arg_action
= ACTION_HALT
;
7849 if (arg_action
!= ACTION_REBOOT
)
7850 arg_action
= ACTION_POWEROFF
;
7854 arg_action
= ACTION_REBOOT
;
7879 /* Compatibility nops */
7886 assert_not_reached("Unhandled option");
7889 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7890 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7893 } else if (optind
< argc
) {
7894 log_error("Too many arguments.");
7901 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7905 if (streq(t
, "now"))
7907 else if (!strchr(t
, ':')) {
7910 if (safe_atou64(t
, &u
) < 0)
7913 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7922 hour
= strtol(t
, &e
, 10);
7923 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7926 minute
= strtol(e
+1, &e
, 10);
7927 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7930 n
= now(CLOCK_REALTIME
);
7931 s
= (time_t) (n
/ USEC_PER_SEC
);
7933 assert_se(localtime_r(&s
, &tm
));
7935 tm
.tm_hour
= (int) hour
;
7936 tm
.tm_min
= (int) minute
;
7939 assert_se(s
= mktime(&tm
));
7941 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7944 *_u
+= USEC_PER_DAY
;
7950 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7957 static const struct option options
[] = {
7958 { "help", no_argument
, NULL
, ARG_HELP
},
7959 { "halt", no_argument
, NULL
, 'H' },
7960 { "poweroff", no_argument
, NULL
, 'P' },
7961 { "reboot", no_argument
, NULL
, 'r' },
7962 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7963 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7973 while ((c
= getopt_long(argc
, argv
, "HPrhkKtafFc", options
, NULL
)) >= 0)
7981 arg_action
= ACTION_HALT
;
7985 arg_action
= ACTION_POWEROFF
;
7990 arg_action
= ACTION_KEXEC
;
7992 arg_action
= ACTION_REBOOT
;
7996 arg_action
= ACTION_KEXEC
;
8000 if (arg_action
!= ACTION_HALT
)
8001 arg_action
= ACTION_POWEROFF
;
8016 /* Compatibility nops */
8020 arg_action
= ACTION_CANCEL_SHUTDOWN
;
8027 assert_not_reached("Unhandled option");
8030 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
8031 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
8033 log_error("Failed to parse time specification: %s", argv
[optind
]);
8037 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
8039 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
8040 /* No time argument for shutdown cancel */
8041 wall
= argv
+ optind
;
8042 else if (argc
> optind
+ 1)
8043 /* We skip the time argument */
8044 wall
= argv
+ optind
+ 1;
8047 arg_wall
= strv_copy(wall
);
8057 static int telinit_parse_argv(int argc
, char *argv
[]) {
8064 static const struct option options
[] = {
8065 { "help", no_argument
, NULL
, ARG_HELP
},
8066 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8070 static const struct {
8074 { '0', ACTION_POWEROFF
},
8075 { '6', ACTION_REBOOT
},
8076 { '1', ACTION_RESCUE
},
8077 { '2', ACTION_RUNLEVEL2
},
8078 { '3', ACTION_RUNLEVEL3
},
8079 { '4', ACTION_RUNLEVEL4
},
8080 { '5', ACTION_RUNLEVEL5
},
8081 { 's', ACTION_RESCUE
},
8082 { 'S', ACTION_RESCUE
},
8083 { 'q', ACTION_RELOAD
},
8084 { 'Q', ACTION_RELOAD
},
8085 { 'u', ACTION_REEXEC
},
8086 { 'U', ACTION_REEXEC
}
8095 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8110 assert_not_reached("Unhandled option");
8113 if (optind
>= argc
) {
8114 log_error("%s: required argument missing.", program_invocation_short_name
);
8118 if (optind
+ 1 < argc
) {
8119 log_error("Too many arguments.");
8123 if (strlen(argv
[optind
]) != 1) {
8124 log_error("Expected single character argument.");
8128 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8129 if (table
[i
].from
== argv
[optind
][0])
8132 if (i
>= ELEMENTSOF(table
)) {
8133 log_error("Unknown command '%s'.", argv
[optind
]);
8137 arg_action
= table
[i
].to
;
8144 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8150 static const struct option options
[] = {
8151 { "help", no_argument
, NULL
, ARG_HELP
},
8160 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8171 assert_not_reached("Unhandled option");
8174 if (optind
< argc
) {
8175 log_error("Too many arguments.");
8182 static int parse_argv(int argc
, char *argv
[]) {
8186 if (program_invocation_short_name
) {
8188 if (strstr(program_invocation_short_name
, "halt")) {
8189 arg_action
= ACTION_HALT
;
8190 return halt_parse_argv(argc
, argv
);
8191 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8192 arg_action
= ACTION_POWEROFF
;
8193 return halt_parse_argv(argc
, argv
);
8194 } else if (strstr(program_invocation_short_name
, "reboot")) {
8196 arg_action
= ACTION_KEXEC
;
8198 arg_action
= ACTION_REBOOT
;
8199 return halt_parse_argv(argc
, argv
);
8200 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8201 arg_action
= ACTION_POWEROFF
;
8202 return shutdown_parse_argv(argc
, argv
);
8203 } else if (strstr(program_invocation_short_name
, "init")) {
8205 if (sd_booted() > 0) {
8206 arg_action
= _ACTION_INVALID
;
8207 return telinit_parse_argv(argc
, argv
);
8209 /* Hmm, so some other init system is
8210 * running, we need to forward this
8211 * request to it. For now we simply
8212 * guess that it is Upstart. */
8214 execv(TELINIT
, argv
);
8216 log_error("Couldn't find an alternative telinit implementation to spawn.");
8220 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8221 arg_action
= ACTION_RUNLEVEL
;
8222 return runlevel_parse_argv(argc
, argv
);
8226 arg_action
= ACTION_SYSTEMCTL
;
8227 return systemctl_parse_argv(argc
, argv
);
8230 #if HAVE_SYSV_COMPAT
8231 _pure_
static int action_to_runlevel(void) {
8233 static const char table
[_ACTION_MAX
] = {
8234 [ACTION_HALT
] = '0',
8235 [ACTION_POWEROFF
] = '0',
8236 [ACTION_REBOOT
] = '6',
8237 [ACTION_RUNLEVEL2
] = '2',
8238 [ACTION_RUNLEVEL3
] = '3',
8239 [ACTION_RUNLEVEL4
] = '4',
8240 [ACTION_RUNLEVEL5
] = '5',
8241 [ACTION_RESCUE
] = '1'
8244 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8246 return table
[arg_action
];
8250 static int talk_initctl(void) {
8251 #if HAVE_SYSV_COMPAT
8252 struct init_request request
= {
8253 .magic
= INIT_MAGIC
,
8255 .cmd
= INIT_CMD_RUNLVL
8258 _cleanup_close_
int fd
= -1;
8262 rl
= action_to_runlevel();
8266 request
.runlevel
= rl
;
8268 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
8270 if (errno
== ENOENT
)
8273 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8276 r
= loop_write(fd
, &request
, sizeof(request
), false);
8278 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8286 static int systemctl_main(int argc
, char *argv
[]) {
8288 static const Verb verbs
[] = {
8289 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
8290 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8291 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
8292 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
8293 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
8294 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
8295 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
8296 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
8297 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8298 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8299 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8300 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8301 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8302 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8303 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8304 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8305 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8306 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
8307 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8308 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
8309 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
8310 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
8311 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8312 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8313 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
8314 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8315 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
8316 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8317 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8318 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8319 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8320 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
8321 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8322 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8323 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
8324 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8325 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8326 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
8327 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8328 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8329 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8330 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8331 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
8332 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8333 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8334 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
8335 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
8336 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8337 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8338 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8339 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8340 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8341 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8342 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8343 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8344 { "link", 2, VERB_ANY
, 0, enable_unit
},
8345 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8346 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
8347 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
8348 { "set-default", 2, 2, 0, set_default
},
8349 { "get-default", VERB_ANY
, 1, 0, get_default
},
8350 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
8351 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8352 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8353 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8354 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
8358 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8361 static int reload_with_fallback(void) {
8363 /* First, try systemd via D-Bus. */
8364 if (daemon_reload(0, NULL
, NULL
) >= 0)
8367 /* Nothing else worked, so let's try signals */
8368 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8370 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8371 return log_error_errno(errno
, "kill() failed: %m");
8376 static int start_with_fallback(void) {
8378 /* First, try systemd via D-Bus. */
8379 if (start_unit(0, NULL
, NULL
) >= 0)
8382 /* Nothing else worked, so let's try /dev/initctl */
8383 if (talk_initctl() > 0)
8386 log_error("Failed to talk to init daemon.");
8390 static int halt_now(enum action a
) {
8393 /* The kernel will automaticall flush ATA disks and suchlike
8394 * on reboot(), but the file systems need to be synce'd
8395 * explicitly in advance. */
8399 /* Make sure C-A-D is handled by the kernel from this point
8401 (void) reboot(RB_ENABLE_CAD
);
8407 log_info("Halting.");
8408 (void) reboot(RB_HALT_SYSTEM
);
8411 case ACTION_POWEROFF
:
8413 log_info("Powering off.");
8414 (void) reboot(RB_POWER_OFF
);
8418 case ACTION_REBOOT
: {
8419 _cleanup_free_
char *param
= NULL
;
8421 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8422 if (r
< 0 && r
!= -ENOENT
)
8423 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8425 if (!isempty(param
)) {
8427 log_info("Rebooting with argument '%s'.", param
);
8428 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
8429 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8433 log_info("Rebooting.");
8434 (void) reboot(RB_AUTOBOOT
);
8439 assert_not_reached("Unknown action.");
8443 static int logind_schedule_shutdown(void) {
8446 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8447 char date
[FORMAT_TIMESTAMP_MAX
];
8452 r
= acquire_bus(BUS_FULL
, &bus
);
8456 switch (arg_action
) {
8460 case ACTION_POWEROFF
:
8461 action
= "poweroff";
8476 action
= strjoina("dry-", action
);
8478 (void) logind_set_wall_message();
8480 r
= sd_bus_call_method(
8482 "org.freedesktop.login1",
8483 "/org/freedesktop/login1",
8484 "org.freedesktop.login1.Manager",
8492 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8495 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8498 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8503 static int halt_main(void) {
8506 r
= logind_check_inhibitors(arg_action
);
8511 return logind_schedule_shutdown();
8513 if (geteuid() != 0) {
8514 if (arg_dry
|| arg_force
> 0) {
8515 log_error("Must be root.");
8519 /* Try logind if we are a normal user and no special
8520 * mode applies. Maybe PolicyKit allows us to shutdown
8522 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8523 r
= logind_reboot(arg_action
);
8526 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8527 /* requested operation is not
8528 * supported on the local system or
8529 * already in progress */
8531 /* on all other errors, try low-level operation */
8535 if (!arg_dry
&& !arg_force
)
8536 return start_with_fallback();
8538 assert(geteuid() == 0);
8541 if (sd_booted() > 0)
8542 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8544 r
= utmp_put_shutdown();
8546 log_warning_errno(r
, "Failed to write utmp record: %m");
8553 r
= halt_now(arg_action
);
8554 return log_error_errno(r
, "Failed to reboot: %m");
8557 static int runlevel_main(void) {
8558 int r
, runlevel
, previous
;
8560 r
= utmp_get_runlevel(&runlevel
, &previous
);
8567 previous
<= 0 ? 'N' : previous
,
8568 runlevel
<= 0 ? 'N' : runlevel
);
8573 static int logind_cancel_shutdown(void) {
8575 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8579 r
= acquire_bus(BUS_FULL
, &bus
);
8583 (void) logind_set_wall_message();
8585 r
= sd_bus_call_method(
8587 "org.freedesktop.login1",
8588 "/org/freedesktop/login1",
8589 "org.freedesktop.login1.Manager",
8590 "CancelScheduledShutdown",
8594 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8598 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8603 int main(int argc
, char*argv
[]) {
8606 argv_cmdline
= argv
[0];
8608 setlocale(LC_ALL
, "");
8609 log_parse_environment();
8613 /* Explicitly not on_tty() to avoid setting cached value.
8614 * This becomes relevant for piping output which might be
8616 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8618 r
= parse_argv(argc
, argv
);
8622 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8625 log_info("Running in chroot, ignoring request.");
8630 /* systemctl_main() will print an error message for the bus
8631 * connection, but only if it needs to */
8633 switch (arg_action
) {
8635 case ACTION_SYSTEMCTL
:
8636 r
= systemctl_main(argc
, argv
);
8639 /* Legacy command aliases set arg_action. They provide some fallbacks,
8640 * e.g. to tell sysvinit to reboot after you have installed systemd
8644 case ACTION_POWEROFF
:
8650 case ACTION_RUNLEVEL2
:
8651 case ACTION_RUNLEVEL3
:
8652 case ACTION_RUNLEVEL4
:
8653 case ACTION_RUNLEVEL5
:
8655 r
= start_with_fallback();
8660 r
= reload_with_fallback();
8663 case ACTION_CANCEL_SHUTDOWN
:
8664 r
= logind_cancel_shutdown();
8667 case ACTION_RUNLEVEL
:
8668 r
= runlevel_main();
8672 case ACTION_SUSPEND
:
8673 case ACTION_HIBERNATE
:
8674 case ACTION_HYBRID_SLEEP
:
8675 case ACTION_EMERGENCY
:
8676 case ACTION_DEFAULT
:
8677 /* systemctl verbs with no equivalent in the legacy commands.
8678 * These cannot appear in arg_action. Fall through. */
8680 case _ACTION_INVALID
:
8682 assert_not_reached("Unknown action");
8689 ask_password_agent_close();
8690 polkit_agent_close();
8692 strv_free(arg_types
);
8693 strv_free(arg_states
);
8694 strv_free(arg_properties
);
8696 strv_free(arg_wall
);
8699 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8700 return r
< 0 ? EXIT_FAILURE
: r
;