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"
58 #include "hexdecoct.h"
63 #include "locale-util.h"
65 #include "logs-show.h"
69 #include "parse-util.h"
70 #include "path-lookup.h"
71 #include "path-util.h"
72 #include "process-util.h"
73 #include "rlimit-util.h"
76 #include "signal-util.h"
77 #include "socket-util.h"
78 #include "spawn-ask-password-agent.h"
79 #include "spawn-polkit-agent.h"
81 #include "stat-util.h"
83 #include "terminal-util.h"
84 #include "unit-name.h"
85 #include "user-util.h"
87 #include "utmp-wtmp.h"
91 /* The init script exit status codes
92 0 program is running or service is OK
93 1 program is dead and /var/run pid file exists
94 2 program is dead and /var/lock lock file exists
95 3 program is not running
96 4 program or service status is unknown
97 5-99 reserved for future LSB use
98 100-149 reserved for distribution use
99 150-199 reserved for application use
103 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
= 0,
104 EXIT_PROGRAM_DEAD_AND_PID_EXISTS
= 1,
105 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS
= 2,
106 EXIT_PROGRAM_NOT_RUNNING
= 3,
107 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
= 4,
110 static char **arg_types
= NULL
;
111 static char **arg_states
= NULL
;
112 static char **arg_properties
= NULL
;
113 static bool arg_all
= false;
114 static enum dependency
{
120 } arg_dependency
= DEPENDENCY_FORWARD
;
121 static const char *arg_job_mode
= "replace";
122 static UnitFileScope arg_scope
= UNIT_FILE_SYSTEM
;
123 static bool arg_wait
= false;
124 static bool arg_no_block
= false;
125 static bool arg_no_legend
= false;
126 static bool arg_no_pager
= false;
127 static bool arg_no_wtmp
= false;
128 static bool arg_no_sync
= false;
129 static bool arg_no_wall
= false;
130 static bool arg_no_reload
= false;
131 static bool arg_value
= false;
132 static bool arg_show_types
= false;
133 static bool arg_ignore_inhibitors
= false;
134 static bool arg_dry
= false;
135 static bool arg_quiet
= false;
136 static bool arg_full
= false;
137 static bool arg_recursive
= false;
138 static int arg_force
= 0;
139 static bool arg_ask_password
= false;
140 static bool arg_runtime
= false;
141 static UnitFilePresetMode arg_preset_mode
= UNIT_FILE_PRESET_FULL
;
142 static char **arg_wall
= NULL
;
143 static const char *arg_kill_who
= NULL
;
144 static int arg_signal
= SIGTERM
;
145 static char *arg_root
= NULL
;
146 static usec_t arg_when
= 0;
147 static char *argv_cmdline
= NULL
;
168 ACTION_CANCEL_SHUTDOWN
,
171 } arg_action
= ACTION_SYSTEMCTL
;
172 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
173 static const char *arg_host
= NULL
;
174 static unsigned arg_lines
= 10;
175 static OutputMode arg_output
= OUTPUT_SHORT
;
176 static bool arg_plain
= false;
177 static bool arg_firmware_setup
= false;
178 static bool arg_now
= false;
179 static bool arg_jobs_before
= false;
180 static bool arg_jobs_after
= false;
182 static int daemon_reload(int argc
, char *argv
[], void* userdata
);
183 static int trivial_method(int argc
, char *argv
[], void *userdata
);
184 static int halt_now(enum action a
);
185 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
);
187 static bool original_stdout_is_tty
;
189 typedef enum BusFocus
{
190 BUS_FULL
, /* The full bus indicated via --system or --user */
191 BUS_MANAGER
, /* The manager itself, possibly directly, possibly via the bus */
195 static sd_bus
*busses
[_BUS_FOCUS_MAX
] = {};
197 static UnitFileFlags
args_to_flags(void) {
198 return (arg_runtime
? UNIT_FILE_RUNTIME
: 0) |
199 (arg_force
? UNIT_FILE_FORCE
: 0);
202 static int acquire_bus(BusFocus focus
, sd_bus
**ret
) {
205 assert(focus
< _BUS_FOCUS_MAX
);
208 /* We only go directly to the manager, if we are using a local transport */
209 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
212 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
215 if (!busses
[focus
]) {
218 user
= arg_scope
!= UNIT_FILE_SYSTEM
;
220 if (!user
&& sd_booted() <= 0) {
221 /* Print a friendly message when the local system is actually not running systemd as PID 1. */
222 log_error("System has not been booted with systemd as init system (PID 1). Can't operate.");
226 if (focus
== BUS_MANAGER
)
227 r
= bus_connect_transport_systemd(arg_transport
, arg_host
, user
, &busses
[focus
]);
229 r
= bus_connect_transport(arg_transport
, arg_host
, user
, &busses
[focus
]);
231 return log_error_errno(r
, "Failed to connect to bus: %m");
233 (void) sd_bus_set_allow_interactive_authorization(busses
[focus
], arg_ask_password
);
236 *ret
= busses
[focus
];
240 static void release_busses(void) {
243 for (w
= 0; w
< _BUS_FOCUS_MAX
; w
++)
244 busses
[w
] = sd_bus_flush_close_unref(busses
[w
]);
247 static int map_string_no_copy(sd_bus
*bus
, const char *member
, sd_bus_message
*m
, sd_bus_error
*error
, void *userdata
) {
249 const char **p
= userdata
;
252 r
= sd_bus_message_read_basic(m
, SD_BUS_TYPE_STRING
, &s
);
262 static void ask_password_agent_open_if_enabled(void) {
264 /* Open the password agent as a child process if necessary */
266 if (!arg_ask_password
)
269 if (arg_scope
!= UNIT_FILE_SYSTEM
)
272 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
275 ask_password_agent_open();
278 static void polkit_agent_open_maybe(void) {
279 /* Open the polkit agent as a child process if necessary */
281 if (arg_scope
!= UNIT_FILE_SYSTEM
)
284 polkit_agent_open_if_enabled(arg_transport
, arg_ask_password
);
287 static OutputFlags
get_output_flags(void) {
289 arg_all
* OUTPUT_SHOW_ALL
|
290 (arg_full
|| !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH
|
291 colors_enabled() * OUTPUT_COLOR
|
292 !arg_quiet
* OUTPUT_WARN_CUTOFF
;
295 static int translate_bus_error_to_exit_status(int r
, const sd_bus_error
*error
) {
298 if (!sd_bus_error_is_set(error
))
301 if (sd_bus_error_has_name(error
, SD_BUS_ERROR_ACCESS_DENIED
) ||
302 sd_bus_error_has_name(error
, BUS_ERROR_ONLY_BY_DEPENDENCY
) ||
303 sd_bus_error_has_name(error
, BUS_ERROR_NO_ISOLATION
) ||
304 sd_bus_error_has_name(error
, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE
))
305 return EXIT_NOPERMISSION
;
307 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
))
308 return EXIT_NOTINSTALLED
;
310 if (sd_bus_error_has_name(error
, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE
) ||
311 sd_bus_error_has_name(error
, SD_BUS_ERROR_NOT_SUPPORTED
))
312 return EXIT_NOTIMPLEMENTED
;
314 if (sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
))
315 return EXIT_NOTCONFIGURED
;
323 static bool install_client_side(void) {
325 /* Decides when to execute enable/disable/... operations
326 * client-side rather than server-side. */
328 if (running_in_chroot() > 0)
331 if (sd_booted() <= 0)
334 if (!isempty(arg_root
))
337 if (arg_scope
== UNIT_FILE_GLOBAL
)
340 /* Unsupported environment variable, mostly for debugging purposes */
341 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
347 static int compare_unit_info(const void *a
, const void *b
) {
348 const UnitInfo
*u
= a
, *v
= b
;
352 /* First, order by machine */
353 if (!u
->machine
&& v
->machine
)
355 if (u
->machine
&& !v
->machine
)
357 if (u
->machine
&& v
->machine
) {
358 r
= strcasecmp(u
->machine
, v
->machine
);
363 /* Second, order by unit type */
364 d1
= strrchr(u
->id
, '.');
365 d2
= strrchr(v
->id
, '.');
367 r
= strcasecmp(d1
, d2
);
372 /* Third, order by name */
373 return strcasecmp(u
->id
, v
->id
);
376 static const char* unit_type_suffix(const char *name
) {
379 dot
= strrchr(name
, '.');
386 static bool output_show_unit(const UnitInfo
*u
, char **patterns
) {
389 if (!strv_fnmatch_or_empty(patterns
, u
->id
, FNM_NOESCAPE
))
392 if (arg_types
&& !strv_find(arg_types
, unit_type_suffix(u
->id
)))
398 /* Note that '--all' is not purely a state filter, but also a
399 * filter that hides units that "follow" other units (which is
400 * used for device units that appear under different names). */
401 if (!isempty(u
->following
))
404 if (!strv_isempty(arg_states
))
407 /* By default show all units except the ones in inactive
408 * state and with no pending job */
412 if (streq(u
->active_state
, "inactive"))
418 static int output_units_list(const UnitInfo
*unit_infos
, unsigned c
) {
419 unsigned circle_len
= 0, id_len
, max_id_len
, load_len
, active_len
, sub_len
, job_len
, desc_len
, max_desc_len
;
421 unsigned n_shown
= 0;
424 max_id_len
= strlen("UNIT");
425 load_len
= strlen("LOAD");
426 active_len
= strlen("ACTIVE");
427 sub_len
= strlen("SUB");
428 job_len
= strlen("JOB");
429 max_desc_len
= strlen("DESCRIPTION");
431 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
432 max_id_len
= MAX(max_id_len
, strlen(u
->id
) + (u
->machine
? strlen(u
->machine
)+1 : 0));
433 load_len
= MAX(load_len
, strlen(u
->load_state
));
434 active_len
= MAX(active_len
, strlen(u
->active_state
));
435 sub_len
= MAX(sub_len
, strlen(u
->sub_state
));
436 max_desc_len
= MAX(max_desc_len
, strlen(u
->description
));
438 if (u
->job_id
!= 0) {
439 job_len
= MAX(job_len
, strlen(u
->job_type
));
443 if (!arg_no_legend
&&
444 (streq(u
->active_state
, "failed") ||
445 STR_IN_SET(u
->load_state
, "error", "not-found", "masked")))
449 if (!arg_full
&& original_stdout_is_tty
) {
452 id_len
= MIN(max_id_len
, 25u); /* as much as it needs, but at most 25 for now */
453 basic_len
= circle_len
+ 1 + id_len
+ 1 + load_len
+ 1 + active_len
+ 1 + sub_len
+ 1;
456 basic_len
+= job_len
+ 1;
458 if (basic_len
< (unsigned) columns()) {
459 unsigned extra_len
, incr
;
460 extra_len
= columns() - basic_len
;
462 /* Either UNIT already got 25, or is fully satisfied.
463 * Grant up to 25 to DESC now. */
464 incr
= MIN(extra_len
, 25u);
468 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
469 * description but not more than it needs. */
471 incr
= MIN(max_id_len
- id_len
, extra_len
);
473 desc_len
+= MIN(extra_len
- incr
, max_desc_len
- desc_len
);
479 desc_len
= max_desc_len
;
482 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
483 _cleanup_free_
char *e
= NULL
, *j
= NULL
;
484 const char *on_underline
= "", *off_underline
= "";
485 const char *on_loaded
= "", *off_loaded
= "";
486 const char *on_active
= "", *off_active
= "";
487 const char *on_circle
= "", *off_circle
= "";
489 bool circle
= false, underline
= false;
491 if (!n_shown
&& !arg_no_legend
) {
496 printf("%s%-*s %-*s %-*s %-*s ",
500 active_len
, "ACTIVE",
504 printf("%-*s ", job_len
, "JOB");
508 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
515 if (u
+ 1 < unit_infos
+ c
&&
516 !streq(unit_type_suffix(u
->id
), unit_type_suffix((u
+ 1)->id
))) {
517 on_underline
= ansi_underline();
518 off_underline
= ansi_normal();
522 if (STR_IN_SET(u
->load_state
, "error", "not-found", "masked") && !arg_plain
) {
523 on_circle
= ansi_highlight_yellow();
524 off_circle
= ansi_normal();
526 on_loaded
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
527 off_loaded
= underline
? on_underline
: ansi_normal();
528 } else if (streq(u
->active_state
, "failed") && !arg_plain
) {
529 on_circle
= ansi_highlight_red();
530 off_circle
= ansi_normal();
532 on_active
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
533 off_active
= underline
? on_underline
: ansi_normal();
537 j
= strjoin(u
->machine
, ":", u
->id
);
546 e
= ellipsize(id
, id_len
, 33);
554 printf("%s%s%s ", on_circle
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_circle
);
556 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
558 on_active
, id_len
, id
, off_active
,
559 on_loaded
, load_len
, u
->load_state
, off_loaded
,
560 on_active
, active_len
, u
->active_state
,
561 sub_len
, u
->sub_state
, off_active
,
562 job_count
? job_len
+ 1 : 0, u
->job_id
? u
->job_type
: "");
566 !arg_full
&& arg_no_pager
? (int) desc_len
: -1,
571 if (!arg_no_legend
) {
572 const char *on
, *off
;
576 "LOAD = Reflects whether the unit definition was properly loaded.\n"
577 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
578 "SUB = The low-level unit activation state, values depend on unit type.");
579 puts(job_count
? "JOB = Pending job for the unit.\n" : "");
580 on
= ansi_highlight();
583 on
= ansi_highlight_red();
588 printf("%s%u loaded units listed.%s\n"
589 "To show all installed unit files use 'systemctl list-unit-files'.\n",
592 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
593 "To show all installed unit files use 'systemctl list-unit-files'.\n",
600 static int get_unit_list(
604 UnitInfo
**unit_infos
,
606 sd_bus_message
**_reply
) {
608 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
609 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
610 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
614 bool fallback
= false;
620 r
= sd_bus_message_new_method_call(
623 "org.freedesktop.systemd1",
624 "/org/freedesktop/systemd1",
625 "org.freedesktop.systemd1.Manager",
626 "ListUnitsByPatterns");
628 return bus_log_create_error(r
);
630 r
= sd_bus_message_append_strv(m
, arg_states
);
632 return bus_log_create_error(r
);
634 r
= sd_bus_message_append_strv(m
, patterns
);
636 return bus_log_create_error(r
);
638 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
639 if (r
< 0 && (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
) ||
640 sd_bus_error_has_name(&error
, SD_BUS_ERROR_ACCESS_DENIED
))) {
641 /* Fallback to legacy ListUnitsFiltered method */
643 log_debug_errno(r
, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error
, r
));
644 m
= sd_bus_message_unref(m
);
645 sd_bus_error_free(&error
);
647 r
= sd_bus_message_new_method_call(
650 "org.freedesktop.systemd1",
651 "/org/freedesktop/systemd1",
652 "org.freedesktop.systemd1.Manager",
653 "ListUnitsFiltered");
655 return bus_log_create_error(r
);
657 r
= sd_bus_message_append_strv(m
, arg_states
);
659 return bus_log_create_error(r
);
661 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
664 return log_error_errno(r
, "Failed to list units: %s", bus_error_message(&error
, r
));
666 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssssouso)");
668 return bus_log_parse_error(r
);
670 while ((r
= bus_parse_unit_info(reply
, &u
)) > 0) {
673 if (!output_show_unit(&u
, fallback
? patterns
: NULL
))
676 if (!GREEDY_REALLOC(*unit_infos
, size
, c
+1))
679 (*unit_infos
)[c
++] = u
;
682 return bus_log_parse_error(r
);
684 r
= sd_bus_message_exit_container(reply
);
686 return bus_log_parse_error(r
);
694 static void message_set_freep(Set
**set
) {
697 while ((m
= set_steal_first(*set
)))
698 sd_bus_message_unref(m
);
703 static int get_unit_list_recursive(
706 UnitInfo
**_unit_infos
,
710 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
711 _cleanup_(message_set_freep
) Set
*replies
;
712 sd_bus_message
*reply
;
720 replies
= set_new(NULL
);
724 c
= get_unit_list(bus
, NULL
, patterns
, &unit_infos
, 0, &reply
);
728 r
= set_put(replies
, reply
);
730 sd_bus_message_unref(reply
);
735 _cleanup_strv_free_
char **machines
= NULL
;
738 r
= sd_get_machine_names(&machines
);
740 return log_error_errno(r
, "Failed to get machine names: %m");
742 STRV_FOREACH(i
, machines
) {
743 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
746 r
= sd_bus_open_system_machine(&container
, *i
);
748 log_warning_errno(r
, "Failed to connect to container %s, ignoring: %m", *i
);
752 k
= get_unit_list(container
, *i
, patterns
, &unit_infos
, c
, &reply
);
758 r
= set_put(replies
, reply
);
760 sd_bus_message_unref(reply
);
765 *_machines
= machines
;
770 *_unit_infos
= unit_infos
;
779 static int list_units(int argc
, char *argv
[], void *userdata
) {
780 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
781 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
782 _cleanup_strv_free_
char **machines
= NULL
;
786 r
= acquire_bus(BUS_MANAGER
, &bus
);
790 pager_open(arg_no_pager
, false);
792 r
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
796 qsort_safe(unit_infos
, r
, sizeof(UnitInfo
), compare_unit_info
);
797 return output_units_list(unit_infos
, r
);
800 static int get_triggered_units(
805 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
812 r
= sd_bus_get_property_strv(
814 "org.freedesktop.systemd1",
816 "org.freedesktop.systemd1.Unit",
821 return log_error_errno(r
, "Failed to determine triggers: %s", bus_error_message(&error
, r
));
826 static int get_listening(
828 const char* unit_path
,
831 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
832 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
833 const char *type
, *path
;
836 r
= sd_bus_get_property(
838 "org.freedesktop.systemd1",
840 "org.freedesktop.systemd1.Socket",
846 return log_error_errno(r
, "Failed to get list of listening sockets: %s", bus_error_message(&error
, r
));
848 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
850 return bus_log_parse_error(r
);
852 while ((r
= sd_bus_message_read(reply
, "(ss)", &type
, &path
)) > 0) {
854 r
= strv_extend(listening
, type
);
858 r
= strv_extend(listening
, path
);
865 return bus_log_parse_error(r
);
867 r
= sd_bus_message_exit_container(reply
);
869 return bus_log_parse_error(r
);
881 /* Note: triggered is a list here, although it almost certainly
882 * will always be one unit. Nevertheless, dbus API allows for multiple
883 * values, so let's follow that. */
886 /* The strv above is shared. free is set only in the first one. */
890 static int socket_info_compare(const struct socket_info
*a
, const struct socket_info
*b
) {
896 if (!a
->machine
&& b
->machine
)
898 if (a
->machine
&& !b
->machine
)
900 if (a
->machine
&& b
->machine
) {
901 o
= strcasecmp(a
->machine
, b
->machine
);
906 o
= strcmp(a
->path
, b
->path
);
908 o
= strcmp(a
->type
, b
->type
);
913 static int output_sockets_list(struct socket_info
*socket_infos
, unsigned cs
) {
914 struct socket_info
*s
;
915 unsigned pathlen
= strlen("LISTEN"),
916 typelen
= strlen("TYPE") * arg_show_types
,
917 socklen
= strlen("UNIT"),
918 servlen
= strlen("ACTIVATES");
919 const char *on
, *off
;
921 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
925 socklen
= MAX(socklen
, strlen(s
->id
));
927 typelen
= MAX(typelen
, strlen(s
->type
));
928 pathlen
= MAX(pathlen
, strlen(s
->path
) + (s
->machine
? strlen(s
->machine
)+1 : 0));
930 STRV_FOREACH(a
, s
->triggered
)
931 tmp
+= strlen(*a
) + 2*(a
!= s
->triggered
);
932 servlen
= MAX(servlen
, tmp
);
937 printf("%-*s %-*.*s%-*s %s\n",
939 typelen
+ arg_show_types
, typelen
+ arg_show_types
, "TYPE ",
943 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
944 _cleanup_free_
char *j
= NULL
;
949 j
= strjoin(s
->machine
, ":", s
->path
);
957 printf("%-*s %-*s %-*s",
958 pathlen
, path
, typelen
, s
->type
, socklen
, s
->id
);
961 pathlen
, path
, socklen
, s
->id
);
962 STRV_FOREACH(a
, s
->triggered
)
964 a
== s
->triggered
? "" : ",", *a
);
968 on
= ansi_highlight();
973 on
= ansi_highlight_red();
977 if (!arg_no_legend
) {
978 printf("%s%u sockets listed.%s\n", on
, cs
, off
);
980 printf("Pass --all to see loaded but inactive sockets, too.\n");
986 static int list_sockets(int argc
, char *argv
[], void *userdata
) {
987 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
988 _cleanup_strv_free_
char **machines
= NULL
;
989 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
990 _cleanup_free_
struct socket_info
*socket_infos
= NULL
;
992 struct socket_info
*s
;
998 r
= acquire_bus(BUS_MANAGER
, &bus
);
1002 pager_open(arg_no_pager
, false);
1004 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1008 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1009 _cleanup_strv_free_
char **listening
= NULL
, **triggered
= NULL
;
1012 if (!endswith(u
->id
, ".socket"))
1015 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1019 c
= get_listening(bus
, u
->unit_path
, &listening
);
1025 if (!GREEDY_REALLOC(socket_infos
, size
, cs
+ c
)) {
1030 for (i
= 0; i
< c
; i
++)
1031 socket_infos
[cs
+ i
] = (struct socket_info
) {
1032 .machine
= u
->machine
,
1034 .type
= listening
[i
*2],
1035 .path
= listening
[i
*2 + 1],
1036 .triggered
= triggered
,
1037 .own_triggered
= i
==0,
1040 /* from this point on we will cleanup those socket_infos */
1043 listening
= triggered
= NULL
; /* avoid cleanup */
1046 qsort_safe(socket_infos
, cs
, sizeof(struct socket_info
),
1047 (__compar_fn_t
) socket_info_compare
);
1049 output_sockets_list(socket_infos
, cs
);
1052 assert(cs
== 0 || socket_infos
);
1053 for (s
= socket_infos
; s
< socket_infos
+ cs
; s
++) {
1056 if (s
->own_triggered
)
1057 strv_free(s
->triggered
);
1063 static int get_next_elapse(
1066 dual_timestamp
*next
) {
1068 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1076 r
= sd_bus_get_property_trivial(
1078 "org.freedesktop.systemd1",
1080 "org.freedesktop.systemd1.Timer",
1081 "NextElapseUSecMonotonic",
1086 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1088 r
= sd_bus_get_property_trivial(
1090 "org.freedesktop.systemd1",
1092 "org.freedesktop.systemd1.Timer",
1093 "NextElapseUSecRealtime",
1098 return log_error_errno(r
, "Failed to get next elapsation time: %s", bus_error_message(&error
, r
));
1104 static int get_last_trigger(
1109 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1116 r
= sd_bus_get_property_trivial(
1118 "org.freedesktop.systemd1",
1120 "org.freedesktop.systemd1.Timer",
1126 return log_error_errno(r
, "Failed to get last trigger time: %s", bus_error_message(&error
, r
));
1132 const char* machine
;
1135 usec_t last_trigger
;
1139 static int timer_info_compare(const struct timer_info
*a
, const struct timer_info
*b
) {
1145 if (!a
->machine
&& b
->machine
)
1147 if (a
->machine
&& !b
->machine
)
1149 if (a
->machine
&& b
->machine
) {
1150 o
= strcasecmp(a
->machine
, b
->machine
);
1155 if (a
->next_elapse
< b
->next_elapse
)
1157 if (a
->next_elapse
> b
->next_elapse
)
1160 return strcmp(a
->id
, b
->id
);
1163 static int output_timers_list(struct timer_info
*timer_infos
, unsigned n
) {
1164 struct timer_info
*t
;
1166 nextlen
= strlen("NEXT"),
1167 leftlen
= strlen("LEFT"),
1168 lastlen
= strlen("LAST"),
1169 passedlen
= strlen("PASSED"),
1170 unitlen
= strlen("UNIT"),
1171 activatelen
= strlen("ACTIVATES");
1173 const char *on
, *off
;
1175 assert(timer_infos
|| n
== 0);
1177 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1181 if (t
->next_elapse
> 0) {
1182 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1184 format_timestamp(tstamp
, sizeof(tstamp
), t
->next_elapse
);
1185 nextlen
= MAX(nextlen
, strlen(tstamp
) + 1);
1187 format_timestamp_relative(trel
, sizeof(trel
), t
->next_elapse
);
1188 leftlen
= MAX(leftlen
, strlen(trel
));
1191 if (t
->last_trigger
> 0) {
1192 char tstamp
[FORMAT_TIMESTAMP_MAX
] = "", trel
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "";
1194 format_timestamp(tstamp
, sizeof(tstamp
), t
->last_trigger
);
1195 lastlen
= MAX(lastlen
, strlen(tstamp
) + 1);
1197 format_timestamp_relative(trel
, sizeof(trel
), t
->last_trigger
);
1198 passedlen
= MAX(passedlen
, strlen(trel
));
1201 unitlen
= MAX(unitlen
, strlen(t
->id
) + (t
->machine
? strlen(t
->machine
)+1 : 0));
1203 STRV_FOREACH(a
, t
->triggered
)
1204 ul
+= strlen(*a
) + 2*(a
!= t
->triggered
);
1206 activatelen
= MAX(activatelen
, ul
);
1211 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1215 passedlen
, "PASSED",
1219 for (t
= timer_infos
; t
< timer_infos
+ n
; t
++) {
1220 _cleanup_free_
char *j
= NULL
;
1222 char tstamp1
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel1
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1223 char tstamp2
[FORMAT_TIMESTAMP_MAX
] = "n/a", trel2
[FORMAT_TIMESTAMP_RELATIVE_MAX
] = "n/a";
1226 format_timestamp(tstamp1
, sizeof(tstamp1
), t
->next_elapse
);
1227 format_timestamp_relative(trel1
, sizeof(trel1
), t
->next_elapse
);
1229 format_timestamp(tstamp2
, sizeof(tstamp2
), t
->last_trigger
);
1230 format_timestamp_relative(trel2
, sizeof(trel2
), t
->last_trigger
);
1233 j
= strjoin(t
->machine
, ":", t
->id
);
1240 printf("%-*s %-*s %-*s %-*s %-*s",
1241 nextlen
, tstamp1
, leftlen
, trel1
, lastlen
, tstamp2
, passedlen
, trel2
, unitlen
, unit
);
1243 STRV_FOREACH(a
, t
->triggered
)
1245 a
== t
->triggered
? "" : ",", *a
);
1249 on
= ansi_highlight();
1250 off
= ansi_normal();
1254 on
= ansi_highlight_red();
1255 off
= ansi_normal();
1258 if (!arg_no_legend
) {
1259 printf("%s%u timers listed.%s\n", on
, n
, off
);
1261 printf("Pass --all to see loaded but inactive timers, too.\n");
1267 static usec_t
calc_next_elapse(dual_timestamp
*nw
, dual_timestamp
*next
) {
1273 if (next
->monotonic
!= USEC_INFINITY
&& next
->monotonic
> 0) {
1276 if (next
->monotonic
> nw
->monotonic
)
1277 converted
= nw
->realtime
+ (next
->monotonic
- nw
->monotonic
);
1279 converted
= nw
->realtime
- (nw
->monotonic
- next
->monotonic
);
1281 if (next
->realtime
!= USEC_INFINITY
&& next
->realtime
> 0)
1282 next_elapse
= MIN(converted
, next
->realtime
);
1284 next_elapse
= converted
;
1287 next_elapse
= next
->realtime
;
1292 static int list_timers(int argc
, char *argv
[], void *userdata
) {
1293 _cleanup_(message_set_freep
) Set
*replies
= NULL
;
1294 _cleanup_strv_free_
char **machines
= NULL
;
1295 _cleanup_free_
struct timer_info
*timer_infos
= NULL
;
1296 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
1297 struct timer_info
*t
;
1305 r
= acquire_bus(BUS_MANAGER
, &bus
);
1309 pager_open(arg_no_pager
, false);
1311 n
= get_unit_list_recursive(bus
, strv_skip(argv
, 1), &unit_infos
, &replies
, &machines
);
1315 dual_timestamp_get(&nw
);
1317 for (u
= unit_infos
; u
< unit_infos
+ n
; u
++) {
1318 _cleanup_strv_free_
char **triggered
= NULL
;
1319 dual_timestamp next
= DUAL_TIMESTAMP_NULL
;
1322 if (!endswith(u
->id
, ".timer"))
1325 r
= get_triggered_units(bus
, u
->unit_path
, &triggered
);
1329 r
= get_next_elapse(bus
, u
->unit_path
, &next
);
1333 get_last_trigger(bus
, u
->unit_path
, &last
);
1335 if (!GREEDY_REALLOC(timer_infos
, size
, c
+1)) {
1340 m
= calc_next_elapse(&nw
, &next
);
1342 timer_infos
[c
++] = (struct timer_info
) {
1343 .machine
= u
->machine
,
1346 .last_trigger
= last
,
1347 .triggered
= triggered
,
1350 triggered
= NULL
; /* avoid cleanup */
1353 qsort_safe(timer_infos
, c
, sizeof(struct timer_info
),
1354 (__compar_fn_t
) timer_info_compare
);
1356 output_timers_list(timer_infos
, c
);
1359 for (t
= timer_infos
; t
< timer_infos
+ c
; t
++)
1360 strv_free(t
->triggered
);
1365 static int compare_unit_file_list(const void *a
, const void *b
) {
1366 const char *d1
, *d2
;
1367 const UnitFileList
*u
= a
, *v
= b
;
1369 d1
= strrchr(u
->path
, '.');
1370 d2
= strrchr(v
->path
, '.');
1375 r
= strcasecmp(d1
, d2
);
1380 return strcasecmp(basename(u
->path
), basename(v
->path
));
1383 static bool output_show_unit_file(const UnitFileList
*u
, char **states
, char **patterns
) {
1386 if (!strv_fnmatch_or_empty(patterns
, basename(u
->path
), FNM_NOESCAPE
))
1389 if (!strv_isempty(arg_types
)) {
1392 dot
= strrchr(u
->path
, '.');
1396 if (!strv_find(arg_types
, dot
+1))
1400 if (!strv_isempty(states
) &&
1401 !strv_find(states
, unit_file_state_to_string(u
->state
)))
1407 static void output_unit_file_list(const UnitFileList
*units
, unsigned c
) {
1408 unsigned max_id_len
, id_cols
, state_cols
;
1409 const UnitFileList
*u
;
1411 max_id_len
= strlen("UNIT FILE");
1412 state_cols
= strlen("STATE");
1414 for (u
= units
; u
< units
+ c
; u
++) {
1415 max_id_len
= MAX(max_id_len
, strlen(basename(u
->path
)));
1416 state_cols
= MAX(state_cols
, strlen(unit_file_state_to_string(u
->state
)));
1420 unsigned basic_cols
;
1422 id_cols
= MIN(max_id_len
, 25u);
1423 basic_cols
= 1 + id_cols
+ state_cols
;
1424 if (basic_cols
< (unsigned) columns())
1425 id_cols
+= MIN(columns() - basic_cols
, max_id_len
- id_cols
);
1427 id_cols
= max_id_len
;
1429 if (!arg_no_legend
&& c
> 0)
1430 printf("%s%-*s %-*s%s\n",
1432 id_cols
, "UNIT FILE",
1433 state_cols
, "STATE",
1436 for (u
= units
; u
< units
+ c
; u
++) {
1437 const char *on_underline
= NULL
, *on_color
= NULL
, *off
= NULL
, *id
;
1438 _cleanup_free_
char *e
= NULL
;
1441 underline
= u
+ 1 < units
+ c
&&
1442 !streq(unit_type_suffix(u
->path
), unit_type_suffix((u
+ 1)->path
));
1445 on_underline
= ansi_underline();
1447 if (IN_SET(u
->state
,
1449 UNIT_FILE_MASKED_RUNTIME
,
1452 on_color
= underline
? ansi_highlight_red_underline() : ansi_highlight_red();
1453 else if (u
->state
== UNIT_FILE_ENABLED
)
1454 on_color
= underline
? ansi_highlight_green_underline() : ansi_highlight_green();
1456 if (on_underline
|| on_color
)
1457 off
= ansi_normal();
1459 id
= basename(u
->path
);
1461 e
= arg_full
? NULL
: ellipsize(id
, id_cols
, 33);
1463 printf("%s%-*s %s%-*s%s\n",
1464 strempty(on_underline
),
1465 id_cols
, e
? e
: id
,
1466 strempty(on_color
), state_cols
, unit_file_state_to_string(u
->state
), strempty(off
));
1470 printf("\n%u unit files listed.\n", c
);
1473 static int list_unit_files(int argc
, char *argv
[], void *userdata
) {
1474 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1475 _cleanup_free_ UnitFileList
*units
= NULL
;
1482 bool fallback
= false;
1484 if (install_client_side()) {
1490 h
= hashmap_new(&string_hash_ops
);
1494 r
= unit_file_get_list(arg_scope
, arg_root
, h
, arg_states
, strv_skip(argv
, 1));
1496 unit_file_list_free(h
);
1497 return log_error_errno(r
, "Failed to get unit file list: %m");
1500 n_units
= hashmap_size(h
);
1502 units
= new(UnitFileList
, n_units
?: 1); /* avoid malloc(0) */
1504 unit_file_list_free(h
);
1508 HASHMAP_FOREACH(u
, h
, i
) {
1509 if (!output_show_unit_file(u
, NULL
, NULL
))
1516 assert(c
<= n_units
);
1521 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
1522 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1525 r
= acquire_bus(BUS_MANAGER
, &bus
);
1529 r
= sd_bus_message_new_method_call(
1532 "org.freedesktop.systemd1",
1533 "/org/freedesktop/systemd1",
1534 "org.freedesktop.systemd1.Manager",
1535 "ListUnitFilesByPatterns");
1537 return bus_log_create_error(r
);
1539 r
= sd_bus_message_append_strv(m
, arg_states
);
1541 return bus_log_create_error(r
);
1543 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
1545 return bus_log_create_error(r
);
1547 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1548 if (r
< 0 && sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_METHOD
)) {
1549 /* Fallback to legacy ListUnitFiles method */
1551 log_debug_errno(r
, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error
, r
));
1552 m
= sd_bus_message_unref(m
);
1553 sd_bus_error_free(&error
);
1555 r
= sd_bus_message_new_method_call(
1558 "org.freedesktop.systemd1",
1559 "/org/freedesktop/systemd1",
1560 "org.freedesktop.systemd1.Manager",
1563 return bus_log_create_error(r
);
1565 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
1568 return log_error_errno(r
, "Failed to list unit files: %s", bus_error_message(&error
, r
));
1570 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ss)");
1572 return bus_log_parse_error(r
);
1574 while ((r
= sd_bus_message_read(reply
, "(ss)", &path
, &state
)) > 0) {
1576 if (!GREEDY_REALLOC(units
, size
, c
+ 1))
1579 units
[c
] = (struct UnitFileList
) {
1581 unit_file_state_from_string(state
)
1584 if (output_show_unit_file(&units
[c
],
1585 fallback
? arg_states
: NULL
,
1586 fallback
? strv_skip(argv
, 1) : NULL
))
1591 return bus_log_parse_error(r
);
1593 r
= sd_bus_message_exit_container(reply
);
1595 return bus_log_parse_error(r
);
1598 pager_open(arg_no_pager
, false);
1600 qsort_safe(units
, c
, sizeof(UnitFileList
), compare_unit_file_list
);
1601 output_unit_file_list(units
, c
);
1603 if (install_client_side())
1604 for (unit
= units
; unit
< units
+ c
; unit
++)
1610 static int list_dependencies_print(const char *name
, int level
, unsigned int branches
, bool last
) {
1611 _cleanup_free_
char *n
= NULL
;
1612 size_t max_len
= MAX(columns(),20u);
1618 for (i
= level
- 1; i
>= 0; i
--) {
1620 if (len
> max_len
- 3 && !arg_full
) {
1621 printf("%s...\n",max_len
% 2 ? "" : " ");
1624 printf("%s", special_glyph(branches
& (1 << i
) ? TREE_VERTICAL
: TREE_SPACE
));
1628 if (len
> max_len
- 3 && !arg_full
) {
1629 printf("%s...\n",max_len
% 2 ? "" : " ");
1633 printf("%s", special_glyph(last
? TREE_RIGHT
: TREE_BRANCH
));
1637 printf("%s\n", name
);
1641 n
= ellipsize(name
, max_len
-len
, 100);
1649 static int list_dependencies_get_dependencies(sd_bus
*bus
, const char *name
, char ***deps
) {
1651 static const char *dependencies
[_DEPENDENCY_MAX
] = {
1652 [DEPENDENCY_FORWARD
] = "Requires\0"
1657 [DEPENDENCY_REVERSE
] = "RequiredBy\0"
1662 [DEPENDENCY_AFTER
] = "After\0",
1663 [DEPENDENCY_BEFORE
] = "Before\0",
1666 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1667 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1668 _cleanup_strv_free_
char **ret
= NULL
;
1669 _cleanup_free_
char *path
= NULL
;
1675 assert_cc(ELEMENTSOF(dependencies
) == _DEPENDENCY_MAX
);
1677 path
= unit_dbus_path_from_name(name
);
1681 r
= sd_bus_call_method(
1683 "org.freedesktop.systemd1",
1685 "org.freedesktop.DBus.Properties",
1689 "s", "org.freedesktop.systemd1.Unit");
1691 return log_error_errno(r
, "Failed to get properties of %s: %s", name
, bus_error_message(&error
, r
));
1693 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
1695 return bus_log_parse_error(r
);
1697 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
1700 r
= sd_bus_message_read(reply
, "s", &prop
);
1702 return bus_log_parse_error(r
);
1704 if (!nulstr_contains(dependencies
[arg_dependency
], prop
)) {
1705 r
= sd_bus_message_skip(reply
, "v");
1707 return bus_log_parse_error(r
);
1710 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, "as");
1712 return bus_log_parse_error(r
);
1714 r
= bus_message_read_strv_extend(reply
, &ret
);
1716 return bus_log_parse_error(r
);
1718 r
= sd_bus_message_exit_container(reply
);
1720 return bus_log_parse_error(r
);
1723 r
= sd_bus_message_exit_container(reply
);
1725 return bus_log_parse_error(r
);
1729 return bus_log_parse_error(r
);
1731 r
= sd_bus_message_exit_container(reply
);
1733 return bus_log_parse_error(r
);
1735 *deps
= strv_uniq(ret
);
1741 static int list_dependencies_compare(const void *_a
, const void *_b
) {
1742 const char **a
= (const char**) _a
, **b
= (const char**) _b
;
1744 if (unit_name_to_type(*a
) == UNIT_TARGET
&& unit_name_to_type(*b
) != UNIT_TARGET
)
1746 if (unit_name_to_type(*a
) != UNIT_TARGET
&& unit_name_to_type(*b
) == UNIT_TARGET
)
1749 return strcasecmp(*a
, *b
);
1752 static int list_dependencies_one(
1757 unsigned int branches
) {
1759 _cleanup_strv_free_
char **deps
= NULL
;
1767 r
= strv_extend(units
, name
);
1771 r
= list_dependencies_get_dependencies(bus
, name
, &deps
);
1775 qsort_safe(deps
, strv_length(deps
), sizeof (char*), list_dependencies_compare
);
1777 STRV_FOREACH(c
, deps
) {
1778 if (strv_contains(*units
, *c
)) {
1781 r
= list_dependencies_print("...", level
+ 1, (branches
<< 1) | (c
[1] == NULL
? 0 : 1), 1);
1791 UnitActiveState active_state
= _UNIT_ACTIVE_STATE_INVALID
;
1794 (void) get_state_one_unit(bus
, *c
, &active_state
);
1796 switch (active_state
) {
1798 case UNIT_RELOADING
:
1799 case UNIT_ACTIVATING
:
1800 on
= ansi_highlight_green();
1804 case UNIT_DEACTIVATING
:
1809 on
= ansi_highlight_red();
1813 printf("%s%s%s ", on
, special_glyph(BLACK_CIRCLE
), ansi_normal());
1816 r
= list_dependencies_print(*c
, level
, branches
, c
[1] == NULL
);
1820 if (arg_all
|| unit_name_to_type(*c
) == UNIT_TARGET
) {
1821 r
= list_dependencies_one(bus
, *c
, level
+ 1, units
, (branches
<< 1) | (c
[1] == NULL
? 0 : 1));
1828 strv_remove(*units
, name
);
1833 static int list_dependencies(int argc
, char *argv
[], void *userdata
) {
1834 _cleanup_strv_free_
char **units
= NULL
;
1835 _cleanup_free_
char *unit
= NULL
;
1841 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &unit
);
1843 return log_error_errno(r
, "Failed to mangle unit name: %m");
1847 u
= SPECIAL_DEFAULT_TARGET
;
1849 r
= acquire_bus(BUS_MANAGER
, &bus
);
1853 pager_open(arg_no_pager
, false);
1857 return list_dependencies_one(bus
, u
, 0, &units
, 0);
1860 struct machine_info
{
1864 char *control_group
;
1865 uint32_t n_failed_units
;
1870 static const struct bus_properties_map machine_info_property_map
[] = {
1871 { "SystemState", "s", NULL
, offsetof(struct machine_info
, state
) },
1872 { "NJobs", "u", NULL
, offsetof(struct machine_info
, n_jobs
) },
1873 { "NFailedUnits", "u", NULL
, offsetof(struct machine_info
, n_failed_units
) },
1874 { "ControlGroup", "s", NULL
, offsetof(struct machine_info
, control_group
) },
1875 { "UserspaceTimestamp", "t", NULL
, offsetof(struct machine_info
, timestamp
) },
1879 static void machine_info_clear(struct machine_info
*info
) {
1884 free(info
->control_group
);
1888 static void free_machines_list(struct machine_info
*machine_infos
, int n
) {
1894 for (i
= 0; i
< n
; i
++)
1895 machine_info_clear(&machine_infos
[i
]);
1897 free(machine_infos
);
1900 static int compare_machine_info(const void *a
, const void *b
) {
1901 const struct machine_info
*u
= a
, *v
= b
;
1903 if (u
->is_host
!= v
->is_host
)
1904 return u
->is_host
> v
->is_host
? -1 : 1;
1906 return strcasecmp(u
->name
, v
->name
);
1909 static int get_machine_properties(sd_bus
*bus
, struct machine_info
*mi
) {
1910 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*container
= NULL
;
1916 r
= sd_bus_open_system_machine(&container
, mi
->name
);
1923 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, NULL
, mi
);
1930 static bool output_show_machine(const char *name
, char **patterns
) {
1931 return strv_fnmatch_or_empty(patterns
, name
, FNM_NOESCAPE
);
1934 static int get_machine_list(
1936 struct machine_info
**_machine_infos
,
1939 struct machine_info
*machine_infos
= NULL
;
1940 _cleanup_strv_free_
char **m
= NULL
;
1941 _cleanup_free_
char *hn
= NULL
;
1946 hn
= gethostname_malloc();
1950 if (output_show_machine(hn
, patterns
)) {
1951 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1))
1954 machine_infos
[c
].is_host
= true;
1955 machine_infos
[c
].name
= hn
;
1958 (void) get_machine_properties(bus
, &machine_infos
[c
]);
1962 r
= sd_get_machine_names(&m
);
1964 return log_error_errno(r
, "Failed to get machine list: %m");
1966 STRV_FOREACH(i
, m
) {
1967 _cleanup_free_
char *class = NULL
;
1969 if (!output_show_machine(*i
, patterns
))
1972 sd_machine_get_class(*i
, &class);
1973 if (!streq_ptr(class, "container"))
1976 if (!GREEDY_REALLOC0(machine_infos
, sz
, c
+1)) {
1977 free_machines_list(machine_infos
, c
);
1981 machine_infos
[c
].is_host
= false;
1982 machine_infos
[c
].name
= strdup(*i
);
1983 if (!machine_infos
[c
].name
) {
1984 free_machines_list(machine_infos
, c
);
1988 (void) get_machine_properties(NULL
, &machine_infos
[c
]);
1992 *_machine_infos
= machine_infos
;
1996 static void output_machines_list(struct machine_info
*machine_infos
, unsigned n
) {
1997 struct machine_info
*m
;
2000 namelen
= sizeof("NAME") - 1,
2001 statelen
= sizeof("STATE") - 1,
2002 failedlen
= sizeof("FAILED") - 1,
2003 jobslen
= sizeof("JOBS") - 1;
2005 assert(machine_infos
|| n
== 0);
2007 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2008 namelen
= MAX(namelen
, strlen(m
->name
) + (m
->is_host
? sizeof(" (host)") - 1 : 0));
2009 statelen
= MAX(statelen
, strlen_ptr(m
->state
));
2010 failedlen
= MAX(failedlen
, DECIMAL_STR_WIDTH(m
->n_failed_units
));
2011 jobslen
= MAX(jobslen
, DECIMAL_STR_WIDTH(m
->n_jobs
));
2013 if (!arg_plain
&& !streq_ptr(m
->state
, "running"))
2017 if (!arg_no_legend
) {
2021 printf("%-*s %-*s %-*s %-*s\n",
2024 failedlen
, "FAILED",
2028 for (m
= machine_infos
; m
< machine_infos
+ n
; m
++) {
2029 const char *on_state
= "", *off_state
= "";
2030 const char *on_failed
= "", *off_failed
= "";
2031 bool circle
= false;
2033 if (streq_ptr(m
->state
, "degraded")) {
2034 on_state
= ansi_highlight_red();
2035 off_state
= ansi_normal();
2037 } else if (!streq_ptr(m
->state
, "running")) {
2038 on_state
= ansi_highlight_yellow();
2039 off_state
= ansi_normal();
2043 if (m
->n_failed_units
> 0) {
2044 on_failed
= ansi_highlight_red();
2045 off_failed
= ansi_normal();
2047 on_failed
= off_failed
= "";
2050 printf("%s%s%s ", on_state
, circle
? special_glyph(BLACK_CIRCLE
) : " ", off_state
);
2053 printf("%-*s (host) %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2054 (int) (namelen
- (sizeof(" (host)")-1)), strna(m
->name
),
2055 on_state
, statelen
, strna(m
->state
), off_state
,
2056 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2057 jobslen
, m
->n_jobs
);
2059 printf("%-*s %s%-*s%s %s%*" PRIu32
"%s %*" PRIu32
"\n",
2060 namelen
, strna(m
->name
),
2061 on_state
, statelen
, strna(m
->state
), off_state
,
2062 on_failed
, failedlen
, m
->n_failed_units
, off_failed
,
2063 jobslen
, m
->n_jobs
);
2067 printf("\n%u machines listed.\n", n
);
2070 static int list_machines(int argc
, char *argv
[], void *userdata
) {
2071 struct machine_info
*machine_infos
= NULL
;
2075 if (geteuid() != 0) {
2076 log_error("Must be root.");
2080 r
= acquire_bus(BUS_MANAGER
, &bus
);
2084 r
= get_machine_list(bus
, &machine_infos
, strv_skip(argv
, 1));
2088 pager_open(arg_no_pager
, false);
2090 qsort_safe(machine_infos
, r
, sizeof(struct machine_info
), compare_machine_info
);
2091 output_machines_list(machine_infos
, r
);
2092 free_machines_list(machine_infos
, r
);
2097 static int get_default(int argc
, char *argv
[], void *userdata
) {
2098 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2099 _cleanup_free_
char *_path
= NULL
;
2103 if (install_client_side()) {
2104 r
= unit_file_get_default(arg_scope
, arg_root
, &_path
);
2106 return log_error_errno(r
, "Failed to get default target: %m");
2111 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2114 r
= acquire_bus(BUS_MANAGER
, &bus
);
2118 r
= sd_bus_call_method(
2120 "org.freedesktop.systemd1",
2121 "/org/freedesktop/systemd1",
2122 "org.freedesktop.systemd1.Manager",
2128 return log_error_errno(r
, "Failed to get default target: %s", bus_error_message(&error
, r
));
2130 r
= sd_bus_message_read(reply
, "s", &path
);
2132 return bus_log_parse_error(r
);
2136 printf("%s\n", path
);
2141 static int set_default(int argc
, char *argv
[], void *userdata
) {
2142 _cleanup_free_
char *unit
= NULL
;
2143 UnitFileChange
*changes
= NULL
;
2144 unsigned n_changes
= 0;
2150 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &unit
);
2152 return log_error_errno(r
, "Failed to mangle unit name: %m");
2154 if (install_client_side()) {
2155 r
= unit_file_set_default(arg_scope
, UNIT_FILE_FORCE
, arg_root
, unit
, &changes
, &n_changes
);
2156 unit_file_dump_changes(r
, "set default", changes
, n_changes
, arg_quiet
);
2161 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2162 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2165 polkit_agent_open_maybe();
2167 r
= acquire_bus(BUS_MANAGER
, &bus
);
2171 r
= sd_bus_call_method(
2173 "org.freedesktop.systemd1",
2174 "/org/freedesktop/systemd1",
2175 "org.freedesktop.systemd1.Manager",
2181 return log_error_errno(r
, "Failed to set default target: %s", bus_error_message(&error
, r
));
2183 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
2187 /* Try to reload if enabled */
2189 r
= daemon_reload(argc
, argv
, userdata
);
2195 unit_file_changes_free(changes
, n_changes
);
2200 static int output_waiting_jobs(sd_bus
*bus
, uint32_t id
, const char *method
, const char *prefix
) {
2201 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2202 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2203 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2209 r
= sd_bus_call_method(
2211 "org.freedesktop.systemd1",
2212 "/org/freedesktop/systemd1",
2213 "org.freedesktop.systemd1.Manager",
2219 return log_debug_errno(r
, "Failed to get waiting jobs for job %" PRIu32
, id
);
2221 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2223 return bus_log_parse_error(r
);
2225 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &other_id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0)
2226 printf("%s %u (%s/%s)\n", prefix
, other_id
, name
, type
);
2228 return bus_log_parse_error(r
);
2230 r
= sd_bus_message_exit_container(reply
);
2232 return bus_log_parse_error(r
);
2239 const char *name
, *type
, *state
;
2242 static void output_jobs_list(sd_bus
*bus
, const struct job_info
* jobs
, unsigned n
, bool skipped
) {
2243 unsigned id_len
, unit_len
, type_len
, state_len
;
2244 const struct job_info
*j
;
2245 const char *on
, *off
;
2246 bool shorten
= false;
2248 assert(n
== 0 || jobs
);
2251 if (!arg_no_legend
) {
2252 on
= ansi_highlight_green();
2253 off
= ansi_normal();
2255 printf("%sNo jobs %s.%s\n", on
, skipped
? "listed" : "running", off
);
2260 pager_open(arg_no_pager
, false);
2262 id_len
= strlen("JOB");
2263 unit_len
= strlen("UNIT");
2264 type_len
= strlen("TYPE");
2265 state_len
= strlen("STATE");
2267 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2268 uint32_t id
= j
->id
;
2269 assert(j
->name
&& j
->type
&& j
->state
);
2271 id_len
= MAX(id_len
, DECIMAL_STR_WIDTH(id
));
2272 unit_len
= MAX(unit_len
, strlen(j
->name
));
2273 type_len
= MAX(type_len
, strlen(j
->type
));
2274 state_len
= MAX(state_len
, strlen(j
->state
));
2277 if (!arg_full
&& id_len
+ 1 + unit_len
+ type_len
+ 1 + state_len
> columns()) {
2278 unit_len
= MAX(33u, columns() - id_len
- type_len
- state_len
- 3);
2283 printf("%*s %-*s %-*s %-*s\n",
2287 state_len
, "STATE");
2289 for (j
= jobs
; j
< jobs
+ n
; j
++) {
2290 _cleanup_free_
char *e
= NULL
;
2292 if (streq(j
->state
, "running")) {
2293 on
= ansi_highlight();
2294 off
= ansi_normal();
2298 e
= shorten
? ellipsize(j
->name
, unit_len
, 33) : NULL
;
2299 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2301 on
, unit_len
, e
? e
: j
->name
, off
,
2303 on
, state_len
, j
->state
, off
);
2306 output_waiting_jobs(bus
, j
->id
, "GetJobAfter", "\twaiting for job");
2307 if (arg_jobs_before
)
2308 output_waiting_jobs(bus
, j
->id
, "GetJobBefore", "\tblocking job");
2311 if (!arg_no_legend
) {
2312 on
= ansi_highlight();
2313 off
= ansi_normal();
2315 printf("\n%s%u jobs listed%s.\n", on
, n
, off
);
2319 static bool output_show_job(struct job_info
*job
, char **patterns
) {
2320 return strv_fnmatch_or_empty(patterns
, job
->name
, FNM_NOESCAPE
);
2323 static int list_jobs(int argc
, char *argv
[], void *userdata
) {
2324 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2325 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2326 const char *name
, *type
, *state
, *job_path
, *unit_path
;
2327 _cleanup_free_
struct job_info
*jobs
= NULL
;
2333 bool skipped
= false;
2335 r
= acquire_bus(BUS_MANAGER
, &bus
);
2339 r
= sd_bus_call_method(
2341 "org.freedesktop.systemd1",
2342 "/org/freedesktop/systemd1",
2343 "org.freedesktop.systemd1.Manager",
2349 return log_error_errno(r
, "Failed to list jobs: %s", bus_error_message(&error
, r
));
2351 r
= sd_bus_message_enter_container(reply
, 'a', "(usssoo)");
2353 return bus_log_parse_error(r
);
2355 while ((r
= sd_bus_message_read(reply
, "(usssoo)", &id
, &name
, &type
, &state
, &job_path
, &unit_path
)) > 0) {
2356 struct job_info job
= { id
, name
, type
, state
};
2358 if (!output_show_job(&job
, strv_skip(argv
, 1))) {
2363 if (!GREEDY_REALLOC(jobs
, size
, c
+ 1))
2369 return bus_log_parse_error(r
);
2371 r
= sd_bus_message_exit_container(reply
);
2373 return bus_log_parse_error(r
);
2375 pager_open(arg_no_pager
, false);
2377 output_jobs_list(bus
, jobs
, c
, skipped
);
2381 static int cancel_job(int argc
, char *argv
[], void *userdata
) {
2387 return trivial_method(argc
, argv
, userdata
);
2389 r
= acquire_bus(BUS_MANAGER
, &bus
);
2393 polkit_agent_open_maybe();
2395 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
2396 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2400 q
= safe_atou32(*name
, &id
);
2402 return log_error_errno(q
, "Failed to parse job id \"%s\": %m", *name
);
2404 q
= sd_bus_call_method(
2406 "org.freedesktop.systemd1",
2407 "/org/freedesktop/systemd1",
2408 "org.freedesktop.systemd1.Manager",
2414 log_error_errno(q
, "Failed to cancel job %"PRIu32
": %s", id
, bus_error_message(&error
, q
));
2423 static int need_daemon_reload(sd_bus
*bus
, const char *unit
) {
2424 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2428 /* We ignore all errors here, since this is used to show a
2431 /* We don't use unit_dbus_path_from_name() directly since we
2432 * don't want to load the unit if it isn't loaded. */
2434 r
= sd_bus_call_method(
2436 "org.freedesktop.systemd1",
2437 "/org/freedesktop/systemd1",
2438 "org.freedesktop.systemd1.Manager",
2446 r
= sd_bus_message_read(reply
, "o", &path
);
2450 r
= sd_bus_get_property_trivial(
2452 "org.freedesktop.systemd1",
2454 "org.freedesktop.systemd1.Unit",
2464 static void warn_unit_file_changed(const char *name
) {
2467 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2468 ansi_highlight_red(),
2471 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user");
2474 static int unit_file_find_path(LookupPaths
*lp
, const char *unit_name
, char **unit_path
) {
2480 STRV_FOREACH(p
, lp
->search_path
) {
2481 _cleanup_free_
char *path
= NULL
, *lpath
= NULL
;
2484 path
= path_join(NULL
, *p
, unit_name
);
2488 r
= chase_symlinks(path
, arg_root
, 0, &lpath
);
2494 return log_error_errno(r
, "Failed to access path '%s': %m", path
);
2506 static int unit_find_template_path(
2507 const char *unit_name
,
2509 char **fragment_path
,
2512 _cleanup_free_
char *_template
= NULL
;
2515 /* Returns 1 if a fragment was found, 0 if not found, negative on error. */
2517 r
= unit_file_find_path(lp
, unit_name
, fragment_path
);
2519 return r
; /* error or found a real unit */
2521 r
= unit_name_template(unit_name
, &_template
);
2523 return 0; /* not a template, does not exist */
2525 return log_error_errno(r
, "Failed to determine template name: %m");
2527 r
= unit_file_find_path(lp
, _template
, fragment_path
);
2532 *template = _template
;
2538 static int unit_find_paths(
2540 const char *unit_name
,
2542 char **fragment_path
,
2543 char ***dropin_paths
) {
2545 _cleanup_free_
char *path
= NULL
;
2546 _cleanup_strv_free_
char **dropins
= NULL
;
2550 * Finds where the unit is defined on disk. Returns 0 if the unit
2551 * is not found. Returns 1 if it is found, and sets
2552 * - the path to the unit in *path, if it exists on disk,
2553 * - and a strv of existing drop-ins in *dropins,
2554 * if the arg is not NULL and any dropins were found.
2558 assert(fragment_path
);
2561 if (!install_client_side() && !unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
2562 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2563 _cleanup_free_
char *unit
= NULL
;
2565 unit
= unit_dbus_path_from_name(unit_name
);
2569 r
= sd_bus_get_property_string(
2571 "org.freedesktop.systemd1",
2573 "org.freedesktop.systemd1.Unit",
2578 return log_error_errno(r
, "Failed to get FragmentPath: %s", bus_error_message(&error
, r
));
2581 r
= sd_bus_get_property_strv(
2583 "org.freedesktop.systemd1",
2585 "org.freedesktop.systemd1.Unit",
2590 return log_error_errno(r
, "Failed to get DropInPaths: %s", bus_error_message(&error
, r
));
2593 _cleanup_set_free_ Set
*names
= NULL
;
2594 _cleanup_free_
char *template = NULL
;
2596 names
= set_new(NULL
);
2600 r
= unit_find_template_path(unit_name
, lp
, &path
, &template);
2605 /* We found the unit file. If we followed symlinks, this name might be
2606 * different then the unit_name with started with. Look for dropins matching
2607 * that "final" name. */
2608 r
= set_put(names
, basename(path
));
2610 /* No unit file, let's look for dropins matching the original name.
2611 * systemd has fairly complicated rules (based on unit type and provenience),
2612 * which units are allowed not to have the main unit file. We err on the
2613 * side of including too many files, and always try to load dropins. */
2614 r
= set_put(names
, unit_name
);
2616 /* The cases where we allow a unit to exist without the main file are
2617 * never valid for templates. Don't try to load dropins in this case. */
2621 return log_error_errno(r
, "Failed to add unit name: %m");
2624 r
= unit_file_find_dropin_conf_paths(arg_root
, lp
->search_path
,
2625 NULL
, names
, &dropins
);
2633 if (!isempty(path
)) {
2634 *fragment_path
= path
;
2639 if (dropin_paths
&& !strv_isempty(dropins
)) {
2640 *dropin_paths
= dropins
;
2645 if (r
== 0 && !arg_force
)
2646 log_error("No files found for %s.", unit_name
);
2651 static int get_state_one_unit(sd_bus
*bus
, const char *name
, UnitActiveState
*active_state
) {
2652 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2653 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2654 _cleanup_free_
char *buf
= NULL
;
2655 UnitActiveState state
;
2660 assert(active_state
);
2662 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2664 r
= sd_bus_call_method(
2666 "org.freedesktop.systemd1",
2667 "/org/freedesktop/systemd1",
2668 "org.freedesktop.systemd1.Manager",
2674 if (!sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
))
2675 return log_error_errno(r
, "Failed to retrieve unit: %s", bus_error_message(&error
, r
));
2677 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2678 * considered inactive. */
2679 state
= UNIT_INACTIVE
;
2682 r
= sd_bus_message_read(reply
, "o", &path
);
2684 return bus_log_parse_error(r
);
2686 r
= sd_bus_get_property_string(
2688 "org.freedesktop.systemd1",
2690 "org.freedesktop.systemd1.Unit",
2695 return log_error_errno(r
, "Failed to retrieve unit state: %s", bus_error_message(&error
, r
));
2697 state
= unit_active_state_from_string(buf
);
2698 if (state
== _UNIT_ACTIVE_STATE_INVALID
) {
2699 log_error("Invalid unit state '%s' for: %s", buf
, name
);
2704 *active_state
= state
;
2708 static int check_triggering_units(
2712 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
2713 _cleanup_free_
char *path
= NULL
, *n
= NULL
, *load_state
= NULL
;
2714 _cleanup_strv_free_
char **triggered_by
= NULL
;
2715 bool print_warning_label
= true;
2716 UnitActiveState active_state
;
2720 r
= unit_name_mangle(name
, UNIT_NAME_NOGLOB
, &n
);
2722 return log_error_errno(r
, "Failed to mangle unit name: %m");
2724 path
= unit_dbus_path_from_name(n
);
2728 r
= sd_bus_get_property_string(
2730 "org.freedesktop.systemd1",
2732 "org.freedesktop.systemd1.Unit",
2737 return log_error_errno(r
, "Failed to get load state of %s: %s", n
, bus_error_message(&error
, r
));
2739 if (streq(load_state
, "masked"))
2742 r
= sd_bus_get_property_strv(
2744 "org.freedesktop.systemd1",
2746 "org.freedesktop.systemd1.Unit",
2751 return log_error_errno(r
, "Failed to get triggered by array of %s: %s", n
, bus_error_message(&error
, r
));
2753 STRV_FOREACH(i
, triggered_by
) {
2754 r
= get_state_one_unit(bus
, *i
, &active_state
);
2758 if (!IN_SET(active_state
, UNIT_ACTIVE
, UNIT_RELOADING
))
2761 if (print_warning_label
) {
2762 log_warning("Warning: Stopping %s, but it can still be activated by:", n
);
2763 print_warning_label
= false;
2766 log_warning(" %s", *i
);
2772 static const struct {
2775 } unit_actions
[] = {
2776 { "start", "StartUnit" },
2777 { "stop", "StopUnit" },
2778 { "condstop", "StopUnit" },
2779 { "reload", "ReloadUnit" },
2780 { "restart", "RestartUnit" },
2781 { "try-restart", "TryRestartUnit" },
2782 { "condrestart", "TryRestartUnit" },
2783 { "reload-or-restart", "ReloadOrRestartUnit" },
2784 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2785 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2786 { "condreload", "ReloadOrTryRestartUnit" },
2787 { "force-reload", "ReloadOrTryRestartUnit" }
2790 static const char *verb_to_method(const char *verb
) {
2793 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2794 if (streq_ptr(unit_actions
[i
].verb
, verb
))
2795 return unit_actions
[i
].method
;
2800 static const char *method_to_verb(const char *method
) {
2803 for (i
= 0; i
< ELEMENTSOF(unit_actions
); i
++)
2804 if (streq_ptr(unit_actions
[i
].method
, method
))
2805 return unit_actions
[i
].verb
;
2817 static void wait_context_free(WaitContext
*c
) {
2818 c
->match
= sd_bus_slot_unref(c
->match
);
2819 c
->event
= sd_event_unref(c
->event
);
2820 c
->unit_paths
= set_free_free(c
->unit_paths
);
2823 static int on_properties_changed(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
2824 WaitContext
*c
= userdata
;
2828 path
= sd_bus_message_get_path(m
);
2829 if (!set_contains(c
->unit_paths
, path
))
2832 /* Check if ActiveState changed to inactive/failed */
2833 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2834 r
= sd_bus_message_skip(m
, "s");
2836 return bus_log_parse_error(r
);
2838 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "{sv}");
2840 return bus_log_parse_error(r
);
2842 while ((r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
2845 r
= sd_bus_message_read(m
, "s", &s
);
2847 return bus_log_parse_error(r
);
2849 if (streq(s
, "ActiveState")) {
2852 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_VARIANT
, "s");
2854 return bus_log_parse_error(r
);
2856 r
= sd_bus_message_read(m
, "s", &s
);
2858 return bus_log_parse_error(r
);
2860 is_failed
= streq(s
, "failed");
2861 if (streq(s
, "inactive") || is_failed
) {
2862 log_debug("%s became %s, dropping from --wait tracking", path
, s
);
2863 free(set_remove(c
->unit_paths
, path
));
2864 c
->any_failed
= c
->any_failed
|| is_failed
;
2866 log_debug("ActiveState on %s changed to %s", path
, s
);
2868 break; /* no need to dissect the rest of the message */
2870 /* other property */
2871 r
= sd_bus_message_skip(m
, "v");
2873 return bus_log_parse_error(r
);
2875 r
= sd_bus_message_exit_container(m
);
2877 return bus_log_parse_error(r
);
2880 return bus_log_parse_error(r
);
2882 if (set_isempty(c
->unit_paths
))
2883 sd_event_exit(c
->event
, EXIT_SUCCESS
);
2888 static int start_unit_one(
2893 sd_bus_error
*error
,
2895 WaitContext
*wait_context
) {
2897 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
2907 _cleanup_free_
char *unit_path
= NULL
;
2910 log_debug("Watching for property changes of %s", name
);
2911 r
= sd_bus_call_method(
2913 "org.freedesktop.systemd1",
2914 "/org/freedesktop/systemd1",
2915 "org.freedesktop.systemd1.Manager",
2921 return log_error_errno(r
, "Failed to RefUnit %s: %s", name
, bus_error_message(error
, r
));
2923 unit_path
= unit_dbus_path_from_name(name
);
2927 r
= set_put_strdup(wait_context
->unit_paths
, unit_path
);
2929 return log_error_errno(r
, "Failed to add unit path %s to set: %m", unit_path
);
2931 mt
= strjoina("type='signal',"
2932 "interface='org.freedesktop.DBus.Properties',"
2933 "path='", unit_path
, "',"
2934 "member='PropertiesChanged'");
2935 r
= sd_bus_add_match(bus
, &wait_context
->match
, mt
, on_properties_changed
, wait_context
);
2937 return log_error_errno(r
, "Failed to add match for PropertiesChanged signal: %m");
2940 log_debug("Calling manager for %s on %s, %s", method
, name
, mode
);
2942 r
= sd_bus_call_method(
2944 "org.freedesktop.systemd1",
2945 "/org/freedesktop/systemd1",
2946 "org.freedesktop.systemd1.Manager",
2954 /* There's always a fallback possible for legacy actions. */
2955 if (arg_action
!= ACTION_SYSTEMCTL
)
2958 verb
= method_to_verb(method
);
2960 log_error("Failed to %s %s: %s", verb
, name
, bus_error_message(error
, r
));
2962 if (!sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) &&
2963 !sd_bus_error_has_name(error
, BUS_ERROR_UNIT_MASKED
))
2964 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2965 arg_scope
== UNIT_FILE_SYSTEM
? "system" : "user",
2966 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
2967 name
[0] == '-' ? " --" : "",
2973 r
= sd_bus_message_read(reply
, "o", &path
);
2975 return bus_log_parse_error(r
);
2977 if (need_daemon_reload(bus
, name
) > 0)
2978 warn_unit_file_changed(name
);
2981 log_debug("Adding %s to the set", path
);
2982 r
= bus_wait_for_jobs_add(w
, path
);
2990 static int expand_names(sd_bus
*bus
, char **names
, const char* suffix
, char ***ret
) {
2991 _cleanup_strv_free_
char **mangled
= NULL
, **globs
= NULL
;
2998 STRV_FOREACH(name
, names
) {
3002 r
= unit_name_mangle_with_suffix(*name
, UNIT_NAME_GLOB
, suffix
, &t
);
3004 r
= unit_name_mangle(*name
, UNIT_NAME_GLOB
, &t
);
3006 return log_error_errno(r
, "Failed to mangle name: %m");
3008 if (string_is_glob(t
))
3009 r
= strv_consume(&globs
, t
);
3011 r
= strv_consume(&mangled
, t
);
3016 /* Query the manager only if any of the names are a glob, since
3017 * this is fairly expensive */
3018 if (!strv_isempty(globs
)) {
3019 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3020 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
3021 size_t allocated
, n
;
3023 r
= get_unit_list(bus
, NULL
, globs
, &unit_infos
, 0, &reply
);
3027 n
= strv_length(mangled
);
3030 for (i
= 0; i
< r
; i
++) {
3031 if (!GREEDY_REALLOC(mangled
, allocated
, n
+2))
3034 mangled
[n
] = strdup(unit_infos
[i
].id
);
3038 mangled
[++n
] = NULL
;
3043 mangled
= NULL
; /* do not free */
3048 static const struct {
3052 } action_table
[_ACTION_MAX
] = {
3053 [ACTION_HALT
] = { SPECIAL_HALT_TARGET
, "halt", "replace-irreversibly" },
3054 [ACTION_POWEROFF
] = { SPECIAL_POWEROFF_TARGET
, "poweroff", "replace-irreversibly" },
3055 [ACTION_REBOOT
] = { SPECIAL_REBOOT_TARGET
, "reboot", "replace-irreversibly" },
3056 [ACTION_KEXEC
] = { SPECIAL_KEXEC_TARGET
, "kexec", "replace-irreversibly" },
3057 [ACTION_RUNLEVEL2
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3058 [ACTION_RUNLEVEL3
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3059 [ACTION_RUNLEVEL4
] = { SPECIAL_MULTI_USER_TARGET
, NULL
, "isolate" },
3060 [ACTION_RUNLEVEL5
] = { SPECIAL_GRAPHICAL_TARGET
, NULL
, "isolate" },
3061 [ACTION_RESCUE
] = { SPECIAL_RESCUE_TARGET
, "rescue", "isolate" },
3062 [ACTION_EMERGENCY
] = { SPECIAL_EMERGENCY_TARGET
, "emergency", "isolate" },
3063 [ACTION_DEFAULT
] = { SPECIAL_DEFAULT_TARGET
, "default", "isolate" },
3064 [ACTION_EXIT
] = { SPECIAL_EXIT_TARGET
, "exit", "replace-irreversibly" },
3065 [ACTION_SUSPEND
] = { SPECIAL_SUSPEND_TARGET
, "suspend", "replace-irreversibly" },
3066 [ACTION_HIBERNATE
] = { SPECIAL_HIBERNATE_TARGET
, "hibernate", "replace-irreversibly" },
3067 [ACTION_HYBRID_SLEEP
] = { SPECIAL_HYBRID_SLEEP_TARGET
, "hybrid-sleep", "replace-irreversibly" },
3070 static enum action
verb_to_action(const char *verb
) {
3073 for (i
= 0; i
< _ACTION_MAX
; i
++)
3074 if (streq_ptr(action_table
[i
].verb
, verb
))
3077 return _ACTION_INVALID
;
3080 static int start_unit(int argc
, char *argv
[], void *userdata
) {
3081 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
3082 const char *method
, *mode
, *one_name
, *suffix
= NULL
;
3083 _cleanup_strv_free_
char **names
= NULL
;
3085 _cleanup_(wait_context_free
) WaitContext wait_context
= {};
3089 if (arg_wait
&& !STR_IN_SET(argv
[0], "start", "restart")) {
3090 log_error("--wait may only be used with the 'start' or 'restart' commands.");
3094 /* we cannot do sender tracking on the private bus, so we need the full
3095 * one for RefUnit to implement --wait */
3096 r
= acquire_bus(arg_wait
? BUS_FULL
: BUS_MANAGER
, &bus
);
3100 ask_password_agent_open_if_enabled();
3101 polkit_agent_open_maybe();
3103 if (arg_action
== ACTION_SYSTEMCTL
) {
3106 action
= verb_to_action(argv
[0]);
3108 if (action
!= _ACTION_INVALID
) {
3109 method
= "StartUnit";
3110 mode
= action_table
[action
].mode
;
3111 one_name
= action_table
[action
].target
;
3113 if (streq(argv
[0], "isolate")) {
3114 method
= "StartUnit";
3119 method
= verb_to_method(argv
[0]);
3120 mode
= arg_job_mode
;
3125 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
3126 assert(action_table
[arg_action
].target
);
3127 assert(action_table
[arg_action
].mode
);
3129 method
= "StartUnit";
3130 mode
= action_table
[arg_action
].mode
;
3131 one_name
= action_table
[arg_action
].target
;
3135 names
= strv_new(one_name
, NULL
);
3137 r
= expand_names(bus
, strv_skip(argv
, 1), suffix
, &names
);
3139 return log_error_errno(r
, "Failed to expand names: %m");
3142 if (!arg_no_block
) {
3143 r
= bus_wait_for_jobs_new(bus
, &w
);
3145 return log_error_errno(r
, "Could not watch jobs: %m");
3149 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3151 wait_context
.unit_paths
= set_new(&string_hash_ops
);
3152 if (!wait_context
.unit_paths
)
3155 r
= sd_bus_call_method(
3157 "org.freedesktop.systemd1",
3158 "/org/freedesktop/systemd1",
3159 "org.freedesktop.systemd1.Manager",
3164 return log_error_errno(r
, "Failed to enable subscription: %s", bus_error_message(&error
, r
));
3165 r
= sd_event_default(&wait_context
.event
);
3167 return log_error_errno(r
, "Failed to allocate event loop: %m");
3168 r
= sd_bus_attach_event(bus
, wait_context
.event
, 0);
3170 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
3173 STRV_FOREACH(name
, names
) {
3174 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3177 q
= start_unit_one(bus
, method
, *name
, mode
, &error
, w
, arg_wait
? &wait_context
: NULL
);
3178 if (r
>= 0 && q
< 0)
3179 r
= translate_bus_error_to_exit_status(q
, &error
);
3182 if (!arg_no_block
) {
3183 int q
, arg_count
= 0;
3184 const char* extra_args
[4] = {};
3186 if (arg_scope
!= UNIT_FILE_SYSTEM
)
3187 extra_args
[arg_count
++] = "--user";
3189 assert(IN_SET(arg_transport
, BUS_TRANSPORT_LOCAL
, BUS_TRANSPORT_REMOTE
, BUS_TRANSPORT_MACHINE
));
3190 if (arg_transport
== BUS_TRANSPORT_REMOTE
) {
3191 extra_args
[arg_count
++] = "-H";
3192 extra_args
[arg_count
++] = arg_host
;
3193 } else if (arg_transport
== BUS_TRANSPORT_MACHINE
) {
3194 extra_args
[arg_count
++] = "-M";
3195 extra_args
[arg_count
++] = arg_host
;
3198 q
= bus_wait_for_jobs(w
, arg_quiet
, extra_args
);
3202 /* When stopping units, warn if they can still be triggered by
3203 * another active unit (socket, path, timer) */
3204 if (!arg_quiet
&& streq(method
, "StopUnit"))
3205 STRV_FOREACH(name
, names
)
3206 check_triggering_units(bus
, *name
);
3209 if (r
>= 0 && arg_wait
) {
3211 q
= sd_event_loop(wait_context
.event
);
3213 return log_error_errno(q
, "Failed to run event loop: %m");
3214 if (wait_context
.any_failed
)
3222 static int logind_set_wall_message(void) {
3223 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3225 _cleanup_free_
char *m
= NULL
;
3228 r
= acquire_bus(BUS_FULL
, &bus
);
3232 m
= strv_join(arg_wall
, " ");
3236 r
= sd_bus_call_method(
3238 "org.freedesktop.login1",
3239 "/org/freedesktop/login1",
3240 "org.freedesktop.login1.Manager",
3249 return log_warning_errno(r
, "Failed to set wall message, ignoring: %s", bus_error_message(&error
, r
));
3254 /* Ask systemd-logind, which might grant access to unprivileged users
3255 * through PolicyKit */
3256 static int logind_reboot(enum action a
) {
3258 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3259 const char *method
, *description
;
3263 r
= acquire_bus(BUS_FULL
, &bus
);
3269 case ACTION_POWEROFF
:
3270 method
= "PowerOff";
3271 description
= "power off system";
3276 description
= "reboot system";
3281 description
= "halt system";
3284 case ACTION_SUSPEND
:
3286 description
= "suspend system";
3289 case ACTION_HIBERNATE
:
3290 method
= "Hibernate";
3291 description
= "hibernate system";
3294 case ACTION_HYBRID_SLEEP
:
3295 method
= "HybridSleep";
3296 description
= "put system into hybrid sleep";
3303 polkit_agent_open_maybe();
3304 (void) logind_set_wall_message();
3306 r
= sd_bus_call_method(
3308 "org.freedesktop.login1",
3309 "/org/freedesktop/login1",
3310 "org.freedesktop.login1.Manager",
3314 "b", arg_ask_password
);
3316 return log_error_errno(r
, "Failed to %s via logind: %s", description
, bus_error_message(&error
, r
));
3324 static int logind_check_inhibitors(enum action a
) {
3326 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
3327 _cleanup_strv_free_
char **sessions
= NULL
;
3328 const char *what
, *who
, *why
, *mode
;
3335 if (arg_ignore_inhibitors
|| arg_force
> 0)
3347 if (arg_transport
!= BUS_TRANSPORT_LOCAL
)
3350 r
= acquire_bus(BUS_FULL
, &bus
);
3354 r
= sd_bus_call_method(
3356 "org.freedesktop.login1",
3357 "/org/freedesktop/login1",
3358 "org.freedesktop.login1.Manager",
3364 /* If logind is not around, then there are no inhibitors... */
3367 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "(ssssuu)");
3369 return bus_log_parse_error(r
);
3371 while ((r
= sd_bus_message_read(reply
, "(ssssuu)", &what
, &who
, &why
, &mode
, &uid
, &pid
)) > 0) {
3372 _cleanup_free_
char *comm
= NULL
, *user
= NULL
;
3373 _cleanup_strv_free_
char **sv
= NULL
;
3375 if (!streq(mode
, "block"))
3378 sv
= strv_split(what
, ":");
3382 if (!pid_is_valid((pid_t
) pid
)) {
3383 log_error("Invalid PID "PID_FMT
".", (pid_t
) pid
);
3387 if (!strv_contains(sv
,
3392 ACTION_KEXEC
) ? "shutdown" : "sleep"))
3395 get_process_comm(pid
, &comm
);
3396 user
= uid_to_name(uid
);
3398 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT
" \"%s\", user %s), reason is \"%s\".",
3399 who
, (pid_t
) pid
, strna(comm
), strna(user
), why
);
3404 return bus_log_parse_error(r
);
3406 r
= sd_bus_message_exit_container(reply
);
3408 return bus_log_parse_error(r
);
3410 /* Check for current sessions */
3411 sd_get_sessions(&sessions
);
3412 STRV_FOREACH(s
, sessions
) {
3413 _cleanup_free_
char *type
= NULL
, *tty
= NULL
, *seat
= NULL
, *user
= NULL
, *service
= NULL
, *class = NULL
;
3415 if (sd_session_get_uid(*s
, &uid
) < 0 || uid
== getuid())
3418 if (sd_session_get_class(*s
, &class) < 0 || !streq(class, "user"))
3421 if (sd_session_get_type(*s
, &type
) < 0 || !STR_IN_SET(type
, "x11", "wayland", "tty", "mir"))
3424 sd_session_get_tty(*s
, &tty
);
3425 sd_session_get_seat(*s
, &seat
);
3426 sd_session_get_service(*s
, &service
);
3427 user
= uid_to_name(uid
);
3429 log_warning("User %s is logged in on %s.", strna(user
), isempty(tty
) ? (isempty(seat
) ? strna(service
) : seat
) : tty
);
3436 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3437 action_table
[a
].verb
);
3445 static int logind_prepare_firmware_setup(void) {
3447 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3451 r
= acquire_bus(BUS_FULL
, &bus
);
3455 r
= sd_bus_call_method(
3457 "org.freedesktop.login1",
3458 "/org/freedesktop/login1",
3459 "org.freedesktop.login1.Manager",
3460 "SetRebootToFirmwareSetup",
3465 return log_error_errno(r
, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error
, r
));
3469 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3474 static int prepare_firmware_setup(void) {
3477 if (!arg_firmware_setup
)
3480 if (arg_transport
== BUS_TRANSPORT_LOCAL
) {
3482 r
= efi_set_reboot_to_firmware(true);
3484 log_debug_errno(r
, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3489 return logind_prepare_firmware_setup();
3492 static int set_exit_code(uint8_t code
) {
3493 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3497 r
= acquire_bus(BUS_MANAGER
, &bus
);
3501 r
= sd_bus_call_method(
3503 "org.freedesktop.systemd1",
3504 "/org/freedesktop/systemd1",
3505 "org.freedesktop.systemd1.Manager",
3511 return log_error_errno(r
, "Failed to set exit code: %s", bus_error_message(&error
, r
));
3516 static int start_special(int argc
, char *argv
[], void *userdata
) {
3519 bool termination_action
; /* an action that terminates the manager,
3520 * can be performed also by signal. */
3524 a
= verb_to_action(argv
[0]);
3526 r
= logind_check_inhibitors(a
);
3530 if (arg_force
>= 2 && geteuid() != 0) {
3531 log_error("Must be root.");
3535 r
= prepare_firmware_setup();
3539 if (a
== ACTION_REBOOT
&& argc
> 1) {
3540 r
= update_reboot_parameter_and_warn(argv
[1]);
3544 } else if (a
== ACTION_EXIT
&& argc
> 1) {
3547 /* If the exit code is not given on the command line,
3548 * don't reset it to zero: just keep it as it might
3549 * have been set previously. */
3551 r
= safe_atou8(argv
[1], &code
);
3553 return log_error_errno(r
, "Invalid exit code.");
3555 r
= set_exit_code(code
);
3560 termination_action
= IN_SET(a
,
3564 if (termination_action
&& arg_force
>= 2)
3567 if (arg_force
>= 1 &&
3568 (termination_action
|| IN_SET(a
, ACTION_KEXEC
, ACTION_EXIT
)))
3569 r
= trivial_method(argc
, argv
, userdata
);
3571 /* First try logind, to allow authentication with polkit */
3578 ACTION_HYBRID_SLEEP
)) {
3580 r
= logind_reboot(a
);
3583 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
3584 /* requested operation is not supported or already in progress */
3587 /* On all other errors, try low-level operation. In order to minimize the difference between
3588 * operation with and without logind, we explicitly enable non-blocking mode for this, as
3589 * logind's shutdown operations are always non-blocking. */
3591 arg_no_block
= true;
3593 } else if (IN_SET(a
, ACTION_EXIT
, ACTION_KEXEC
))
3594 /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them
3595 * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */
3596 arg_no_block
= true;
3598 r
= start_unit(argc
, argv
, userdata
);
3601 if (termination_action
&& arg_force
< 2 &&
3602 IN_SET(r
, -ENOENT
, -ETIMEDOUT
))
3603 log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1).");
3608 static int start_system_special(int argc
, char *argv
[], void *userdata
) {
3609 /* Like start_special above, but raises an error when running in user mode */
3611 if (arg_scope
!= UNIT_FILE_SYSTEM
) {
3612 log_error("Bad action for %s mode.",
3613 arg_scope
== UNIT_FILE_GLOBAL
? "--global" : "--user");
3617 return start_special(argc
, argv
, userdata
);
3620 static int check_unit_generic(int code
, const UnitActiveState good_states
[], int nb_states
, char **args
) {
3621 _cleanup_strv_free_
char **names
= NULL
;
3622 UnitActiveState active_state
;
3628 r
= acquire_bus(BUS_MANAGER
, &bus
);
3632 r
= expand_names(bus
, args
, NULL
, &names
);
3634 return log_error_errno(r
, "Failed to expand names: %m");
3636 STRV_FOREACH(name
, names
) {
3637 r
= get_state_one_unit(bus
, *name
, &active_state
);
3642 puts(unit_active_state_to_string(active_state
));
3644 for (i
= 0; i
< nb_states
; ++i
)
3645 if (good_states
[i
] == active_state
)
3649 /* use the given return code for the case that we won't find
3650 * any unit which matches the list */
3651 return found
? 0 : code
;
3654 static int check_unit_active(int argc
, char *argv
[], void *userdata
) {
3655 const UnitActiveState states
[] = { UNIT_ACTIVE
, UNIT_RELOADING
};
3656 /* According to LSB: 3, "program is not running" */
3657 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3660 static int check_unit_failed(int argc
, char *argv
[], void *userdata
) {
3661 const UnitActiveState states
[] = { UNIT_FAILED
};
3662 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS
, states
, ELEMENTSOF(states
), strv_skip(argv
, 1));
3665 static int kill_unit(int argc
, char *argv
[], void *userdata
) {
3666 _cleanup_strv_free_
char **names
= NULL
;
3667 char *kill_who
= NULL
, **name
;
3671 r
= acquire_bus(BUS_MANAGER
, &bus
);
3675 polkit_agent_open_maybe();
3678 arg_kill_who
= "all";
3680 /* --fail was specified */
3681 if (streq(arg_job_mode
, "fail"))
3682 kill_who
= strjoina(arg_kill_who
, "-fail");
3684 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
3686 return log_error_errno(r
, "Failed to expand names: %m");
3688 STRV_FOREACH(name
, names
) {
3689 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
3691 q
= sd_bus_call_method(
3693 "org.freedesktop.systemd1",
3694 "/org/freedesktop/systemd1",
3695 "org.freedesktop.systemd1.Manager",
3699 "ssi", *name
, kill_who
? kill_who
: arg_kill_who
, arg_signal
);
3701 log_error_errno(q
, "Failed to kill unit %s: %s", *name
, bus_error_message(&error
, q
));
3710 typedef struct ExecStatusInfo
{
3718 usec_t start_timestamp
;
3719 usec_t exit_timestamp
;
3724 LIST_FIELDS(struct ExecStatusInfo
, exec
);
3727 static void exec_status_info_free(ExecStatusInfo
*i
) {
3736 static int exec_status_info_deserialize(sd_bus_message
*m
, ExecStatusInfo
*i
) {
3737 uint64_t start_timestamp
, exit_timestamp
, start_timestamp_monotonic
, exit_timestamp_monotonic
;
3740 int32_t code
, status
;
3746 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_STRUCT
, "sasbttttuii");
3748 return bus_log_parse_error(r
);
3752 r
= sd_bus_message_read(m
, "s", &path
);
3754 return bus_log_parse_error(r
);
3756 i
->path
= strdup(path
);
3760 r
= sd_bus_message_read_strv(m
, &i
->argv
);
3762 return bus_log_parse_error(r
);
3764 r
= sd_bus_message_read(m
,
3767 &start_timestamp
, &start_timestamp_monotonic
,
3768 &exit_timestamp
, &exit_timestamp_monotonic
,
3772 return bus_log_parse_error(r
);
3775 i
->start_timestamp
= (usec_t
) start_timestamp
;
3776 i
->exit_timestamp
= (usec_t
) exit_timestamp
;
3777 i
->pid
= (pid_t
) pid
;
3781 r
= sd_bus_message_exit_container(m
);
3783 return bus_log_parse_error(r
);
3788 typedef struct UnitCondition
{
3795 LIST_FIELDS(struct UnitCondition
, conditions
);
3798 static void unit_condition_free(UnitCondition
*c
) {
3807 DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition
*, unit_condition_free
);
3809 typedef struct UnitStatusInfo
{
3811 const char *load_state
;
3812 const char *active_state
;
3813 const char *sub_state
;
3814 const char *unit_file_state
;
3815 const char *unit_file_preset
;
3817 const char *description
;
3818 const char *following
;
3820 char **documentation
;
3822 const char *fragment_path
;
3823 const char *source_path
;
3824 const char *control_group
;
3826 char **dropin_paths
;
3828 const char *load_error
;
3831 usec_t inactive_exit_timestamp
;
3832 usec_t inactive_exit_timestamp_monotonic
;
3833 usec_t active_enter_timestamp
;
3834 usec_t active_exit_timestamp
;
3835 usec_t inactive_enter_timestamp
;
3837 bool need_daemon_reload
;
3843 const char *status_text
;
3844 const char *pid_file
;
3848 usec_t start_timestamp
;
3849 usec_t exit_timestamp
;
3851 int exit_code
, exit_status
;
3853 usec_t condition_timestamp
;
3854 bool condition_result
;
3855 LIST_HEAD(UnitCondition
, conditions
);
3857 usec_t assert_timestamp
;
3859 bool failed_assert_trigger
;
3860 bool failed_assert_negate
;
3861 const char *failed_assert
;
3862 const char *failed_assert_parameter
;
3863 usec_t next_elapse_real
;
3864 usec_t next_elapse_monotonic
;
3867 unsigned n_accepted
;
3868 unsigned n_connections
;
3871 /* Pairs of type, path */
3875 const char *sysfs_path
;
3877 /* Mount, Automount */
3884 uint64_t memory_current
;
3885 uint64_t memory_low
;
3886 uint64_t memory_high
;
3887 uint64_t memory_max
;
3888 uint64_t memory_swap_max
;
3889 uint64_t memory_limit
;
3890 uint64_t cpu_usage_nsec
;
3891 uint64_t tasks_current
;
3894 uint64_t ip_ingress_bytes
;
3895 uint64_t ip_egress_bytes
;
3897 LIST_HEAD(ExecStatusInfo
, exec
);
3900 static void unit_status_info_free(UnitStatusInfo
*info
) {
3904 strv_free(info
->documentation
);
3905 strv_free(info
->dropin_paths
);
3906 strv_free(info
->listen
);
3908 while ((c
= info
->conditions
)) {
3909 LIST_REMOVE(conditions
, info
->conditions
, c
);
3910 unit_condition_free(c
);
3913 while ((p
= info
->exec
)) {
3914 LIST_REMOVE(exec
, info
->exec
, p
);
3915 exec_status_info_free(p
);
3919 static void print_status_info(
3925 const char *active_on
, *active_off
, *on
, *off
, *ss
;
3927 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], *s1
;
3928 char since2
[FORMAT_TIMESTAMP_MAX
], *s2
;
3935 /* This shows pretty information about a unit. See
3936 * print_property() for a low-level property printer */
3938 if (streq_ptr(i
->active_state
, "failed")) {
3939 active_on
= ansi_highlight_red();
3940 active_off
= ansi_normal();
3941 } else if (STRPTR_IN_SET(i
->active_state
, "active", "reloading")) {
3942 active_on
= ansi_highlight_green();
3943 active_off
= ansi_normal();
3945 active_on
= active_off
= "";
3947 printf("%s%s%s %s", active_on
, special_glyph(BLACK_CIRCLE
), active_off
, strna(i
->id
));
3949 if (i
->description
&& !streq_ptr(i
->id
, i
->description
))
3950 printf(" - %s", i
->description
);
3955 printf(" Follow: unit currently follows state of %s\n", i
->following
);
3957 if (streq_ptr(i
->load_state
, "error")) {
3958 on
= ansi_highlight_red();
3959 off
= ansi_normal();
3963 path
= i
->source_path
? i
->source_path
: i
->fragment_path
;
3965 if (i
->load_error
!= 0)
3966 printf(" Loaded: %s%s%s (Reason: %s)\n",
3967 on
, strna(i
->load_state
), off
, i
->load_error
);
3968 else if (path
&& !isempty(i
->unit_file_state
) && !isempty(i
->unit_file_preset
))
3969 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3970 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
, i
->unit_file_preset
);
3971 else if (path
&& !isempty(i
->unit_file_state
))
3972 printf(" Loaded: %s%s%s (%s; %s)\n",
3973 on
, strna(i
->load_state
), off
, path
, i
->unit_file_state
);
3975 printf(" Loaded: %s%s%s (%s)\n",
3976 on
, strna(i
->load_state
), off
, path
);
3978 printf(" Loaded: %s%s%s\n",
3979 on
, strna(i
->load_state
), off
);
3982 printf("Transient: yes\n");
3984 if (!strv_isempty(i
->dropin_paths
)) {
3985 _cleanup_free_
char *dir
= NULL
;
3989 STRV_FOREACH(dropin
, i
->dropin_paths
) {
3990 if (! dir
|| last
) {
3991 printf(dir
? " " : " Drop-In: ");
3995 dir
= dirname_malloc(*dropin
);
4001 printf("%s\n %s", dir
,
4002 special_glyph(TREE_RIGHT
));
4005 last
= ! (*(dropin
+ 1) && startswith(*(dropin
+ 1), dir
));
4007 printf("%s%s", basename(*dropin
), last
? "\n" : ", ");
4011 ss
= streq_ptr(i
->active_state
, i
->sub_state
) ? NULL
: i
->sub_state
;
4013 printf(" Active: %s%s (%s)%s",
4014 active_on
, strna(i
->active_state
), ss
, active_off
);
4016 printf(" Active: %s%s%s",
4017 active_on
, strna(i
->active_state
), active_off
);
4019 if (!isempty(i
->result
) && !streq(i
->result
, "success"))
4020 printf(" (Result: %s)", i
->result
);
4022 timestamp
= STRPTR_IN_SET(i
->active_state
, "active", "reloading") ? i
->active_enter_timestamp
:
4023 STRPTR_IN_SET(i
->active_state
, "inactive", "failed") ? i
->inactive_enter_timestamp
:
4024 STRPTR_IN_SET(i
->active_state
, "activating") ? i
->inactive_exit_timestamp
:
4025 i
->active_exit_timestamp
;
4027 s1
= format_timestamp_relative(since1
, sizeof(since1
), timestamp
);
4028 s2
= format_timestamp(since2
, sizeof(since2
), timestamp
);
4031 printf(" since %s; %s\n", s2
, s1
);
4033 printf(" since %s\n", s2
);
4037 if (endswith(i
->id
, ".timer")) {
4038 char tstamp1
[FORMAT_TIMESTAMP_RELATIVE_MAX
],
4039 tstamp2
[FORMAT_TIMESTAMP_MAX
];
4040 char *next_rel_time
, *next_time
;
4041 dual_timestamp nw
, next
= {i
->next_elapse_real
,
4042 i
->next_elapse_monotonic
};
4045 printf(" Trigger: ");
4047 dual_timestamp_get(&nw
);
4048 next_elapse
= calc_next_elapse(&nw
, &next
);
4049 next_rel_time
= format_timestamp_relative(tstamp1
,
4052 next_time
= format_timestamp(tstamp2
,
4056 if (next_time
&& next_rel_time
)
4057 printf("%s; %s\n", next_time
, next_rel_time
);
4062 if (!i
->condition_result
&& i
->condition_timestamp
> 0) {
4066 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->condition_timestamp
);
4067 s2
= format_timestamp(since2
, sizeof(since2
), i
->condition_timestamp
);
4069 printf("Condition: start %scondition failed%s at %s%s%s\n",
4070 ansi_highlight_yellow(), ansi_normal(),
4071 s2
, s1
? "; " : "", strempty(s1
));
4073 LIST_FOREACH(conditions
, c
, i
->conditions
)
4074 if (c
->tristate
< 0)
4077 LIST_FOREACH(conditions
, c
, i
->conditions
)
4078 if (c
->tristate
< 0)
4079 printf(" %s %s=%s%s%s was not met\n",
4080 --n
? special_glyph(TREE_BRANCH
) : special_glyph(TREE_RIGHT
),
4082 c
->trigger
? "|" : "",
4083 c
->negate
? "!" : "",
4087 if (!i
->assert_result
&& i
->assert_timestamp
> 0) {
4088 s1
= format_timestamp_relative(since1
, sizeof(since1
), i
->assert_timestamp
);
4089 s2
= format_timestamp(since2
, sizeof(since2
), i
->assert_timestamp
);
4091 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4092 ansi_highlight_red(), ansi_normal(),
4093 s2
, s1
? "; " : "", strempty(s1
));
4094 if (i
->failed_assert_trigger
)
4095 printf(" none of the trigger assertions were met\n");
4096 else if (i
->failed_assert
)
4097 printf(" %s=%s%s was not met\n",
4099 i
->failed_assert_negate
? "!" : "",
4100 i
->failed_assert_parameter
);
4104 printf(" Device: %s\n", i
->sysfs_path
);
4106 printf(" Where: %s\n", i
->where
);
4108 printf(" What: %s\n", i
->what
);
4110 STRV_FOREACH(t
, i
->documentation
)
4111 printf(" %*s %s\n", 9, t
== i
->documentation
? "Docs:" : "", *t
);
4113 STRV_FOREACH_PAIR(t
, t2
, i
->listen
)
4114 printf(" %*s %s (%s)\n", 9, t
== i
->listen
? "Listen:" : "", *t2
, *t
);
4117 printf(" Accepted: %u; Connected: %u\n", i
->n_accepted
, i
->n_connections
);
4119 LIST_FOREACH(exec
, p
, i
->exec
) {
4120 _cleanup_free_
char *argv
= NULL
;
4123 /* Only show exited processes here */
4127 argv
= strv_join(p
->argv
, " ");
4128 printf(" Process: "PID_FMT
" %s=%s ", p
->pid
, p
->name
, strna(argv
));
4130 good
= is_clean_exit(p
->code
, p
->status
, EXIT_CLEAN_DAEMON
, NULL
);
4132 on
= ansi_highlight_red();
4133 off
= ansi_normal();
4137 printf("%s(code=%s, ", on
, sigchld_code_to_string(p
->code
));
4139 if (p
->code
== CLD_EXITED
) {
4142 printf("status=%i", p
->status
);
4144 c
= exit_status_to_string(p
->status
, EXIT_STATUS_SYSTEMD
);
4149 printf("signal=%s", signal_to_string(p
->status
));
4151 printf(")%s\n", off
);
4153 if (i
->main_pid
== p
->pid
&&
4154 i
->start_timestamp
== p
->start_timestamp
&&
4155 i
->exit_timestamp
== p
->start_timestamp
)
4156 /* Let's not show this twice */
4159 if (p
->pid
== i
->control_pid
)
4163 if (i
->main_pid
> 0 || i
->control_pid
> 0) {
4164 if (i
->main_pid
> 0) {
4165 printf(" Main PID: "PID_FMT
, i
->main_pid
);
4168 _cleanup_free_
char *comm
= NULL
;
4169 (void) get_process_comm(i
->main_pid
, &comm
);
4171 printf(" (%s)", comm
);
4172 } else if (i
->exit_code
> 0) {
4173 printf(" (code=%s, ", sigchld_code_to_string(i
->exit_code
));
4175 if (i
->exit_code
== CLD_EXITED
) {
4178 printf("status=%i", i
->exit_status
);
4180 c
= exit_status_to_string(i
->exit_status
, EXIT_STATUS_SYSTEMD
);
4185 printf("signal=%s", signal_to_string(i
->exit_status
));
4190 if (i
->control_pid
> 0) {
4191 _cleanup_free_
char *c
= NULL
;
4193 if (i
->main_pid
> 0)
4194 fputs("; Control PID: ", stdout
);
4196 fputs("Cntrl PID: ", stdout
); /* if first in column, abbreviated so it fits alignment */
4198 printf(PID_FMT
, i
->control_pid
);
4200 (void) get_process_comm(i
->control_pid
, &c
);
4209 printf(" Status: \"%s\"\n", i
->status_text
);
4210 if (i
->status_errno
> 0)
4211 printf(" Error: %i (%s)\n", i
->status_errno
, strerror(i
->status_errno
));
4213 if (i
->ip_ingress_bytes
!= (uint64_t) -1 && i
->ip_egress_bytes
!= (uint64_t) -1) {
4214 char buf_in
[FORMAT_BYTES_MAX
], buf_out
[FORMAT_BYTES_MAX
];
4216 printf(" IP: %s in, %s out\n",
4217 format_bytes(buf_in
, sizeof(buf_in
), i
->ip_ingress_bytes
),
4218 format_bytes(buf_out
, sizeof(buf_out
), i
->ip_egress_bytes
));
4221 if (i
->tasks_current
!= (uint64_t) -1) {
4222 printf(" Tasks: %" PRIu64
, i
->tasks_current
);
4224 if (i
->tasks_max
!= (uint64_t) -1)
4225 printf(" (limit: %" PRIu64
")\n", i
->tasks_max
);
4230 if (i
->memory_current
!= (uint64_t) -1) {
4231 char buf
[FORMAT_BYTES_MAX
];
4233 printf(" Memory: %s", format_bytes(buf
, sizeof(buf
), i
->memory_current
));
4235 if (i
->memory_low
> 0 || i
->memory_high
!= CGROUP_LIMIT_MAX
||
4236 i
->memory_max
!= CGROUP_LIMIT_MAX
|| i
->memory_swap_max
!= CGROUP_LIMIT_MAX
||
4237 i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4238 const char *prefix
= "";
4241 if (i
->memory_low
> 0) {
4242 printf("%slow: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_low
));
4245 if (i
->memory_high
!= CGROUP_LIMIT_MAX
) {
4246 printf("%shigh: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_high
));
4249 if (i
->memory_max
!= CGROUP_LIMIT_MAX
) {
4250 printf("%smax: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_max
));
4253 if (i
->memory_swap_max
!= CGROUP_LIMIT_MAX
) {
4254 printf("%sswap max: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_swap_max
));
4257 if (i
->memory_limit
!= CGROUP_LIMIT_MAX
) {
4258 printf("%slimit: %s", prefix
, format_bytes(buf
, sizeof(buf
), i
->memory_limit
));
4266 if (i
->cpu_usage_nsec
!= (uint64_t) -1) {
4267 char buf
[FORMAT_TIMESPAN_MAX
];
4268 printf(" CPU: %s\n", format_timespan(buf
, sizeof(buf
), i
->cpu_usage_nsec
/ NSEC_PER_USEC
, USEC_PER_MSEC
));
4271 if (i
->control_group
) {
4272 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
4273 static const char prefix
[] = " ";
4276 printf(" CGroup: %s\n", i
->control_group
);
4279 if (c
> sizeof(prefix
) - 1)
4280 c
-= sizeof(prefix
) - 1;
4284 r
= unit_show_processes(bus
, i
->id
, i
->control_group
, prefix
, c
, get_output_flags(), &error
);
4289 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4291 if (i
->main_pid
> 0)
4292 extra
[k
++] = i
->main_pid
;
4294 if (i
->control_pid
> 0)
4295 extra
[k
++] = i
->control_pid
;
4297 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER
, i
->control_group
, prefix
, c
, extra
, k
, get_output_flags());
4299 log_warning_errno(r
, "Failed to dump process list, ignoring: %s", bus_error_message(&error
, r
));
4302 if (i
->id
&& arg_transport
== BUS_TRANSPORT_LOCAL
)
4303 show_journal_by_unit(
4308 i
->inactive_exit_timestamp_monotonic
,
4311 get_output_flags() | OUTPUT_BEGIN_NEWLINE
,
4312 SD_JOURNAL_LOCAL_ONLY
,
4313 arg_scope
== UNIT_FILE_SYSTEM
,
4316 if (i
->need_daemon_reload
)
4317 warn_unit_file_changed(i
->id
);
4320 static void show_unit_help(UnitStatusInfo
*i
) {
4325 if (!i
->documentation
) {
4326 log_info("Documentation for %s not known.", i
->id
);
4330 STRV_FOREACH(p
, i
->documentation
)
4331 if (startswith(*p
, "man:"))
4332 show_man_page(*p
+ 4, false);
4334 log_info("Can't show: %s", *p
);
4337 static int status_property(const char *name
, sd_bus_message
*m
, UnitStatusInfo
*i
, const char *contents
) {
4344 switch (contents
[0]) {
4346 case SD_BUS_TYPE_STRING
: {
4349 r
= sd_bus_message_read(m
, "s", &s
);
4351 return bus_log_parse_error(r
);
4354 if (streq(name
, "Id"))
4356 else if (streq(name
, "LoadState"))
4358 else if (streq(name
, "ActiveState"))
4359 i
->active_state
= s
;
4360 else if (streq(name
, "SubState"))
4362 else if (streq(name
, "Description"))
4364 else if (streq(name
, "FragmentPath"))
4365 i
->fragment_path
= s
;
4366 else if (streq(name
, "SourcePath"))
4369 else if (streq(name
, "DefaultControlGroup")) {
4371 e
= startswith(s
, SYSTEMD_CGROUP_CONTROLLER
":");
4373 i
->control_group
= e
;
4376 else if (streq(name
, "ControlGroup"))
4377 i
->control_group
= s
;
4378 else if (streq(name
, "StatusText"))
4380 else if (streq(name
, "PIDFile"))
4382 else if (streq(name
, "SysFSPath"))
4384 else if (streq(name
, "Where"))
4386 else if (streq(name
, "What"))
4388 else if (streq(name
, "Following"))
4390 else if (streq(name
, "UnitFileState"))
4391 i
->unit_file_state
= s
;
4392 else if (streq(name
, "UnitFilePreset"))
4393 i
->unit_file_preset
= s
;
4394 else if (streq(name
, "Result"))
4401 case SD_BUS_TYPE_BOOLEAN
: {
4404 r
= sd_bus_message_read(m
, "b", &b
);
4406 return bus_log_parse_error(r
);
4408 if (streq(name
, "Accept"))
4410 else if (streq(name
, "NeedDaemonReload"))
4411 i
->need_daemon_reload
= b
;
4412 else if (streq(name
, "ConditionResult"))
4413 i
->condition_result
= b
;
4414 else if (streq(name
, "AssertResult"))
4415 i
->assert_result
= b
;
4416 else if (streq(name
, "Transient"))
4422 case SD_BUS_TYPE_UINT32
: {
4425 r
= sd_bus_message_read(m
, "u", &u
);
4427 return bus_log_parse_error(r
);
4429 if (streq(name
, "MainPID")) {
4431 i
->main_pid
= (pid_t
) u
;
4434 } else if (streq(name
, "ControlPID"))
4435 i
->control_pid
= (pid_t
) u
;
4436 else if (streq(name
, "ExecMainPID")) {
4438 i
->main_pid
= (pid_t
) u
;
4439 } else if (streq(name
, "NAccepted"))
4441 else if (streq(name
, "NConnections"))
4442 i
->n_connections
= u
;
4447 case SD_BUS_TYPE_INT32
: {
4450 r
= sd_bus_message_read(m
, "i", &j
);
4452 return bus_log_parse_error(r
);
4454 if (streq(name
, "ExecMainCode"))
4455 i
->exit_code
= (int) j
;
4456 else if (streq(name
, "ExecMainStatus"))
4457 i
->exit_status
= (int) j
;
4458 else if (streq(name
, "StatusErrno"))
4459 i
->status_errno
= (int) j
;
4464 case SD_BUS_TYPE_UINT64
: {
4467 r
= sd_bus_message_read(m
, "t", &u
);
4469 return bus_log_parse_error(r
);
4471 if (streq(name
, "ExecMainStartTimestamp"))
4472 i
->start_timestamp
= (usec_t
) u
;
4473 else if (streq(name
, "ExecMainExitTimestamp"))
4474 i
->exit_timestamp
= (usec_t
) u
;
4475 else if (streq(name
, "ActiveEnterTimestamp"))
4476 i
->active_enter_timestamp
= (usec_t
) u
;
4477 else if (streq(name
, "InactiveEnterTimestamp"))
4478 i
->inactive_enter_timestamp
= (usec_t
) u
;
4479 else if (streq(name
, "InactiveExitTimestamp"))
4480 i
->inactive_exit_timestamp
= (usec_t
) u
;
4481 else if (streq(name
, "InactiveExitTimestampMonotonic"))
4482 i
->inactive_exit_timestamp_monotonic
= (usec_t
) u
;
4483 else if (streq(name
, "ActiveExitTimestamp"))
4484 i
->active_exit_timestamp
= (usec_t
) u
;
4485 else if (streq(name
, "ConditionTimestamp"))
4486 i
->condition_timestamp
= (usec_t
) u
;
4487 else if (streq(name
, "AssertTimestamp"))
4488 i
->assert_timestamp
= (usec_t
) u
;
4489 else if (streq(name
, "MemoryCurrent"))
4490 i
->memory_current
= u
;
4491 else if (streq(name
, "MemoryLow"))
4493 else if (streq(name
, "MemoryHigh"))
4495 else if (streq(name
, "MemoryMax"))
4497 else if (streq(name
, "MemorySwapMax"))
4498 i
->memory_swap_max
= u
;
4499 else if (streq(name
, "MemoryLimit"))
4500 i
->memory_limit
= u
;
4501 else if (streq(name
, "TasksCurrent"))
4502 i
->tasks_current
= u
;
4503 else if (streq(name
, "TasksMax"))
4505 else if (streq(name
, "CPUUsageNSec"))
4506 i
->cpu_usage_nsec
= u
;
4507 else if (streq(name
, "NextElapseUSecMonotonic"))
4508 i
->next_elapse_monotonic
= u
;
4509 else if (streq(name
, "NextElapseUSecRealtime"))
4510 i
->next_elapse_real
= u
;
4511 else if (streq(name
, "IPIngressBytes"))
4512 i
->ip_ingress_bytes
= u
;
4513 else if (streq(name
, "IPEgressBytes"))
4514 i
->ip_egress_bytes
= u
;
4519 case SD_BUS_TYPE_ARRAY
:
4521 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4522 _cleanup_free_ ExecStatusInfo
*info
= NULL
;
4524 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4526 return bus_log_parse_error(r
);
4528 info
= new0(ExecStatusInfo
, 1);
4532 while ((r
= exec_status_info_deserialize(m
, info
)) > 0) {
4534 info
->name
= strdup(name
);
4538 LIST_PREPEND(exec
, i
->exec
, info
);
4540 info
= new0(ExecStatusInfo
, 1);
4546 return bus_log_parse_error(r
);
4548 r
= sd_bus_message_exit_container(m
);
4550 return bus_log_parse_error(r
);
4554 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4555 const char *type
, *path
;
4557 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4559 return bus_log_parse_error(r
);
4561 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0) {
4563 r
= strv_extend(&i
->listen
, type
);
4567 r
= strv_extend(&i
->listen
, path
);
4572 return bus_log_parse_error(r
);
4574 r
= sd_bus_message_exit_container(m
);
4576 return bus_log_parse_error(r
);
4580 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "DropInPaths")) {
4582 r
= sd_bus_message_read_strv(m
, &i
->dropin_paths
);
4584 return bus_log_parse_error(r
);
4586 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Documentation")) {
4588 r
= sd_bus_message_read_strv(m
, &i
->documentation
);
4590 return bus_log_parse_error(r
);
4592 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Conditions")) {
4593 const char *cond
, *param
;
4594 int trigger
, negate
;
4597 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4599 return bus_log_parse_error(r
);
4601 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4602 _cleanup_(unit_condition_freep
) UnitCondition
*c
= NULL
;
4604 log_debug("%s trigger=%d negate=%d %s →%d", cond
, trigger
, negate
, param
, state
);
4606 c
= new0(UnitCondition
, 1);
4610 c
->name
= strdup(cond
);
4611 c
->param
= strdup(param
);
4612 if (!c
->name
|| !c
->param
)
4615 c
->trigger
= trigger
;
4617 c
->tristate
= state
;
4619 LIST_PREPEND(conditions
, i
->conditions
, c
);
4623 return bus_log_parse_error(r
);
4625 r
= sd_bus_message_exit_container(m
);
4627 return bus_log_parse_error(r
);
4629 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Asserts")) {
4630 const char *cond
, *param
;
4631 int trigger
, negate
;
4634 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sbbsi)");
4636 return bus_log_parse_error(r
);
4638 while ((r
= sd_bus_message_read(m
, "(sbbsi)", &cond
, &trigger
, &negate
, ¶m
, &state
)) > 0) {
4639 log_debug("%s %d %d %s %d", cond
, trigger
, negate
, param
, state
);
4640 if (state
< 0 && (!trigger
|| !i
->failed_assert
)) {
4641 i
->failed_assert
= cond
;
4642 i
->failed_assert_trigger
= trigger
;
4643 i
->failed_assert_negate
= negate
;
4644 i
->failed_assert_parameter
= param
;
4648 return bus_log_parse_error(r
);
4650 r
= sd_bus_message_exit_container(m
);
4652 return bus_log_parse_error(r
);
4659 case SD_BUS_TYPE_STRUCT_BEGIN
:
4661 if (streq(name
, "LoadError")) {
4662 const char *n
, *message
;
4664 r
= sd_bus_message_read(m
, "(ss)", &n
, &message
);
4666 return bus_log_parse_error(r
);
4668 if (!isempty(message
))
4669 i
->load_error
= message
;
4682 r
= sd_bus_message_skip(m
, contents
);
4684 return bus_log_parse_error(r
);
4689 #define print_prop(name, fmt, ...) \
4692 printf(fmt "\n", __VA_ARGS__); \
4694 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4697 static int print_property(const char *name
, sd_bus_message
*m
, const char *contents
) {
4703 /* This is a low-level property printer, see
4704 * print_status_info() for the nicer output */
4706 if (arg_properties
&& !strv_find(arg_properties
, name
)) {
4707 /* skip what we didn't read */
4708 r
= sd_bus_message_skip(m
, contents
);
4712 switch (contents
[0]) {
4714 case SD_BUS_TYPE_STRUCT_BEGIN
:
4716 if (contents
[1] == SD_BUS_TYPE_UINT32
&& streq(name
, "Job")) {
4719 r
= sd_bus_message_read(m
, "(uo)", &u
, NULL
);
4721 return bus_log_parse_error(r
);
4724 print_prop(name
, "%"PRIu32
, u
);
4726 print_prop(name
, "%s", "");
4730 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "Unit")) {
4733 r
= sd_bus_message_read(m
, "(so)", &s
, NULL
);
4735 return bus_log_parse_error(r
);
4737 if (arg_all
|| !isempty(s
))
4738 print_prop(name
, "%s", s
);
4742 } else if (contents
[1] == SD_BUS_TYPE_STRING
&& streq(name
, "LoadError")) {
4743 const char *a
= NULL
, *b
= NULL
;
4745 r
= sd_bus_message_read(m
, "(ss)", &a
, &b
);
4747 return bus_log_parse_error(r
);
4749 if (arg_all
|| !isempty(a
) || !isempty(b
))
4750 print_prop(name
, "%s \"%s\"", strempty(a
), strempty(b
));
4753 } else if (streq_ptr(name
, "SystemCallFilter")) {
4754 _cleanup_strv_free_
char **l
= NULL
;
4757 r
= sd_bus_message_enter_container(m
, 'r', "bas");
4759 return bus_log_parse_error(r
);
4761 r
= sd_bus_message_read(m
, "b", &whitelist
);
4763 return bus_log_parse_error(r
);
4765 r
= sd_bus_message_read_strv(m
, &l
);
4767 return bus_log_parse_error(r
);
4769 r
= sd_bus_message_exit_container(m
);
4771 return bus_log_parse_error(r
);
4773 if (arg_all
|| whitelist
|| !strv_isempty(l
)) {
4778 fputs(name
, stdout
);
4785 STRV_FOREACH(i
, l
) {
4793 fputc('\n', stdout
);
4801 case SD_BUS_TYPE_ARRAY
:
4803 if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "EnvironmentFiles")) {
4807 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sb)");
4809 return bus_log_parse_error(r
);
4811 while ((r
= sd_bus_message_read(m
, "(sb)", &path
, &ignore
)) > 0)
4812 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path
, yes_no(ignore
));
4815 return bus_log_parse_error(r
);
4817 r
= sd_bus_message_exit_container(m
);
4819 return bus_log_parse_error(r
);
4823 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Paths")) {
4824 const char *type
, *path
;
4826 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4828 return bus_log_parse_error(r
);
4830 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4831 print_prop(type
, "%s", path
);
4833 return bus_log_parse_error(r
);
4835 r
= sd_bus_message_exit_container(m
);
4837 return bus_log_parse_error(r
);
4841 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Listen")) {
4842 const char *type
, *path
;
4844 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4846 return bus_log_parse_error(r
);
4848 while ((r
= sd_bus_message_read(m
, "(ss)", &type
, &path
)) > 0)
4852 printf("Listen%s=%s\n", type
, path
);
4854 return bus_log_parse_error(r
);
4856 r
= sd_bus_message_exit_container(m
);
4858 return bus_log_parse_error(r
);
4862 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "Timers")) {
4864 uint64_t value
, next_elapse
;
4866 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(stt)");
4868 return bus_log_parse_error(r
);
4870 while ((r
= sd_bus_message_read(m
, "(stt)", &base
, &value
, &next_elapse
)) > 0) {
4871 char timespan1
[FORMAT_TIMESPAN_MAX
], timespan2
[FORMAT_TIMESPAN_MAX
];
4873 print_prop(base
, "{ value=%s ; next_elapse=%s }",
4874 format_timespan(timespan1
, sizeof(timespan1
), value
, 0),
4875 format_timespan(timespan2
, sizeof(timespan2
), next_elapse
, 0));
4878 return bus_log_parse_error(r
);
4880 r
= sd_bus_message_exit_container(m
);
4882 return bus_log_parse_error(r
);
4886 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& startswith(name
, "Exec")) {
4887 ExecStatusInfo info
= {};
4889 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(sasbttttuii)");
4891 return bus_log_parse_error(r
);
4893 while ((r
= exec_status_info_deserialize(m
, &info
)) > 0) {
4894 char timestamp1
[FORMAT_TIMESTAMP_MAX
], timestamp2
[FORMAT_TIMESTAMP_MAX
];
4895 _cleanup_free_
char *tt
;
4897 tt
= strv_join(info
.argv
, " ");
4900 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT
" ; code=%s ; status=%i%s%s }",
4903 yes_no(info
.ignore
),
4904 strna(format_timestamp(timestamp1
, sizeof(timestamp1
), info
.start_timestamp
)),
4905 strna(format_timestamp(timestamp2
, sizeof(timestamp2
), info
.exit_timestamp
)),
4907 sigchld_code_to_string(info
.code
),
4909 info
.code
== CLD_EXITED
? "" : "/",
4910 strempty(info
.code
== CLD_EXITED
? NULL
: signal_to_string(info
.status
)));
4913 strv_free(info
.argv
);
4917 r
= sd_bus_message_exit_container(m
);
4919 return bus_log_parse_error(r
);
4923 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&& streq(name
, "DeviceAllow")) {
4924 const char *path
, *rwm
;
4926 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(ss)");
4928 return bus_log_parse_error(r
);
4930 while ((r
= sd_bus_message_read(m
, "(ss)", &path
, &rwm
)) > 0)
4931 print_prop(name
, "%s %s", strna(path
), strna(rwm
));
4933 return bus_log_parse_error(r
);
4935 r
= sd_bus_message_exit_container(m
);
4937 return bus_log_parse_error(r
);
4941 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4942 STR_IN_SET(name
, "IODeviceWeight", "BlockIODeviceWeight")) {
4946 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4948 return bus_log_parse_error(r
);
4950 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &weight
)) > 0)
4951 print_prop(name
, "%s %"PRIu64
, strna(path
), weight
);
4953 return bus_log_parse_error(r
);
4955 r
= sd_bus_message_exit_container(m
);
4957 return bus_log_parse_error(r
);
4961 } else if (contents
[1] == SD_BUS_TYPE_STRUCT_BEGIN
&&
4962 (cgroup_io_limit_type_from_string(name
) >= 0 ||
4963 STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4967 r
= sd_bus_message_enter_container(m
, SD_BUS_TYPE_ARRAY
, "(st)");
4969 return bus_log_parse_error(r
);
4971 while ((r
= sd_bus_message_read(m
, "(st)", &path
, &bandwidth
)) > 0)
4972 print_prop(name
, "%s %"PRIu64
, strna(path
), bandwidth
);
4974 return bus_log_parse_error(r
);
4976 r
= sd_bus_message_exit_container(m
);
4978 return bus_log_parse_error(r
);
4982 } else if (contents
[1] == SD_BUS_TYPE_BYTE
&& streq(name
, "StandardInputData")) {
4983 _cleanup_free_
char *h
= NULL
;
4988 r
= sd_bus_message_read_array(m
, 'y', &p
, &sz
);
4990 return bus_log_parse_error(r
);
4992 n
= base64mem(p
, sz
, &h
);
4996 print_prop(name
, "%s", h
);
5004 r
= bus_print_property(name
, m
, arg_value
, arg_all
);
5006 return bus_log_parse_error(r
);
5009 r
= sd_bus_message_skip(m
, contents
);
5011 return bus_log_parse_error(r
);
5014 printf("%s=[unprintable]\n", name
);
5020 static int show_one(
5025 bool show_properties
,
5029 static const struct bus_properties_map property_map
[] = {
5030 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
5031 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
) },
5035 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5036 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5037 _cleanup_set_free_ Set
*found_properties
= NULL
;
5038 _cleanup_(unit_status_info_free
) UnitStatusInfo info
= {
5039 .memory_current
= (uint64_t) -1,
5040 .memory_high
= CGROUP_LIMIT_MAX
,
5041 .memory_max
= CGROUP_LIMIT_MAX
,
5042 .memory_swap_max
= CGROUP_LIMIT_MAX
,
5043 .memory_limit
= (uint64_t) -1,
5044 .cpu_usage_nsec
= (uint64_t) -1,
5045 .tasks_current
= (uint64_t) -1,
5046 .tasks_max
= (uint64_t) -1,
5047 .ip_ingress_bytes
= (uint64_t) -1,
5048 .ip_egress_bytes
= (uint64_t) -1,
5055 log_debug("Showing one %s", path
);
5057 r
= sd_bus_call_method(
5059 "org.freedesktop.systemd1",
5061 "org.freedesktop.DBus.Properties",
5067 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
5070 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
5072 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
5074 if (streq_ptr(info
.load_state
, "not-found") && streq_ptr(info
.active_state
, "inactive")) {
5075 log_full(streq(verb
, "status") ? LOG_ERR
: LOG_DEBUG
,
5076 "Unit %s could not be found.", unit
);
5078 if (streq(verb
, "status"))
5079 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN
;
5081 if (!streq(verb
, "show"))
5085 r
= sd_bus_message_rewind(reply
, true);
5087 return log_error_errno(r
, "Failed to rewind: %s", bus_error_message(&error
, r
));
5090 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "{sv}");
5092 return bus_log_parse_error(r
);
5099 while ((r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_DICT_ENTRY
, "sv")) > 0) {
5100 const char *name
, *contents
;
5102 r
= sd_bus_message_read(reply
, "s", &name
);
5104 return bus_log_parse_error(r
);
5106 r
= sd_bus_message_peek_type(reply
, NULL
, &contents
);
5108 return bus_log_parse_error(r
);
5110 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_VARIANT
, contents
);
5112 return bus_log_parse_error(r
);
5114 if (show_properties
) {
5115 r
= set_ensure_allocated(&found_properties
, &string_hash_ops
);
5119 r
= set_put(found_properties
, name
);
5120 if (r
< 0 && r
!= EEXIST
)
5123 r
= print_property(name
, reply
, contents
);
5125 r
= status_property(name
, reply
, &info
, contents
);
5129 r
= sd_bus_message_exit_container(reply
);
5131 return bus_log_parse_error(r
);
5133 r
= sd_bus_message_exit_container(reply
);
5135 return bus_log_parse_error(r
);
5138 return bus_log_parse_error(r
);
5140 r
= sd_bus_message_exit_container(reply
);
5142 return bus_log_parse_error(r
);
5145 if (show_properties
) {
5148 STRV_FOREACH(pp
, arg_properties
)
5149 if (!set_contains(found_properties
, *pp
))
5150 log_debug("Property %s does not exist.", *pp
);
5152 } else if (streq(verb
, "help"))
5153 show_unit_help(&info
);
5154 else if (streq(verb
, "status")) {
5155 print_status_info(bus
, &info
, ellipsized
);
5157 if (info
.active_state
&& !STR_IN_SET(info
.active_state
, "active", "reloading"))
5158 r
= EXIT_PROGRAM_NOT_RUNNING
;
5160 r
= EXIT_PROGRAM_RUNNING_OR_SERVICE_OK
;
5166 static int get_unit_dbus_path_by_pid(
5171 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5172 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5176 r
= sd_bus_call_method(
5178 "org.freedesktop.systemd1",
5179 "/org/freedesktop/systemd1",
5180 "org.freedesktop.systemd1.Manager",
5186 return log_error_errno(r
, "Failed to get unit for PID %"PRIu32
": %s", pid
, bus_error_message(&error
, r
));
5188 r
= sd_bus_message_read(reply
, "o", &u
);
5190 return bus_log_parse_error(r
);
5200 static int show_all(
5203 bool show_properties
,
5207 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5208 _cleanup_free_ UnitInfo
*unit_infos
= NULL
;
5213 r
= get_unit_list(bus
, NULL
, NULL
, &unit_infos
, 0, &reply
);
5217 pager_open(arg_no_pager
, false);
5221 qsort_safe(unit_infos
, c
, sizeof(UnitInfo
), compare_unit_info
);
5223 for (u
= unit_infos
; u
< unit_infos
+ c
; u
++) {
5224 _cleanup_free_
char *p
= NULL
;
5226 p
= unit_dbus_path_from_name(u
->id
);
5230 r
= show_one(verb
, bus
, p
, u
->id
, show_properties
, new_line
, ellipsized
);
5233 else if (r
> 0 && ret
== 0)
5240 static int show_system_status(sd_bus
*bus
) {
5241 char since1
[FORMAT_TIMESTAMP_RELATIVE_MAX
], since2
[FORMAT_TIMESTAMP_MAX
];
5242 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5243 _cleanup_(machine_info_clear
) struct machine_info mi
= {};
5244 _cleanup_free_
char *hn
= NULL
;
5245 const char *on
, *off
;
5248 hn
= gethostname_malloc();
5252 r
= bus_map_all_properties(bus
, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map
, &error
, &mi
);
5254 return log_error_errno(r
, "Failed to read server status: %s", bus_error_message(&error
, r
));
5256 if (streq_ptr(mi
.state
, "degraded")) {
5257 on
= ansi_highlight_red();
5258 off
= ansi_normal();
5259 } else if (streq_ptr(mi
.state
, "running")) {
5260 on
= ansi_highlight_green();
5261 off
= ansi_normal();
5263 on
= ansi_highlight_yellow();
5264 off
= ansi_normal();
5267 printf("%s%s%s %s\n", on
, special_glyph(BLACK_CIRCLE
), off
, arg_host
? arg_host
: hn
);
5269 printf(" State: %s%s%s\n",
5270 on
, strna(mi
.state
), off
);
5272 printf(" Jobs: %" PRIu32
" queued\n", mi
.n_jobs
);
5273 printf(" Failed: %" PRIu32
" units\n", mi
.n_failed_units
);
5275 printf(" Since: %s; %s\n",
5276 format_timestamp(since2
, sizeof(since2
), mi
.timestamp
),
5277 format_timestamp_relative(since1
, sizeof(since1
), mi
.timestamp
));
5279 printf(" CGroup: %s\n", mi
.control_group
?: "/");
5280 if (IN_SET(arg_transport
,
5281 BUS_TRANSPORT_LOCAL
,
5282 BUS_TRANSPORT_MACHINE
)) {
5283 static const char prefix
[] = " ";
5287 if (c
> sizeof(prefix
) - 1)
5288 c
-= sizeof(prefix
) - 1;
5292 show_cgroup(SYSTEMD_CGROUP_CONTROLLER
, strempty(mi
.control_group
), prefix
, c
, get_output_flags());
5298 static int show(int argc
, char *argv
[], void *userdata
) {
5299 bool show_properties
, show_status
, show_help
, new_line
= false;
5300 bool ellipsized
= false;
5306 show_properties
= streq(argv
[0], "show");
5307 show_status
= streq(argv
[0], "status");
5308 show_help
= streq(argv
[0], "help");
5310 if (show_help
&& argc
<= 1) {
5311 log_error("This command expects one or more unit names. Did you mean --help?");
5315 r
= acquire_bus(BUS_MANAGER
, &bus
);
5319 pager_open(arg_no_pager
, false);
5322 /* Increase max number of open files to 16K if we can, we
5323 * might needs this when browsing journal files, which might
5324 * be split up into many files. */
5325 setrlimit_closest(RLIMIT_NOFILE
, &RLIMIT_MAKE_CONST(16384));
5327 /* If no argument is specified inspect the manager itself */
5328 if (show_properties
&& argc
<= 1)
5329 return show_one(argv
[0], bus
, "/org/freedesktop/systemd1", NULL
, show_properties
, &new_line
, &ellipsized
);
5331 if (show_status
&& argc
<= 1) {
5333 show_system_status(bus
);
5337 ret
= show_all(argv
[0], bus
, false, &new_line
, &ellipsized
);
5339 _cleanup_free_
char **patterns
= NULL
;
5342 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
5343 _cleanup_free_
char *path
= NULL
, *unit
= NULL
;
5346 if (safe_atou32(*name
, &id
) < 0) {
5347 if (strv_push(&patterns
, *name
) < 0)
5351 } else if (show_properties
) {
5352 /* Interpret as job id */
5353 if (asprintf(&path
, "/org/freedesktop/systemd1/job/%u", id
) < 0)
5357 /* Interpret as PID */
5358 r
= get_unit_dbus_path_by_pid(bus
, id
, &path
);
5364 r
= unit_name_from_dbus_path(path
, &unit
);
5369 r
= show_one(argv
[0], bus
, path
, unit
, show_properties
, &new_line
, &ellipsized
);
5372 else if (r
> 0 && ret
== 0)
5376 if (!strv_isempty(patterns
)) {
5377 _cleanup_strv_free_
char **names
= NULL
;
5379 r
= expand_names(bus
, patterns
, NULL
, &names
);
5381 return log_error_errno(r
, "Failed to expand names: %m");
5383 STRV_FOREACH(name
, names
) {
5384 _cleanup_free_
char *path
;
5386 path
= unit_dbus_path_from_name(*name
);
5390 r
= show_one(argv
[0], bus
, path
, *name
, show_properties
, &new_line
, &ellipsized
);
5393 if (r
> 0 && ret
== 0)
5399 if (ellipsized
&& !arg_quiet
)
5400 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5405 static int cat_file(const char *filename
, bool newline
) {
5406 _cleanup_close_
int fd
;
5408 fd
= open(filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
5412 printf("%s%s# %s%s\n",
5413 newline
? "\n" : "",
5414 ansi_highlight_blue(),
5419 return copy_bytes(fd
, STDOUT_FILENO
, (uint64_t) -1, 0);
5422 static int cat(int argc
, char *argv
[], void *userdata
) {
5423 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
5424 _cleanup_strv_free_
char **names
= NULL
;
5430 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5431 log_error("Cannot remotely cat units.");
5435 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
5437 return log_error_errno(r
, "Failed to determine unit paths: %m");
5439 r
= acquire_bus(BUS_MANAGER
, &bus
);
5443 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5445 return log_error_errno(r
, "Failed to expand names: %m");
5447 pager_open(arg_no_pager
, false);
5449 STRV_FOREACH(name
, names
) {
5450 _cleanup_free_
char *fragment_path
= NULL
;
5451 _cleanup_strv_free_
char **dropin_paths
= NULL
;
5454 r
= unit_find_paths(bus
, *name
, &lp
, &fragment_path
, &dropin_paths
);
5465 if (need_daemon_reload(bus
, *name
) > 0) /* ignore errors (<0), this is informational output */
5467 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5468 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5469 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5470 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5471 ansi_highlight_red(),
5473 ansi_highlight_red(),
5474 ansi_highlight_red(),
5475 ansi_highlight_red(),
5476 arg_scope
== UNIT_FILE_SYSTEM
? "" : " --user",
5479 if (fragment_path
) {
5480 r
= cat_file(fragment_path
, false);
5482 return log_warning_errno(r
, "Failed to cat %s: %m", fragment_path
);
5485 STRV_FOREACH(path
, dropin_paths
) {
5486 r
= cat_file(*path
, path
== dropin_paths
);
5488 return log_warning_errno(r
, "Failed to cat %s: %m", *path
);
5495 static int set_property(int argc
, char *argv
[], void *userdata
) {
5496 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5497 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5498 _cleanup_free_
char *n
= NULL
;
5502 r
= acquire_bus(BUS_MANAGER
, &bus
);
5506 polkit_agent_open_maybe();
5508 r
= sd_bus_message_new_method_call(
5511 "org.freedesktop.systemd1",
5512 "/org/freedesktop/systemd1",
5513 "org.freedesktop.systemd1.Manager",
5514 "SetUnitProperties");
5516 return bus_log_create_error(r
);
5518 r
= unit_name_mangle(argv
[1], UNIT_NAME_NOGLOB
, &n
);
5520 return log_error_errno(r
, "Failed to mangle unit name: %m");
5522 r
= sd_bus_message_append(m
, "sb", n
, arg_runtime
);
5524 return bus_log_create_error(r
);
5526 r
= sd_bus_message_open_container(m
, SD_BUS_TYPE_ARRAY
, "(sv)");
5528 return bus_log_create_error(r
);
5530 r
= bus_append_unit_property_assignment_many(m
, strv_skip(argv
, 2));
5534 r
= sd_bus_message_close_container(m
);
5536 return bus_log_create_error(r
);
5538 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5540 return log_error_errno(r
, "Failed to set unit properties on %s: %s", n
, bus_error_message(&error
, r
));
5545 static int daemon_reload(int argc
, char *argv
[], void *userdata
) {
5546 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5547 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5552 r
= acquire_bus(BUS_MANAGER
, &bus
);
5556 polkit_agent_open_maybe();
5558 switch (arg_action
) {
5565 method
= "Reexecute";
5568 case ACTION_SYSTEMCTL
:
5569 method
= streq(argv
[0], "daemon-reexec") ? "Reexecute" :
5570 /* "daemon-reload" */ "Reload";
5574 assert_not_reached("Unexpected action");
5577 r
= sd_bus_message_new_method_call(
5580 "org.freedesktop.systemd1",
5581 "/org/freedesktop/systemd1",
5582 "org.freedesktop.systemd1.Manager",
5585 return bus_log_create_error(r
);
5587 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5588 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5589 * their timeout, and for everything else there's the same time budget in place. */
5591 r
= sd_bus_call(bus
, m
, DEFAULT_TIMEOUT_USEC
* 2, &error
, NULL
);
5593 /* On reexecution, we expect a disconnect, not a reply */
5594 if (IN_SET(r
, -ETIMEDOUT
, -ECONNRESET
) && streq(method
, "Reexecute"))
5597 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5598 return log_error_errno(r
, "Failed to reload daemon: %s", bus_error_message(&error
, r
));
5600 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5601 * old ways of doing things, hence don't log any error in that case here. */
5603 return r
< 0 ? r
: 0;
5606 static int trivial_method(int argc
, char *argv
[], void *userdata
) {
5607 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5612 r
= acquire_bus(BUS_MANAGER
, &bus
);
5616 polkit_agent_open_maybe();
5619 streq(argv
[0], "clear-jobs") ||
5620 streq(argv
[0], "cancel") ? "ClearJobs" :
5621 streq(argv
[0], "reset-failed") ? "ResetFailed" :
5622 streq(argv
[0], "halt") ? "Halt" :
5623 streq(argv
[0], "reboot") ? "Reboot" :
5624 streq(argv
[0], "kexec") ? "KExec" :
5625 streq(argv
[0], "exit") ? "Exit" :
5626 /* poweroff */ "PowerOff";
5628 r
= sd_bus_call_method(
5630 "org.freedesktop.systemd1",
5631 "/org/freedesktop/systemd1",
5632 "org.freedesktop.systemd1.Manager",
5637 if (r
< 0 && arg_action
== ACTION_SYSTEMCTL
)
5638 return log_error_errno(r
, "Failed to execute operation: %s", bus_error_message(&error
, r
));
5640 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5641 * old ways of doing things, hence don't log any error in that case here. */
5643 return r
< 0 ? r
: 0;
5646 static int reset_failed(int argc
, char *argv
[], void *userdata
) {
5647 _cleanup_strv_free_
char **names
= NULL
;
5653 return trivial_method(argc
, argv
, userdata
);
5655 r
= acquire_bus(BUS_MANAGER
, &bus
);
5659 polkit_agent_open_maybe();
5661 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
5663 return log_error_errno(r
, "Failed to expand names: %m");
5665 STRV_FOREACH(name
, names
) {
5666 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5668 q
= sd_bus_call_method(
5670 "org.freedesktop.systemd1",
5671 "/org/freedesktop/systemd1",
5672 "org.freedesktop.systemd1.Manager",
5678 log_error_errno(q
, "Failed to reset failed state of unit %s: %s", *name
, bus_error_message(&error
, q
));
5687 static int print_variable(const char *s
) {
5689 _cleanup_free_
char *esc
= NULL
;
5691 sep
= strchr(s
, '=');
5693 log_error("Invalid environment block");
5697 esc
= shell_maybe_quote(sep
+ 1, ESCAPE_POSIX
);
5701 printf("%.*s=%s\n", (int)(sep
-s
), s
, esc
);
5705 static int show_environment(int argc
, char *argv
[], void *userdata
) {
5706 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5707 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
5712 r
= acquire_bus(BUS_MANAGER
, &bus
);
5716 pager_open(arg_no_pager
, false);
5718 r
= sd_bus_get_property(
5720 "org.freedesktop.systemd1",
5721 "/org/freedesktop/systemd1",
5722 "org.freedesktop.systemd1.Manager",
5728 return log_error_errno(r
, "Failed to get environment: %s", bus_error_message(&error
, r
));
5730 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
5732 return bus_log_parse_error(r
);
5734 while ((r
= sd_bus_message_read_basic(reply
, SD_BUS_TYPE_STRING
, &text
)) > 0) {
5735 r
= print_variable(text
);
5740 return bus_log_parse_error(r
);
5742 r
= sd_bus_message_exit_container(reply
);
5744 return bus_log_parse_error(r
);
5749 static int switch_root(int argc
, char *argv
[], void *userdata
) {
5750 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5751 _cleanup_free_
char *cmdline_init
= NULL
;
5752 const char *root
, *init
;
5756 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
5757 log_error("Cannot switch root remotely.");
5761 if (argc
< 2 || argc
> 3) {
5762 log_error("Wrong number of arguments.");
5771 r
= parse_env_file("/proc/cmdline", WHITESPACE
,
5772 "init", &cmdline_init
,
5775 log_debug_errno(r
, "Failed to parse /proc/cmdline: %m");
5777 init
= cmdline_init
;
5780 init
= empty_to_null(init
);
5782 const char *root_systemd_path
= NULL
, *root_init_path
= NULL
;
5784 root_systemd_path
= strjoina(root
, "/" SYSTEMD_BINARY_PATH
);
5785 root_init_path
= strjoina(root
, "/", init
);
5787 /* If the passed init is actually the same as the
5788 * systemd binary, then let's suppress it. */
5789 if (files_same(root_init_path
, root_systemd_path
, 0) > 0)
5793 /* Instruct PID1 to exclude us from its killing spree applied during
5794 * the transition. Otherwise we would exit with a failure status even
5795 * though the switch to the new root has succeed. */
5796 argv_cmdline
[0] = '@';
5798 r
= acquire_bus(BUS_MANAGER
, &bus
);
5802 /* If we are slow to exit after the root switch, the new systemd instance
5803 * will send us a signal to terminate. Just ignore it and exit normally.
5804 * This way the unit does not end up as failed.
5806 r
= ignore_signals(SIGTERM
, -1);
5808 log_warning_errno(r
, "Failed to change disposition of SIGTERM to ignore: %m");
5810 log_debug("Switching root - root: %s; init: %s", root
, strna(init
));
5812 r
= sd_bus_call_method(
5814 "org.freedesktop.systemd1",
5815 "/org/freedesktop/systemd1",
5816 "org.freedesktop.systemd1.Manager",
5822 (void) default_signals(SIGTERM
, -1);
5824 return log_error_errno(r
, "Failed to switch root: %s", bus_error_message(&error
, r
));
5830 static int set_environment(int argc
, char *argv
[], void *userdata
) {
5831 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5832 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5840 r
= acquire_bus(BUS_MANAGER
, &bus
);
5844 polkit_agent_open_maybe();
5846 method
= streq(argv
[0], "set-environment")
5848 : "UnsetEnvironment";
5850 r
= sd_bus_message_new_method_call(
5853 "org.freedesktop.systemd1",
5854 "/org/freedesktop/systemd1",
5855 "org.freedesktop.systemd1.Manager",
5858 return bus_log_create_error(r
);
5860 r
= sd_bus_message_append_strv(m
, strv_skip(argv
, 1));
5862 return bus_log_create_error(r
);
5864 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5866 return log_error_errno(r
, "Failed to set environment: %s", bus_error_message(&error
, r
));
5871 static int import_environment(int argc
, char *argv
[], void *userdata
) {
5872 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
5873 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
5877 r
= acquire_bus(BUS_MANAGER
, &bus
);
5881 polkit_agent_open_maybe();
5883 r
= sd_bus_message_new_method_call(
5886 "org.freedesktop.systemd1",
5887 "/org/freedesktop/systemd1",
5888 "org.freedesktop.systemd1.Manager",
5891 return bus_log_create_error(r
);
5894 r
= sd_bus_message_append_strv(m
, environ
);
5898 r
= sd_bus_message_open_container(m
, 'a', "s");
5900 return bus_log_create_error(r
);
5902 STRV_FOREACH(a
, strv_skip(argv
, 1)) {
5904 if (!env_name_is_valid(*a
)) {
5905 log_error("Not a valid environment variable name: %s", *a
);
5909 STRV_FOREACH(b
, environ
) {
5912 eq
= startswith(*b
, *a
);
5913 if (eq
&& *eq
== '=') {
5915 r
= sd_bus_message_append(m
, "s", *b
);
5917 return bus_log_create_error(r
);
5924 r
= sd_bus_message_close_container(m
);
5927 return bus_log_create_error(r
);
5929 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
5931 return log_error_errno(r
, "Failed to import environment: %s", bus_error_message(&error
, r
));
5936 static int enable_sysv_units(const char *verb
, char **args
) {
5939 #if HAVE_SYSV_COMPAT
5940 _cleanup_lookup_paths_free_ LookupPaths paths
= {};
5943 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5945 if (arg_scope
!= UNIT_FILE_SYSTEM
)
5948 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5951 if (!STR_IN_SET(verb
,
5957 r
= lookup_paths_init(&paths
, arg_scope
, LOOKUP_PATHS_EXCLUDE_GENERATED
, arg_root
);
5964 const char *argv
[] = {
5965 ROOTLIBEXECDIR
"/systemd-sysv-install",
5972 _cleanup_free_
char *p
= NULL
, *q
= NULL
, *l
= NULL
;
5973 bool found_native
= false, found_sysv
;
5982 if (!endswith(name
, ".service"))
5985 if (path_is_absolute(name
))
5988 j
= unit_file_exists(arg_scope
, &paths
, name
);
5989 if (j
< 0 && !IN_SET(j
, -ELOOP
, -ERFKILL
, -EADDRNOTAVAIL
))
5990 return log_error_errno(j
, "Failed to lookup unit file state: %m");
5991 found_native
= j
!= 0;
5993 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5994 * prefer the native unit */
5995 if (found_native
&& streq(verb
, "is-enabled"))
5998 p
= path_join(arg_root
, SYSTEM_SYSVINIT_PATH
, name
);
6002 p
[strlen(p
) - strlen(".service")] = 0;
6003 found_sysv
= access(p
, F_OK
) >= 0;
6009 log_info("Synchronizing state of %s with SysV service script with %s.", name
, argv
[0]);
6011 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name
);
6014 if (!isempty(arg_root
))
6015 argv
[c
++] = q
= strappend("--root=", arg_root
);
6018 argv
[c
++] = basename(p
);
6021 l
= strv_join((char**)argv
, " ");
6026 log_info("Executing: %s", l
);
6030 return log_error_errno(errno
, "Failed to fork: %m");
6031 else if (pid
== 0) {
6034 (void) reset_all_signal_handlers();
6035 (void) reset_signal_mask();
6037 execv(argv
[0], (char**) argv
);
6038 log_error_errno(errno
, "Failed to execute %s: %m", argv
[0]);
6039 _exit(EXIT_FAILURE
);
6042 j
= wait_for_terminate(pid
, &status
);
6044 return log_error_errno(j
, "Failed to wait for child: %m");
6046 if (status
.si_code
== CLD_EXITED
) {
6047 if (streq(verb
, "is-enabled")) {
6048 if (status
.si_status
== 0) {
6057 } else if (status
.si_status
!= 0)
6058 return -EBADE
; /* We don't warn here, under the assumption the script already showed an explanation */
6060 log_error("Unexpected waitid() result.");
6067 /* Remove this entry, so that we don't try enabling it as native unit */
6070 assert(args
[f
] == name
);
6071 strv_remove(args
, name
);
6078 static int mangle_names(char **original_names
, char ***mangled_names
) {
6079 char **i
, **l
, **name
;
6082 l
= i
= new(char*, strv_length(original_names
) + 1);
6086 STRV_FOREACH(name
, original_names
) {
6088 /* When enabling units qualified path names are OK,
6089 * too, hence allow them explicitly. */
6091 if (is_path(*name
)) {
6098 r
= unit_name_mangle(*name
, UNIT_NAME_NOGLOB
, i
);
6102 return log_error_errno(r
, "Failed to mangle unit name: %m");
6115 static int normalize_filenames(char **names
) {
6119 STRV_FOREACH(u
, names
)
6120 if (!path_is_absolute(*u
)) {
6121 char* normalized_path
;
6123 if (!isempty(arg_root
)) {
6124 log_error("Non-absolute paths are not allowed when --root is used: %s", *u
);
6128 if (!strchr(*u
,'/')) {
6129 log_error("Link argument does contain at least one directory separator: %s", *u
);
6133 r
= path_make_absolute_cwd(*u
, &normalized_path
);
6137 free_and_replace(*u
, normalized_path
);
6143 static int normalize_names(char **names
, bool warn_if_path
) {
6145 bool was_path
= false;
6147 STRV_FOREACH(u
, names
) {
6153 r
= free_and_strdup(u
, basename(*u
));
6155 return log_error_errno(r
, "Failed to normalize unit file path: %m");
6160 if (warn_if_path
&& was_path
)
6161 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
6166 static int unit_exists(LookupPaths
*lp
, const char *unit
) {
6167 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6168 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6169 _cleanup_free_
char *path
= NULL
;
6170 static const struct bus_properties_map property_map
[] = {
6171 { "LoadState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, load_state
) },
6172 { "ActiveState", "s", map_string_no_copy
, offsetof(UnitStatusInfo
, active_state
)},
6175 UnitStatusInfo info
= {};
6179 if (unit_name_is_valid(unit
, UNIT_NAME_TEMPLATE
))
6180 return unit_find_template_path(unit
, lp
, NULL
, NULL
);
6182 path
= unit_dbus_path_from_name(unit
);
6186 r
= acquire_bus(BUS_MANAGER
, &bus
);
6190 r
= sd_bus_call_method(
6192 "org.freedesktop.systemd1",
6194 "org.freedesktop.DBus.Properties",
6200 return log_error_errno(r
, "Failed to get properties: %s", bus_error_message(&error
, r
));
6202 r
= bus_message_map_all_properties(reply
, property_map
, &error
, &info
);
6204 return log_error_errno(r
, "Failed to map properties: %s", bus_error_message(&error
, r
));
6206 return !streq_ptr(info
.load_state
, "not-found") || !streq_ptr(info
.active_state
, "inactive");
6209 static int enable_unit(int argc
, char *argv
[], void *userdata
) {
6210 _cleanup_strv_free_
char **names
= NULL
;
6211 const char *verb
= argv
[0];
6212 UnitFileChange
*changes
= NULL
;
6213 unsigned n_changes
= 0;
6214 int carries_install_info
= -1;
6215 bool ignore_carries_install_info
= arg_quiet
;
6221 r
= mangle_names(strv_skip(argv
, 1), &names
);
6225 r
= enable_sysv_units(verb
, names
);
6229 /* If the operation was fully executed by the SysV compat, let's finish early */
6230 if (strv_isempty(names
)) {
6231 if (arg_no_reload
|| install_client_side())
6233 return daemon_reload(argc
, argv
, userdata
);
6236 if (streq(verb
, "disable")) {
6237 r
= normalize_names(names
, true);
6242 if (streq(verb
, "link")) {
6243 r
= normalize_filenames(names
);
6248 if (install_client_side()) {
6249 UnitFileFlags flags
;
6251 flags
= args_to_flags();
6252 if (streq(verb
, "enable")) {
6253 r
= unit_file_enable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6254 carries_install_info
= r
;
6255 } else if (streq(verb
, "disable"))
6256 r
= unit_file_disable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6257 else if (streq(verb
, "reenable")) {
6258 r
= unit_file_reenable(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6259 carries_install_info
= r
;
6260 } else if (streq(verb
, "link"))
6261 r
= unit_file_link(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6262 else if (streq(verb
, "preset")) {
6263 r
= unit_file_preset(arg_scope
, flags
, arg_root
, names
, arg_preset_mode
, &changes
, &n_changes
);
6264 } else if (streq(verb
, "mask"))
6265 r
= unit_file_mask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6266 else if (streq(verb
, "unmask"))
6267 r
= unit_file_unmask(arg_scope
, flags
, arg_root
, names
, &changes
, &n_changes
);
6268 else if (streq(verb
, "revert"))
6269 r
= unit_file_revert(arg_scope
, arg_root
, names
, &changes
, &n_changes
);
6271 assert_not_reached("Unknown verb");
6273 unit_file_dump_changes(r
, verb
, changes
, n_changes
, arg_quiet
);
6278 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6279 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6280 bool expect_carries_install_info
= false;
6281 bool send_runtime
= true, send_force
= true, send_preset_mode
= false;
6285 if (STR_IN_SET(verb
, "mask", "unmask")) {
6287 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6289 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6293 STRV_FOREACH(name
, names
) {
6294 r
= unit_exists(&lp
, *name
);
6298 log_notice("Unit %s does not exist, proceeding anyway.", *names
);
6302 r
= acquire_bus(BUS_MANAGER
, &bus
);
6306 polkit_agent_open_maybe();
6308 if (streq(verb
, "enable")) {
6309 method
= "EnableUnitFiles";
6310 expect_carries_install_info
= true;
6311 } else if (streq(verb
, "disable")) {
6312 method
= "DisableUnitFiles";
6314 } else if (streq(verb
, "reenable")) {
6315 method
= "ReenableUnitFiles";
6316 expect_carries_install_info
= true;
6317 } else if (streq(verb
, "link"))
6318 method
= "LinkUnitFiles";
6319 else if (streq(verb
, "preset")) {
6321 if (arg_preset_mode
!= UNIT_FILE_PRESET_FULL
) {
6322 method
= "PresetUnitFilesWithMode";
6323 send_preset_mode
= true;
6325 method
= "PresetUnitFiles";
6327 expect_carries_install_info
= true;
6328 ignore_carries_install_info
= true;
6329 } else if (streq(verb
, "mask"))
6330 method
= "MaskUnitFiles";
6331 else if (streq(verb
, "unmask")) {
6332 method
= "UnmaskUnitFiles";
6334 } else if (streq(verb
, "revert")) {
6335 method
= "RevertUnitFiles";
6336 send_runtime
= send_force
= false;
6338 assert_not_reached("Unknown verb");
6340 r
= sd_bus_message_new_method_call(
6343 "org.freedesktop.systemd1",
6344 "/org/freedesktop/systemd1",
6345 "org.freedesktop.systemd1.Manager",
6348 return bus_log_create_error(r
);
6350 r
= sd_bus_message_append_strv(m
, names
);
6352 return bus_log_create_error(r
);
6354 if (send_preset_mode
) {
6355 r
= sd_bus_message_append(m
, "s", unit_file_preset_mode_to_string(arg_preset_mode
));
6357 return bus_log_create_error(r
);
6361 r
= sd_bus_message_append(m
, "b", arg_runtime
);
6363 return bus_log_create_error(r
);
6367 r
= sd_bus_message_append(m
, "b", arg_force
);
6369 return bus_log_create_error(r
);
6372 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6374 return log_error_errno(r
, "Failed to %s unit: %s", verb
, bus_error_message(&error
, r
));
6376 if (expect_carries_install_info
) {
6377 r
= sd_bus_message_read(reply
, "b", &carries_install_info
);
6379 return bus_log_parse_error(r
);
6382 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6386 /* Try to reload if enabled */
6388 r
= daemon_reload(argc
, argv
, userdata
);
6393 if (carries_install_info
== 0 && !ignore_carries_install_info
)
6394 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6395 "settings in the [Install] section, and DefaultInstance for template units).\n"
6396 "This means they are not meant to be enabled using systemctl.\n"
6397 "Possible reasons for having this kind of units are:\n"
6398 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6399 " .wants/ or .requires/ directory.\n"
6400 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6401 " a requirement dependency on it.\n"
6402 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6403 " D-Bus, udev, scripted systemctl call, ...).\n"
6404 "4) In case of template units, the unit is meant to be enabled with some\n"
6405 " instance name specified.");
6407 if (arg_now
&& STR_IN_SET(argv
[0], "enable", "disable", "mask")) {
6411 r
= acquire_bus(BUS_MANAGER
, &bus
);
6415 len
= strv_length(names
);
6417 char *new_args
[len
+ 2];
6419 new_args
[0] = (char*) (streq(argv
[0], "enable") ? "start" : "stop");
6420 for (i
= 0; i
< len
; i
++)
6421 new_args
[i
+ 1] = basename(names
[i
]);
6422 new_args
[i
+ 1] = NULL
;
6424 r
= start_unit(len
+ 1, new_args
, userdata
);
6429 unit_file_changes_free(changes
, n_changes
);
6434 static int add_dependency(int argc
, char *argv
[], void *userdata
) {
6435 _cleanup_strv_free_
char **names
= NULL
;
6436 _cleanup_free_
char *target
= NULL
;
6437 const char *verb
= argv
[0];
6438 UnitFileChange
*changes
= NULL
;
6439 unsigned n_changes
= 0;
6446 r
= unit_name_mangle_with_suffix(argv
[1], UNIT_NAME_NOGLOB
, ".target", &target
);
6448 return log_error_errno(r
, "Failed to mangle unit name: %m");
6450 r
= mangle_names(strv_skip(argv
, 2), &names
);
6454 if (streq(verb
, "add-wants"))
6456 else if (streq(verb
, "add-requires"))
6457 dep
= UNIT_REQUIRES
;
6459 assert_not_reached("Unknown verb");
6461 if (install_client_side()) {
6462 r
= unit_file_add_dependency(arg_scope
, args_to_flags(), arg_root
, names
, target
, dep
, &changes
, &n_changes
);
6463 unit_file_dump_changes(r
, "add dependency on", changes
, n_changes
, arg_quiet
);
6468 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
, *m
= NULL
;
6469 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6472 r
= acquire_bus(BUS_MANAGER
, &bus
);
6476 polkit_agent_open_maybe();
6478 r
= sd_bus_message_new_method_call(
6481 "org.freedesktop.systemd1",
6482 "/org/freedesktop/systemd1",
6483 "org.freedesktop.systemd1.Manager",
6484 "AddDependencyUnitFiles");
6486 return bus_log_create_error(r
);
6488 r
= sd_bus_message_append_strv(m
, names
);
6490 return bus_log_create_error(r
);
6492 r
= sd_bus_message_append(m
, "ssbb", target
, unit_dependency_to_string(dep
), arg_runtime
, arg_force
);
6494 return bus_log_create_error(r
);
6496 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
6498 return log_error_errno(r
, "Failed to add dependency: %s", bus_error_message(&error
, r
));
6500 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6504 if (arg_no_reload
) {
6509 r
= daemon_reload(argc
, argv
, userdata
);
6513 unit_file_changes_free(changes
, n_changes
);
6518 static int preset_all(int argc
, char *argv
[], void *userdata
) {
6519 UnitFileChange
*changes
= NULL
;
6520 unsigned n_changes
= 0;
6523 if (install_client_side()) {
6524 r
= unit_file_preset_all(arg_scope
, args_to_flags(), arg_root
, arg_preset_mode
, &changes
, &n_changes
);
6525 unit_file_dump_changes(r
, "preset", changes
, n_changes
, arg_quiet
);
6530 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6531 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6534 r
= acquire_bus(BUS_MANAGER
, &bus
);
6538 polkit_agent_open_maybe();
6540 r
= sd_bus_call_method(
6542 "org.freedesktop.systemd1",
6543 "/org/freedesktop/systemd1",
6544 "org.freedesktop.systemd1.Manager",
6545 "PresetAllUnitFiles",
6549 unit_file_preset_mode_to_string(arg_preset_mode
),
6553 return log_error_errno(r
, "Failed to preset all units: %s", bus_error_message(&error
, r
));
6555 r
= bus_deserialize_and_dump_unit_file_changes(reply
, arg_quiet
, &changes
, &n_changes
);
6559 if (arg_no_reload
) {
6564 r
= daemon_reload(argc
, argv
, userdata
);
6568 unit_file_changes_free(changes
, n_changes
);
6573 static int show_installation_targets_client_side(const char *name
) {
6574 UnitFileChange
*changes
= NULL
;
6575 unsigned n_changes
= 0, i
;
6576 UnitFileFlags flags
;
6580 p
= STRV_MAKE(name
);
6581 flags
= UNIT_FILE_DRY_RUN
|
6582 (arg_runtime
? UNIT_FILE_RUNTIME
: 0);
6584 r
= unit_file_disable(UNIT_FILE_SYSTEM
, flags
, NULL
, p
, &changes
, &n_changes
);
6586 return log_error_errno(r
, "Failed to get file links for %s: %m", name
);
6588 for (i
= 0; i
< n_changes
; i
++)
6589 if (changes
[i
].type
== UNIT_FILE_UNLINK
)
6590 printf(" %s\n", changes
[i
].path
);
6595 static int show_installation_targets(sd_bus
*bus
, const char *name
) {
6596 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6597 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6601 r
= sd_bus_call_method(
6603 "org.freedesktop.systemd1",
6604 "/org/freedesktop/systemd1",
6605 "org.freedesktop.systemd1.Manager",
6609 "sb", name
, arg_runtime
);
6611 return log_error_errno(r
, "Failed to get unit file links for %s: %s", name
, bus_error_message(&error
, r
));
6613 r
= sd_bus_message_enter_container(reply
, SD_BUS_TYPE_ARRAY
, "s");
6615 return bus_log_parse_error(r
);
6617 while ((r
= sd_bus_message_read(reply
, "s", &link
)) > 0)
6618 printf(" %s\n", link
);
6621 return bus_log_parse_error(r
);
6623 r
= sd_bus_message_exit_container(reply
);
6625 return bus_log_parse_error(r
);
6630 static int unit_is_enabled(int argc
, char *argv
[], void *userdata
) {
6632 _cleanup_strv_free_
char **names
= NULL
;
6637 r
= mangle_names(strv_skip(argv
, 1), &names
);
6641 r
= enable_sysv_units(argv
[0], names
);
6647 if (install_client_side()) {
6648 STRV_FOREACH(name
, names
) {
6649 UnitFileState state
;
6651 r
= unit_file_get_state(arg_scope
, arg_root
, *name
, &state
);
6653 return log_error_errno(r
, "Failed to get unit file state for %s: %m", *name
);
6657 UNIT_FILE_ENABLED_RUNTIME
,
6660 UNIT_FILE_GENERATED
))
6664 puts(unit_file_state_to_string(state
));
6666 r
= show_installation_targets_client_side(*name
);
6675 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
6678 r
= acquire_bus(BUS_MANAGER
, &bus
);
6682 STRV_FOREACH(name
, names
) {
6683 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
6686 r
= sd_bus_call_method(
6688 "org.freedesktop.systemd1",
6689 "/org/freedesktop/systemd1",
6690 "org.freedesktop.systemd1.Manager",
6696 return log_error_errno(r
, "Failed to get unit file state for %s: %s", *name
, bus_error_message(&error
, r
));
6698 r
= sd_bus_message_read(reply
, "s", &s
);
6700 return bus_log_parse_error(r
);
6702 if (STR_IN_SET(s
, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6708 r
= show_installation_targets(bus
, *name
);
6716 return enabled
? EXIT_SUCCESS
: EXIT_FAILURE
;
6719 static int is_system_running(int argc
, char *argv
[], void *userdata
) {
6720 _cleanup_free_
char *state
= NULL
;
6724 if (running_in_chroot() > 0 || (arg_transport
== BUS_TRANSPORT_LOCAL
&& !sd_booted())) {
6727 return EXIT_FAILURE
;
6730 r
= acquire_bus(BUS_MANAGER
, &bus
);
6734 r
= sd_bus_get_property_string(
6736 "org.freedesktop.systemd1",
6737 "/org/freedesktop/systemd1",
6738 "org.freedesktop.systemd1.Manager",
6751 return streq(state
, "running") ? EXIT_SUCCESS
: EXIT_FAILURE
;
6754 static int create_edit_temp_file(const char *new_path
, const char *original_path
, char **ret_tmp_fn
) {
6755 _cleanup_free_
char *t
= NULL
;
6759 assert(original_path
);
6762 r
= tempfn_random(new_path
, NULL
, &t
);
6764 return log_error_errno(r
, "Failed to determine temporary filename for \"%s\": %m", new_path
);
6766 r
= mkdir_parents(new_path
, 0755);
6768 return log_error_errno(r
, "Failed to create directories for \"%s\": %m", new_path
);
6770 r
= copy_file(original_path
, t
, 0, 0644, 0, COPY_REFLINK
);
6775 return log_error_errno(r
, "Failed to create temporary file \"%s\": %m", t
);
6778 return log_error_errno(r
, "Failed to create temporary file for \"%s\": %m", new_path
);
6786 static int get_file_to_edit(
6787 const LookupPaths
*paths
,
6791 _cleanup_free_
char *path
= NULL
, *run
= NULL
;
6796 path
= strjoin(paths
->persistent_config
, "/", name
);
6801 run
= strjoin(paths
->runtime_config
, "/", name
);
6807 if (access(path
, F_OK
) >= 0) {
6808 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run
, path
);
6822 static int unit_file_create_new(
6823 const LookupPaths
*paths
,
6824 const char *unit_name
,
6826 char **ret_new_path
,
6827 char **ret_tmp_path
) {
6829 char *tmp_new_path
, *tmp_tmp_path
, *ending
;
6833 assert(ret_new_path
);
6834 assert(ret_tmp_path
);
6836 ending
= strjoina(unit_name
, suffix
);
6837 r
= get_file_to_edit(paths
, ending
, &tmp_new_path
);
6841 r
= create_edit_temp_file(tmp_new_path
, tmp_new_path
, &tmp_tmp_path
);
6847 *ret_new_path
= tmp_new_path
;
6848 *ret_tmp_path
= tmp_tmp_path
;
6853 static int unit_file_create_copy(
6854 const LookupPaths
*paths
,
6855 const char *unit_name
,
6856 const char *fragment_path
,
6857 char **ret_new_path
,
6858 char **ret_tmp_path
) {
6860 char *tmp_new_path
, *tmp_tmp_path
;
6863 assert(fragment_path
);
6865 assert(ret_new_path
);
6866 assert(ret_tmp_path
);
6868 r
= get_file_to_edit(paths
, unit_name
, &tmp_new_path
);
6872 if (!path_equal(fragment_path
, tmp_new_path
) && access(tmp_new_path
, F_OK
) == 0) {
6875 r
= ask_char(&response
, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path
, fragment_path
);
6880 if (response
!= 'y') {
6881 log_warning("%s ignored", unit_name
);
6883 return -EKEYREJECTED
;
6887 r
= create_edit_temp_file(tmp_new_path
, fragment_path
, &tmp_tmp_path
);
6893 *ret_new_path
= tmp_new_path
;
6894 *ret_tmp_path
= tmp_tmp_path
;
6899 static int run_editor(char **paths
) {
6907 return log_error_errno(errno
, "Failed to fork: %m");
6911 char *editor
, **editor_args
= NULL
;
6912 char **tmp_path
, **original_path
, *p
;
6913 unsigned n_editor_args
= 0, i
= 1;
6916 (void) reset_all_signal_handlers();
6917 (void) reset_signal_mask();
6919 argc
= strv_length(paths
)/2 + 1;
6921 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6922 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6923 * we try to execute well known editors
6925 editor
= getenv("SYSTEMD_EDITOR");
6927 editor
= getenv("EDITOR");
6929 editor
= getenv("VISUAL");
6931 if (!isempty(editor
)) {
6932 editor_args
= strv_split(editor
, WHITESPACE
);
6935 _exit(EXIT_FAILURE
);
6937 n_editor_args
= strv_length(editor_args
);
6938 argc
+= n_editor_args
- 1;
6940 args
= newa(const char*, argc
+ 1);
6942 if (n_editor_args
> 0) {
6943 args
[0] = editor_args
[0];
6944 for (; i
< n_editor_args
; i
++)
6945 args
[i
] = editor_args
[i
];
6948 STRV_FOREACH_PAIR(original_path
, tmp_path
, paths
) {
6949 args
[i
] = *tmp_path
;
6954 if (n_editor_args
> 0)
6955 execvp(args
[0], (char* const*) args
);
6957 FOREACH_STRING(p
, "editor", "nano", "vim", "vi") {
6959 execvp(p
, (char* const*) args
);
6960 /* We do not fail if the editor doesn't exist
6961 * because we want to try each one of them before
6964 if (errno
!= ENOENT
) {
6965 log_error_errno(errno
, "Failed to execute %s: %m", editor
);
6966 _exit(EXIT_FAILURE
);
6970 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6971 _exit(EXIT_FAILURE
);
6974 r
= wait_for_terminate_and_warn("editor", pid
, true);
6976 return log_error_errno(r
, "Failed to wait for child: %m");
6981 static int find_paths_to_edit(sd_bus
*bus
, char **names
, char ***paths
) {
6982 _cleanup_lookup_paths_free_ LookupPaths lp
= {};
6989 r
= lookup_paths_init(&lp
, arg_scope
, 0, arg_root
);
6993 STRV_FOREACH(name
, names
) {
6994 _cleanup_free_
char *path
= NULL
, *new_path
= NULL
, *tmp_path
= NULL
, *tmp_name
= NULL
;
6995 const char *unit_name
;
6997 r
= unit_find_paths(bus
, *name
, &lp
, &path
, NULL
);
7005 log_error("Run 'systemctl edit%s --force %s' to create a new unit.",
7006 arg_scope
== UNIT_FILE_GLOBAL
? " --global" :
7007 arg_scope
== UNIT_FILE_USER
? " --user" : "",
7012 /* Create a new unit from scratch */
7014 r
= unit_file_create_new(&lp
, unit_name
,
7015 arg_full
? NULL
: ".d/override.conf",
7016 &new_path
, &tmp_path
);
7020 unit_name
= basename(path
);
7021 /* We follow unit aliases, but we need to propagate the instance */
7022 if (unit_name_is_valid(*name
, UNIT_NAME_INSTANCE
) &&
7023 unit_name_is_valid(unit_name
, UNIT_NAME_TEMPLATE
)) {
7024 _cleanup_free_
char *instance
= NULL
;
7026 r
= unit_name_to_instance(*name
, &instance
);
7030 r
= unit_name_replace_instance(unit_name
, instance
, &tmp_name
);
7034 unit_name
= tmp_name
;
7038 r
= unit_file_create_copy(&lp
, unit_name
, path
, &new_path
, &tmp_path
);
7040 r
= unit_file_create_new(&lp
, unit_name
, ".d/override.conf", &new_path
, &tmp_path
);
7045 r
= strv_push_pair(paths
, new_path
, tmp_path
);
7048 new_path
= tmp_path
= NULL
;
7054 static int edit(int argc
, char *argv
[], void *userdata
) {
7055 _cleanup_strv_free_
char **names
= NULL
;
7056 _cleanup_strv_free_
char **paths
= NULL
;
7057 char **original
, **tmp
;
7062 log_error("Cannot edit units if not on a tty.");
7066 if (arg_transport
!= BUS_TRANSPORT_LOCAL
) {
7067 log_error("Cannot edit units remotely.");
7071 r
= acquire_bus(BUS_MANAGER
, &bus
);
7075 r
= expand_names(bus
, strv_skip(argv
, 1), NULL
, &names
);
7077 return log_error_errno(r
, "Failed to expand names: %m");
7079 r
= find_paths_to_edit(bus
, names
, &paths
);
7083 if (strv_isempty(paths
))
7086 r
= run_editor(paths
);
7090 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7091 /* If the temporary file is empty we ignore it. It's
7092 * useful if the user wants to cancel its modification
7094 if (null_or_empty_path(*tmp
)) {
7095 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original
);
7099 r
= rename(*tmp
, *original
);
7101 r
= log_error_errno(errno
, "Failed to rename \"%s\" to \"%s\": %m", *tmp
, *original
);
7108 if (!arg_no_reload
&& !install_client_side())
7109 r
= daemon_reload(argc
, argv
, userdata
);
7112 STRV_FOREACH_PAIR(original
, tmp
, paths
) {
7113 (void) unlink(*tmp
);
7115 /* Removing empty dropin dirs */
7117 _cleanup_free_
char *dir
;
7119 dir
= dirname_malloc(*original
);
7123 /* no need to check if the dir is empty, rmdir
7124 * does nothing if it is not the case.
7133 static void systemctl_help(void) {
7135 pager_open(arg_no_pager
, false);
7137 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
7138 "Query or send control commands to the systemd manager.\n\n"
7139 " -h --help Show this help\n"
7140 " --version Show package version\n"
7141 " --system Connect to system manager\n"
7142 " --user Connect to user service manager\n"
7143 " -H --host=[USER@]HOST\n"
7144 " Operate on remote host\n"
7145 " -M --machine=CONTAINER\n"
7146 " Operate on local container\n"
7147 " -t --type=TYPE List units of a particular type\n"
7148 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
7149 " -p --property=NAME Show only properties by this name\n"
7150 " -a --all Show all properties/all units currently in memory,\n"
7151 " including dead/empty ones. To list all units installed on\n"
7152 " the system, use the 'list-unit-files' command instead.\n"
7153 " --failed Same as --state=failed\n"
7154 " -l --full Don't ellipsize unit names on output\n"
7155 " -r --recursive Show unit list of host and local containers\n"
7156 " --reverse Show reverse dependencies with 'list-dependencies'\n"
7157 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
7158 " queueing a new job\n"
7159 " --show-types When showing sockets, explicitly show their type\n"
7160 " --value When showing properties, only print the value\n"
7161 " -i --ignore-inhibitors\n"
7162 " When shutting down or sleeping, ignore inhibitors\n"
7163 " --kill-who=WHO Who to send signal to\n"
7164 " -s --signal=SIGNAL Which signal to send\n"
7165 " --now Start or stop unit in addition to enabling or disabling it\n"
7166 " -q --quiet Suppress output\n"
7167 " --wait For (re)start, wait until service stopped again\n"
7168 " --no-block Do not wait until operation finished\n"
7169 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7170 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
7171 " --no-legend Do not print a legend (column headers and hints)\n"
7172 " --no-pager Do not pipe output into a pager\n"
7173 " --no-ask-password\n"
7174 " Do not ask for system passwords\n"
7175 " --global Enable/disable/mask unit files globally\n"
7176 " --runtime Enable/disable/mask unit files temporarily until next\n"
7178 " -f --force When enabling unit files, override existing symlinks\n"
7179 " When shutting down, execute action immediately\n"
7180 " --preset-mode= Apply only enable, only disable, or all presets\n"
7181 " --root=PATH Enable/disable/mask unit files in the specified root\n"
7183 " -n --lines=INTEGER Number of journal entries to show\n"
7184 " -o --output=STRING Change journal output mode (short, short-precise,\n"
7185 " short-iso, short-iso-precise, short-full,\n"
7186 " short-monotonic, short-unix,\n"
7187 " verbose, export, json, json-pretty, json-sse, cat)\n"
7188 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
7189 " --plain Print unit dependencies as a list instead of a tree\n\n"
7191 " list-units [PATTERN...] List units currently in memory\n"
7192 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
7194 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
7196 " start NAME... Start (activate) one or more units\n"
7197 " stop NAME... Stop (deactivate) one or more units\n"
7198 " reload NAME... Reload one or more units\n"
7199 " restart NAME... Start or restart one or more units\n"
7200 " try-restart NAME... Restart one or more units if active\n"
7201 " reload-or-restart NAME... Reload one or more units if possible,\n"
7202 " otherwise start or restart\n"
7203 " try-reload-or-restart NAME... If active, reload one or more units,\n"
7204 " if supported, otherwise restart\n"
7205 " isolate NAME Start one unit and stop all others\n"
7206 " kill NAME... Send signal to processes of a unit\n"
7207 " is-active PATTERN... Check whether units are active\n"
7208 " is-failed PATTERN... Check whether units are failed\n"
7209 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7210 " show [PATTERN...|JOB...] Show properties of one or more\n"
7211 " units/jobs or the manager\n"
7212 " cat PATTERN... Show files and drop-ins of one or more units\n"
7213 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
7214 " help PATTERN...|PID... Show manual for one or more units\n"
7215 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7217 " list-dependencies [NAME] Recursively show units which are required\n"
7218 " or wanted by this unit or by which this\n"
7219 " unit is required or wanted\n\n"
7220 "Unit File Commands:\n"
7221 " list-unit-files [PATTERN...] List installed unit files\n"
7222 " enable [NAME...|PATH...] Enable one or more unit files\n"
7223 " disable NAME... Disable one or more unit files\n"
7224 " reenable NAME... Reenable one or more unit files\n"
7225 " preset NAME... Enable/disable one or more unit files\n"
7226 " based on preset configuration\n"
7227 " preset-all Enable/disable all unit files based on\n"
7228 " preset configuration\n"
7229 " is-enabled NAME... Check whether unit files are enabled\n"
7230 " mask NAME... Mask one or more units\n"
7231 " unmask NAME... Unmask one or more units\n"
7232 " link PATH... Link one or more units files into\n"
7233 " the search path\n"
7234 " revert NAME... Revert one or more unit files to vendor\n"
7236 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
7237 " on specified one or more units\n"
7238 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
7239 " on specified one or more units\n"
7240 " edit NAME... Edit one or more unit files\n"
7241 " get-default Get the name of the default target\n"
7242 " set-default NAME Set the default target\n\n"
7243 "Machine Commands:\n"
7244 " list-machines [PATTERN...] List local containers and host\n\n"
7246 " list-jobs [PATTERN...] List jobs\n"
7247 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7248 "Environment Commands:\n"
7249 " show-environment Dump environment\n"
7250 " set-environment NAME=VALUE... Set one or more environment variables\n"
7251 " unset-environment NAME... Unset one or more environment variables\n"
7252 " import-environment [NAME...] Import all or some environment variables\n\n"
7253 "Manager Lifecycle Commands:\n"
7254 " daemon-reload Reload systemd manager configuration\n"
7255 " daemon-reexec Reexecute systemd manager\n\n"
7256 "System Commands:\n"
7257 " is-system-running Check whether system is fully running\n"
7258 " default Enter system default mode\n"
7259 " rescue Enter system rescue mode\n"
7260 " emergency Enter system emergency mode\n"
7261 " halt Shut down and halt the system\n"
7262 " poweroff Shut down and power-off the system\n"
7263 " reboot [ARG] Shut down and reboot the system\n"
7264 " kexec Shut down and reboot the system with kexec\n"
7265 " exit [EXIT_CODE] Request user instance or container exit\n"
7266 " switch-root ROOT [INIT] Change to a different root file system\n"
7267 " suspend Suspend the system\n"
7268 " hibernate Hibernate the system\n"
7269 " hybrid-sleep Hibernate and suspend the system\n",
7270 program_invocation_short_name
);
7273 static void halt_help(void) {
7274 printf("%s [OPTIONS...]%s\n\n"
7275 "%s the system.\n\n"
7276 " --help Show this help\n"
7277 " --halt Halt the machine\n"
7278 " -p --poweroff Switch off the machine\n"
7279 " --reboot Reboot the machine\n"
7280 " -f --force Force immediate halt/power-off/reboot\n"
7281 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7282 " -d --no-wtmp Don't write wtmp record\n"
7283 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7284 program_invocation_short_name
,
7285 arg_action
== ACTION_REBOOT
? " [ARG]" : "",
7286 arg_action
== ACTION_REBOOT
? "Reboot" :
7287 arg_action
== ACTION_POWEROFF
? "Power off" :
7291 static void shutdown_help(void) {
7292 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7293 "Shut down the system.\n\n"
7294 " --help Show this help\n"
7295 " -H --halt Halt the machine\n"
7296 " -P --poweroff Power-off the machine\n"
7297 " -r --reboot Reboot the machine\n"
7298 " -h Equivalent to --poweroff, overridden by --halt\n"
7299 " -k Don't halt/power-off/reboot, just send warnings\n"
7300 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7301 " -c Cancel a pending shutdown\n",
7302 program_invocation_short_name
);
7305 static void telinit_help(void) {
7306 printf("%s [OPTIONS...] {COMMAND}\n\n"
7307 "Send control commands to the init daemon.\n\n"
7308 " --help Show this help\n"
7309 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7311 " 0 Power-off the machine\n"
7312 " 6 Reboot the machine\n"
7313 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7314 " 1, s, S Enter rescue mode\n"
7315 " q, Q Reload init daemon configuration\n"
7316 " u, U Reexecute init daemon\n",
7317 program_invocation_short_name
);
7320 static void runlevel_help(void) {
7321 printf("%s [OPTIONS...]\n\n"
7322 "Prints the previous and current runlevel of the init system.\n\n"
7323 " --help Show this help\n",
7324 program_invocation_short_name
);
7327 static void help_types(void) {
7331 puts("Available unit types:");
7332 for (i
= 0; i
< _UNIT_TYPE_MAX
; i
++)
7333 puts(unit_type_to_string(i
));
7336 static void help_states(void) {
7340 puts("Available unit load states:");
7341 for (i
= 0; i
< _UNIT_LOAD_STATE_MAX
; i
++)
7342 puts(unit_load_state_to_string(i
));
7345 puts("\nAvailable unit active states:");
7346 for (i
= 0; i
< _UNIT_ACTIVE_STATE_MAX
; i
++)
7347 puts(unit_active_state_to_string(i
));
7350 puts("\nAvailable automount unit substates:");
7351 for (i
= 0; i
< _AUTOMOUNT_STATE_MAX
; i
++)
7352 puts(automount_state_to_string(i
));
7355 puts("\nAvailable device unit substates:");
7356 for (i
= 0; i
< _DEVICE_STATE_MAX
; i
++)
7357 puts(device_state_to_string(i
));
7360 puts("\nAvailable mount unit substates:");
7361 for (i
= 0; i
< _MOUNT_STATE_MAX
; i
++)
7362 puts(mount_state_to_string(i
));
7365 puts("\nAvailable path unit substates:");
7366 for (i
= 0; i
< _PATH_STATE_MAX
; i
++)
7367 puts(path_state_to_string(i
));
7370 puts("\nAvailable scope unit substates:");
7371 for (i
= 0; i
< _SCOPE_STATE_MAX
; i
++)
7372 puts(scope_state_to_string(i
));
7375 puts("\nAvailable service unit substates:");
7376 for (i
= 0; i
< _SERVICE_STATE_MAX
; i
++)
7377 puts(service_state_to_string(i
));
7380 puts("\nAvailable slice unit substates:");
7381 for (i
= 0; i
< _SLICE_STATE_MAX
; i
++)
7382 puts(slice_state_to_string(i
));
7385 puts("\nAvailable socket unit substates:");
7386 for (i
= 0; i
< _SOCKET_STATE_MAX
; i
++)
7387 puts(socket_state_to_string(i
));
7390 puts("\nAvailable swap unit substates:");
7391 for (i
= 0; i
< _SWAP_STATE_MAX
; i
++)
7392 puts(swap_state_to_string(i
));
7395 puts("\nAvailable target unit substates:");
7396 for (i
= 0; i
< _TARGET_STATE_MAX
; i
++)
7397 puts(target_state_to_string(i
));
7400 puts("\nAvailable timer unit substates:");
7401 for (i
= 0; i
< _TIMER_STATE_MAX
; i
++)
7402 puts(timer_state_to_string(i
));
7405 static int systemctl_parse_argv(int argc
, char *argv
[]) {
7414 ARG_IGNORE_DEPENDENCIES
,
7427 ARG_NO_ASK_PASSWORD
,
7441 static const struct option options
[] = {
7442 { "help", no_argument
, NULL
, 'h' },
7443 { "version", no_argument
, NULL
, ARG_VERSION
},
7444 { "type", required_argument
, NULL
, 't' },
7445 { "property", required_argument
, NULL
, 'p' },
7446 { "all", no_argument
, NULL
, 'a' },
7447 { "reverse", no_argument
, NULL
, ARG_REVERSE
},
7448 { "after", no_argument
, NULL
, ARG_AFTER
},
7449 { "before", no_argument
, NULL
, ARG_BEFORE
},
7450 { "show-types", no_argument
, NULL
, ARG_SHOW_TYPES
},
7451 { "failed", no_argument
, NULL
, ARG_FAILED
}, /* compatibility only */
7452 { "full", no_argument
, NULL
, 'l' },
7453 { "job-mode", required_argument
, NULL
, ARG_JOB_MODE
},
7454 { "fail", no_argument
, NULL
, ARG_FAIL
}, /* compatibility only */
7455 { "irreversible", no_argument
, NULL
, ARG_IRREVERSIBLE
}, /* compatibility only */
7456 { "ignore-dependencies", no_argument
, NULL
, ARG_IGNORE_DEPENDENCIES
}, /* compatibility only */
7457 { "ignore-inhibitors", no_argument
, NULL
, 'i' },
7458 { "value", no_argument
, NULL
, ARG_VALUE
},
7459 { "user", no_argument
, NULL
, ARG_USER
},
7460 { "system", no_argument
, NULL
, ARG_SYSTEM
},
7461 { "global", no_argument
, NULL
, ARG_GLOBAL
},
7462 { "wait", no_argument
, NULL
, ARG_WAIT
},
7463 { "no-block", no_argument
, NULL
, ARG_NO_BLOCK
},
7464 { "no-legend", no_argument
, NULL
, ARG_NO_LEGEND
},
7465 { "no-pager", no_argument
, NULL
, ARG_NO_PAGER
},
7466 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7467 { "quiet", no_argument
, NULL
, 'q' },
7468 { "root", required_argument
, NULL
, ARG_ROOT
},
7469 { "force", no_argument
, NULL
, ARG_FORCE
},
7470 { "no-reload", no_argument
, NULL
, ARG_NO_RELOAD
},
7471 { "kill-who", required_argument
, NULL
, ARG_KILL_WHO
},
7472 { "signal", required_argument
, NULL
, 's' },
7473 { "no-ask-password", no_argument
, NULL
, ARG_NO_ASK_PASSWORD
},
7474 { "host", required_argument
, NULL
, 'H' },
7475 { "machine", required_argument
, NULL
, 'M' },
7476 { "runtime", no_argument
, NULL
, ARG_RUNTIME
},
7477 { "lines", required_argument
, NULL
, 'n' },
7478 { "output", required_argument
, NULL
, 'o' },
7479 { "plain", no_argument
, NULL
, ARG_PLAIN
},
7480 { "state", required_argument
, NULL
, ARG_STATE
},
7481 { "recursive", no_argument
, NULL
, 'r' },
7482 { "preset-mode", required_argument
, NULL
, ARG_PRESET_MODE
},
7483 { "firmware-setup", no_argument
, NULL
, ARG_FIRMWARE_SETUP
},
7484 { "now", no_argument
, NULL
, ARG_NOW
},
7485 { "message", required_argument
, NULL
, ARG_MESSAGE
},
7495 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7496 arg_ask_password
= true;
7498 while ((c
= getopt_long(argc
, argv
, "ht:p:alqfs:H:M:n:o:ir", options
, NULL
)) >= 0)
7510 if (isempty(optarg
)) {
7511 log_error("--type= requires arguments.");
7515 for (p
= optarg
;;) {
7516 _cleanup_free_
char *type
= NULL
;
7518 r
= extract_first_word(&p
, &type
, ",", 0);
7520 return log_error_errno(r
, "Failed to parse type: %s", optarg
);
7524 if (streq(type
, "help")) {
7529 if (unit_type_from_string(type
) >= 0) {
7530 if (strv_push(&arg_types
, type
) < 0)
7536 /* It's much nicer to use --state= for
7537 * load states, but let's support this
7538 * in --types= too for compatibility
7539 * with old versions */
7540 if (unit_load_state_from_string(type
) >= 0) {
7541 if (strv_push(&arg_states
, type
) < 0)
7547 log_error("Unknown unit type or load state '%s'.", type
);
7548 log_info("Use -t help to see a list of allowed values.");
7556 /* Make sure that if the empty property list
7557 was specified, we won't show any properties. */
7558 if (isempty(optarg
) && !arg_properties
) {
7559 arg_properties
= new0(char*, 1);
7560 if (!arg_properties
)
7563 for (p
= optarg
;;) {
7564 _cleanup_free_
char *prop
= NULL
;
7566 r
= extract_first_word(&p
, &prop
, ",", 0);
7568 return log_error_errno(r
, "Failed to parse property: %s", optarg
);
7572 if (strv_push(&arg_properties
, prop
) < 0)
7578 /* If the user asked for a particular
7579 * property, show it to him, even if it is
7591 arg_dependency
= DEPENDENCY_REVERSE
;
7595 arg_dependency
= DEPENDENCY_AFTER
;
7596 arg_jobs_after
= true;
7600 arg_dependency
= DEPENDENCY_BEFORE
;
7601 arg_jobs_before
= true;
7604 case ARG_SHOW_TYPES
:
7605 arg_show_types
= true;
7613 arg_job_mode
= optarg
;
7617 arg_job_mode
= "fail";
7620 case ARG_IRREVERSIBLE
:
7621 arg_job_mode
= "replace-irreversibly";
7624 case ARG_IGNORE_DEPENDENCIES
:
7625 arg_job_mode
= "ignore-dependencies";
7629 arg_scope
= UNIT_FILE_USER
;
7633 arg_scope
= UNIT_FILE_SYSTEM
;
7637 arg_scope
= UNIT_FILE_GLOBAL
;
7645 arg_no_block
= true;
7649 arg_no_legend
= true;
7653 arg_no_pager
= true;
7661 r
= parse_path_argument_and_warn(optarg
, false, &arg_root
);
7671 if (strv_extend(&arg_states
, "failed") < 0)
7689 arg_no_reload
= true;
7693 arg_kill_who
= optarg
;
7697 arg_signal
= signal_from_string_try_harder(optarg
);
7698 if (arg_signal
< 0) {
7699 log_error("Failed to parse signal string %s.", optarg
);
7704 case ARG_NO_ASK_PASSWORD
:
7705 arg_ask_password
= false;
7709 arg_transport
= BUS_TRANSPORT_REMOTE
;
7714 arg_transport
= BUS_TRANSPORT_MACHINE
;
7723 if (safe_atou(optarg
, &arg_lines
) < 0) {
7724 log_error("Failed to parse lines '%s'", optarg
);
7730 arg_output
= output_mode_from_string(optarg
);
7731 if (arg_output
< 0) {
7732 log_error("Unknown output '%s'.", optarg
);
7738 arg_ignore_inhibitors
= true;
7745 case ARG_FIRMWARE_SETUP
:
7746 arg_firmware_setup
= true;
7750 if (isempty(optarg
)) {
7751 log_error("--state= requires arguments.");
7755 for (p
= optarg
;;) {
7756 _cleanup_free_
char *s
= NULL
;
7758 r
= extract_first_word(&p
, &s
, ",", 0);
7760 return log_error_errno(r
, "Failed to parse state: %s", optarg
);
7764 if (streq(s
, "help")) {
7769 if (strv_push(&arg_states
, s
) < 0)
7778 if (geteuid() != 0) {
7779 log_error("--recursive requires root privileges.");
7783 arg_recursive
= true;
7786 case ARG_PRESET_MODE
:
7788 arg_preset_mode
= unit_file_preset_mode_from_string(optarg
);
7789 if (arg_preset_mode
< 0) {
7790 log_error("Failed to parse preset mode: %s.", optarg
);
7801 if (strv_extend(&arg_wall
, optarg
) < 0)
7809 assert_not_reached("Unhandled option");
7812 if (arg_transport
!= BUS_TRANSPORT_LOCAL
&& arg_scope
!= UNIT_FILE_SYSTEM
) {
7813 log_error("Cannot access user instance remotely.");
7817 if (arg_wait
&& arg_no_block
) {
7818 log_error("--wait may not be combined with --no-block.");
7825 static int halt_parse_argv(int argc
, char *argv
[]) {
7834 static const struct option options
[] = {
7835 { "help", no_argument
, NULL
, ARG_HELP
},
7836 { "halt", no_argument
, NULL
, ARG_HALT
},
7837 { "poweroff", no_argument
, NULL
, 'p' },
7838 { "reboot", no_argument
, NULL
, ARG_REBOOT
},
7839 { "force", no_argument
, NULL
, 'f' },
7840 { "wtmp-only", no_argument
, NULL
, 'w' },
7841 { "no-wtmp", no_argument
, NULL
, 'd' },
7842 { "no-sync", no_argument
, NULL
, 'n' },
7843 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7852 if (utmp_get_runlevel(&runlevel
, NULL
) >= 0)
7853 if (IN_SET(runlevel
, '0', '6'))
7856 while ((c
= getopt_long(argc
, argv
, "pfwdnih", options
, NULL
)) >= 0)
7864 arg_action
= ACTION_HALT
;
7868 if (arg_action
!= ACTION_REBOOT
)
7869 arg_action
= ACTION_POWEROFF
;
7873 arg_action
= ACTION_REBOOT
;
7898 /* Compatibility nops */
7905 assert_not_reached("Unhandled option");
7908 if (arg_action
== ACTION_REBOOT
&& (argc
== optind
|| argc
== optind
+ 1)) {
7909 r
= update_reboot_parameter_and_warn(argc
== optind
+ 1 ? argv
[optind
] : NULL
);
7912 } else if (optind
< argc
) {
7913 log_error("Too many arguments.");
7920 static int parse_shutdown_time_spec(const char *t
, usec_t
*_u
) {
7924 if (streq(t
, "now"))
7926 else if (!strchr(t
, ':')) {
7929 if (safe_atou64(t
, &u
) < 0)
7932 *_u
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
* u
;
7941 hour
= strtol(t
, &e
, 10);
7942 if (errno
> 0 || *e
!= ':' || hour
< 0 || hour
> 23)
7945 minute
= strtol(e
+1, &e
, 10);
7946 if (errno
> 0 || *e
!= 0 || minute
< 0 || minute
> 59)
7949 n
= now(CLOCK_REALTIME
);
7950 s
= (time_t) (n
/ USEC_PER_SEC
);
7952 assert_se(localtime_r(&s
, &tm
));
7954 tm
.tm_hour
= (int) hour
;
7955 tm
.tm_min
= (int) minute
;
7958 assert_se(s
= mktime(&tm
));
7960 *_u
= (usec_t
) s
* USEC_PER_SEC
;
7963 *_u
+= USEC_PER_DAY
;
7969 static int shutdown_parse_argv(int argc
, char *argv
[]) {
7976 static const struct option options
[] = {
7977 { "help", no_argument
, NULL
, ARG_HELP
},
7978 { "halt", no_argument
, NULL
, 'H' },
7979 { "poweroff", no_argument
, NULL
, 'P' },
7980 { "reboot", no_argument
, NULL
, 'r' },
7981 { "kexec", no_argument
, NULL
, 'K' }, /* not documented extension */
7982 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
7992 while ((c
= getopt_long(argc
, argv
, "HPrhkKtafFc", options
, NULL
)) >= 0)
8000 arg_action
= ACTION_HALT
;
8004 arg_action
= ACTION_POWEROFF
;
8009 arg_action
= ACTION_KEXEC
;
8011 arg_action
= ACTION_REBOOT
;
8015 arg_action
= ACTION_KEXEC
;
8019 if (arg_action
!= ACTION_HALT
)
8020 arg_action
= ACTION_POWEROFF
;
8035 /* Compatibility nops */
8039 arg_action
= ACTION_CANCEL_SHUTDOWN
;
8046 assert_not_reached("Unhandled option");
8049 if (argc
> optind
&& arg_action
!= ACTION_CANCEL_SHUTDOWN
) {
8050 r
= parse_shutdown_time_spec(argv
[optind
], &arg_when
);
8052 log_error("Failed to parse time specification: %s", argv
[optind
]);
8056 arg_when
= now(CLOCK_REALTIME
) + USEC_PER_MINUTE
;
8058 if (argc
> optind
&& arg_action
== ACTION_CANCEL_SHUTDOWN
)
8059 /* No time argument for shutdown cancel */
8060 wall
= argv
+ optind
;
8061 else if (argc
> optind
+ 1)
8062 /* We skip the time argument */
8063 wall
= argv
+ optind
+ 1;
8066 arg_wall
= strv_copy(wall
);
8076 static int telinit_parse_argv(int argc
, char *argv
[]) {
8083 static const struct option options
[] = {
8084 { "help", no_argument
, NULL
, ARG_HELP
},
8085 { "no-wall", no_argument
, NULL
, ARG_NO_WALL
},
8089 static const struct {
8093 { '0', ACTION_POWEROFF
},
8094 { '6', ACTION_REBOOT
},
8095 { '1', ACTION_RESCUE
},
8096 { '2', ACTION_RUNLEVEL2
},
8097 { '3', ACTION_RUNLEVEL3
},
8098 { '4', ACTION_RUNLEVEL4
},
8099 { '5', ACTION_RUNLEVEL5
},
8100 { 's', ACTION_RESCUE
},
8101 { 'S', ACTION_RESCUE
},
8102 { 'q', ACTION_RELOAD
},
8103 { 'Q', ACTION_RELOAD
},
8104 { 'u', ACTION_REEXEC
},
8105 { 'U', ACTION_REEXEC
}
8114 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8129 assert_not_reached("Unhandled option");
8132 if (optind
>= argc
) {
8133 log_error("%s: required argument missing.", program_invocation_short_name
);
8137 if (optind
+ 1 < argc
) {
8138 log_error("Too many arguments.");
8142 if (strlen(argv
[optind
]) != 1) {
8143 log_error("Expected single character argument.");
8147 for (i
= 0; i
< ELEMENTSOF(table
); i
++)
8148 if (table
[i
].from
== argv
[optind
][0])
8151 if (i
>= ELEMENTSOF(table
)) {
8152 log_error("Unknown command '%s'.", argv
[optind
]);
8156 arg_action
= table
[i
].to
;
8163 static int runlevel_parse_argv(int argc
, char *argv
[]) {
8169 static const struct option options
[] = {
8170 { "help", no_argument
, NULL
, ARG_HELP
},
8179 while ((c
= getopt_long(argc
, argv
, "", options
, NULL
)) >= 0)
8190 assert_not_reached("Unhandled option");
8193 if (optind
< argc
) {
8194 log_error("Too many arguments.");
8201 static int parse_argv(int argc
, char *argv
[]) {
8205 if (program_invocation_short_name
) {
8207 if (strstr(program_invocation_short_name
, "halt")) {
8208 arg_action
= ACTION_HALT
;
8209 return halt_parse_argv(argc
, argv
);
8210 } else if (strstr(program_invocation_short_name
, "poweroff")) {
8211 arg_action
= ACTION_POWEROFF
;
8212 return halt_parse_argv(argc
, argv
);
8213 } else if (strstr(program_invocation_short_name
, "reboot")) {
8215 arg_action
= ACTION_KEXEC
;
8217 arg_action
= ACTION_REBOOT
;
8218 return halt_parse_argv(argc
, argv
);
8219 } else if (strstr(program_invocation_short_name
, "shutdown")) {
8220 arg_action
= ACTION_POWEROFF
;
8221 return shutdown_parse_argv(argc
, argv
);
8222 } else if (strstr(program_invocation_short_name
, "init")) {
8224 if (sd_booted() > 0) {
8225 arg_action
= _ACTION_INVALID
;
8226 return telinit_parse_argv(argc
, argv
);
8228 /* Hmm, so some other init system is
8229 * running, we need to forward this
8230 * request to it. For now we simply
8231 * guess that it is Upstart. */
8233 execv(TELINIT
, argv
);
8235 log_error("Couldn't find an alternative telinit implementation to spawn.");
8239 } else if (strstr(program_invocation_short_name
, "runlevel")) {
8240 arg_action
= ACTION_RUNLEVEL
;
8241 return runlevel_parse_argv(argc
, argv
);
8245 arg_action
= ACTION_SYSTEMCTL
;
8246 return systemctl_parse_argv(argc
, argv
);
8249 #if HAVE_SYSV_COMPAT
8250 _pure_
static int action_to_runlevel(void) {
8252 static const char table
[_ACTION_MAX
] = {
8253 [ACTION_HALT
] = '0',
8254 [ACTION_POWEROFF
] = '0',
8255 [ACTION_REBOOT
] = '6',
8256 [ACTION_RUNLEVEL2
] = '2',
8257 [ACTION_RUNLEVEL3
] = '3',
8258 [ACTION_RUNLEVEL4
] = '4',
8259 [ACTION_RUNLEVEL5
] = '5',
8260 [ACTION_RESCUE
] = '1'
8263 assert(arg_action
>= 0 && arg_action
< _ACTION_MAX
);
8265 return table
[arg_action
];
8269 static int talk_initctl(void) {
8270 #if HAVE_SYSV_COMPAT
8271 struct init_request request
= {
8272 .magic
= INIT_MAGIC
,
8274 .cmd
= INIT_CMD_RUNLVL
8277 _cleanup_close_
int fd
= -1;
8281 rl
= action_to_runlevel();
8285 request
.runlevel
= rl
;
8287 fd
= open(INIT_FIFO
, O_WRONLY
|O_NDELAY
|O_CLOEXEC
|O_NOCTTY
);
8289 if (errno
== ENOENT
)
8292 return log_error_errno(errno
, "Failed to open "INIT_FIFO
": %m");
8295 r
= loop_write(fd
, &request
, sizeof(request
), false);
8297 return log_error_errno(r
, "Failed to write to "INIT_FIFO
": %m");
8305 static int systemctl_main(int argc
, char *argv
[]) {
8307 static const Verb verbs
[] = {
8308 { "list-units", VERB_ANY
, VERB_ANY
, VERB_DEFAULT
|VERB_NOCHROOT
, list_units
},
8309 { "list-unit-files", VERB_ANY
, VERB_ANY
, 0, list_unit_files
},
8310 { "list-sockets", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_sockets
},
8311 { "list-timers", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_timers
},
8312 { "list-jobs", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_jobs
},
8313 { "list-machines", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, list_machines
},
8314 { "clear-jobs", VERB_ANY
, 1, VERB_NOCHROOT
, trivial_method
},
8315 { "cancel", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, cancel_job
},
8316 { "start", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8317 { "stop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8318 { "condstop", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8319 { "reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8320 { "restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8321 { "try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8322 { "reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8323 { "reload-or-try-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatbility with old systemctl <= 228 */
8324 { "try-reload-or-restart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
},
8325 { "force-reload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with SysV */
8326 { "condreload", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with ALTLinux */
8327 { "condrestart", 2, VERB_ANY
, VERB_NOCHROOT
, start_unit
}, /* For compatibility with RH */
8328 { "isolate", 2, 2, VERB_NOCHROOT
, start_unit
},
8329 { "kill", 2, VERB_ANY
, VERB_NOCHROOT
, kill_unit
},
8330 { "is-active", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8331 { "check", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_active
},
8332 { "is-failed", 2, VERB_ANY
, VERB_NOCHROOT
, check_unit_failed
},
8333 { "show", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8334 { "cat", 2, VERB_ANY
, VERB_NOCHROOT
, cat
},
8335 { "status", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8336 { "help", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, show
},
8337 { "daemon-reload", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8338 { "daemon-reexec", VERB_ANY
, 1, VERB_NOCHROOT
, daemon_reload
},
8339 { "show-environment", VERB_ANY
, 1, VERB_NOCHROOT
, show_environment
},
8340 { "set-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8341 { "unset-environment", 2, VERB_ANY
, VERB_NOCHROOT
, set_environment
},
8342 { "import-environment", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, import_environment
},
8343 { "halt", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8344 { "poweroff", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8345 { "reboot", VERB_ANY
, 2, VERB_NOCHROOT
, start_system_special
},
8346 { "kexec", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8347 { "suspend", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8348 { "hibernate", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8349 { "hybrid-sleep", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8350 { "default", VERB_ANY
, 1, VERB_NOCHROOT
, start_special
},
8351 { "rescue", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8352 { "emergency", VERB_ANY
, 1, VERB_NOCHROOT
, start_system_special
},
8353 { "exit", VERB_ANY
, 2, VERB_NOCHROOT
, start_special
},
8354 { "reset-failed", VERB_ANY
, VERB_ANY
, VERB_NOCHROOT
, reset_failed
},
8355 { "enable", 2, VERB_ANY
, 0, enable_unit
},
8356 { "disable", 2, VERB_ANY
, 0, enable_unit
},
8357 { "is-enabled", 2, VERB_ANY
, 0, unit_is_enabled
},
8358 { "reenable", 2, VERB_ANY
, 0, enable_unit
},
8359 { "preset", 2, VERB_ANY
, 0, enable_unit
},
8360 { "preset-all", VERB_ANY
, 1, 0, preset_all
},
8361 { "mask", 2, VERB_ANY
, 0, enable_unit
},
8362 { "unmask", 2, VERB_ANY
, 0, enable_unit
},
8363 { "link", 2, VERB_ANY
, 0, enable_unit
},
8364 { "revert", 2, VERB_ANY
, 0, enable_unit
},
8365 { "switch-root", 2, VERB_ANY
, VERB_NOCHROOT
, switch_root
},
8366 { "list-dependencies", VERB_ANY
, 2, VERB_NOCHROOT
, list_dependencies
},
8367 { "set-default", 2, 2, 0, set_default
},
8368 { "get-default", VERB_ANY
, 1, 0, get_default
},
8369 { "set-property", 3, VERB_ANY
, VERB_NOCHROOT
, set_property
},
8370 { "is-system-running", VERB_ANY
, 1, 0, is_system_running
},
8371 { "add-wants", 3, VERB_ANY
, 0, add_dependency
},
8372 { "add-requires", 3, VERB_ANY
, 0, add_dependency
},
8373 { "edit", 2, VERB_ANY
, VERB_NOCHROOT
, edit
},
8377 return dispatch_verb(argc
, argv
, verbs
, NULL
);
8380 static int reload_with_fallback(void) {
8382 /* First, try systemd via D-Bus. */
8383 if (daemon_reload(0, NULL
, NULL
) >= 0)
8386 /* Nothing else worked, so let's try signals */
8387 assert(IN_SET(arg_action
, ACTION_RELOAD
, ACTION_REEXEC
));
8389 if (kill(1, arg_action
== ACTION_RELOAD
? SIGHUP
: SIGTERM
) < 0)
8390 return log_error_errno(errno
, "kill() failed: %m");
8395 static int start_with_fallback(void) {
8397 /* First, try systemd via D-Bus. */
8398 if (start_unit(0, NULL
, NULL
) >= 0)
8401 /* Nothing else worked, so let's try /dev/initctl */
8402 if (talk_initctl() > 0)
8405 log_error("Failed to talk to init daemon.");
8409 static int halt_now(enum action a
) {
8412 /* The kernel will automaticall flush ATA disks and suchlike
8413 * on reboot(), but the file systems need to be synce'd
8414 * explicitly in advance. */
8418 /* Make sure C-A-D is handled by the kernel from this point
8420 (void) reboot(RB_ENABLE_CAD
);
8426 log_info("Halting.");
8427 (void) reboot(RB_HALT_SYSTEM
);
8430 case ACTION_POWEROFF
:
8432 log_info("Powering off.");
8433 (void) reboot(RB_POWER_OFF
);
8437 case ACTION_REBOOT
: {
8438 _cleanup_free_
char *param
= NULL
;
8440 r
= read_one_line_file("/run/systemd/reboot-param", ¶m
);
8441 if (r
< 0 && r
!= -ENOENT
)
8442 log_warning_errno(r
, "Failed to read reboot parameter file: %m");
8444 if (!isempty(param
)) {
8446 log_info("Rebooting with argument '%s'.", param
);
8447 (void) syscall(SYS_reboot
, LINUX_REBOOT_MAGIC1
, LINUX_REBOOT_MAGIC2
, LINUX_REBOOT_CMD_RESTART2
, param
);
8448 log_warning_errno(errno
, "Failed to reboot with parameter, retrying without: %m");
8452 log_info("Rebooting.");
8453 (void) reboot(RB_AUTOBOOT
);
8458 assert_not_reached("Unknown action.");
8462 static int logind_schedule_shutdown(void) {
8465 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8466 char date
[FORMAT_TIMESTAMP_MAX
];
8471 r
= acquire_bus(BUS_FULL
, &bus
);
8475 switch (arg_action
) {
8479 case ACTION_POWEROFF
:
8480 action
= "poweroff";
8495 action
= strjoina("dry-", action
);
8497 (void) logind_set_wall_message();
8499 r
= sd_bus_call_method(
8501 "org.freedesktop.login1",
8502 "/org/freedesktop/login1",
8503 "org.freedesktop.login1.Manager",
8511 return log_warning_errno(r
, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error
, r
));
8514 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date
, sizeof(date
), arg_when
));
8517 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8522 static int halt_main(void) {
8525 r
= logind_check_inhibitors(arg_action
);
8530 return logind_schedule_shutdown();
8532 if (geteuid() != 0) {
8533 if (arg_dry
|| arg_force
> 0) {
8534 log_error("Must be root.");
8538 /* Try logind if we are a normal user and no special
8539 * mode applies. Maybe PolicyKit allows us to shutdown
8541 if (IN_SET(arg_action
, ACTION_POWEROFF
, ACTION_REBOOT
, ACTION_HALT
)) {
8542 r
= logind_reboot(arg_action
);
8545 if (IN_SET(r
, -EOPNOTSUPP
, -EINPROGRESS
))
8546 /* requested operation is not
8547 * supported on the local system or
8548 * already in progress */
8550 /* on all other errors, try low-level operation */
8554 if (!arg_dry
&& !arg_force
)
8555 return start_with_fallback();
8557 assert(geteuid() == 0);
8560 if (sd_booted() > 0)
8561 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8563 r
= utmp_put_shutdown();
8565 log_warning_errno(r
, "Failed to write utmp record: %m");
8572 r
= halt_now(arg_action
);
8573 return log_error_errno(r
, "Failed to reboot: %m");
8576 static int runlevel_main(void) {
8577 int r
, runlevel
, previous
;
8579 r
= utmp_get_runlevel(&runlevel
, &previous
);
8586 previous
<= 0 ? 'N' : previous
,
8587 runlevel
<= 0 ? 'N' : runlevel
);
8592 static int logind_cancel_shutdown(void) {
8594 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
8598 r
= acquire_bus(BUS_FULL
, &bus
);
8602 (void) logind_set_wall_message();
8604 r
= sd_bus_call_method(
8606 "org.freedesktop.login1",
8607 "/org/freedesktop/login1",
8608 "org.freedesktop.login1.Manager",
8609 "CancelScheduledShutdown",
8613 return log_warning_errno(r
, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error
, r
));
8617 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8622 int main(int argc
, char*argv
[]) {
8625 argv_cmdline
= argv
[0];
8627 setlocale(LC_ALL
, "");
8628 log_parse_environment();
8632 /* Explicitly not on_tty() to avoid setting cached value.
8633 * This becomes relevant for piping output which might be
8635 original_stdout_is_tty
= isatty(STDOUT_FILENO
);
8637 r
= parse_argv(argc
, argv
);
8641 if (arg_action
!= ACTION_SYSTEMCTL
&& running_in_chroot() > 0) {
8644 log_info("Running in chroot, ignoring request.");
8649 /* systemctl_main() will print an error message for the bus
8650 * connection, but only if it needs to */
8652 switch (arg_action
) {
8654 case ACTION_SYSTEMCTL
:
8655 r
= systemctl_main(argc
, argv
);
8658 /* Legacy command aliases set arg_action. They provide some fallbacks,
8659 * e.g. to tell sysvinit to reboot after you have installed systemd
8663 case ACTION_POWEROFF
:
8669 case ACTION_RUNLEVEL2
:
8670 case ACTION_RUNLEVEL3
:
8671 case ACTION_RUNLEVEL4
:
8672 case ACTION_RUNLEVEL5
:
8674 r
= start_with_fallback();
8679 r
= reload_with_fallback();
8682 case ACTION_CANCEL_SHUTDOWN
:
8683 r
= logind_cancel_shutdown();
8686 case ACTION_RUNLEVEL
:
8687 r
= runlevel_main();
8691 case ACTION_SUSPEND
:
8692 case ACTION_HIBERNATE
:
8693 case ACTION_HYBRID_SLEEP
:
8694 case ACTION_EMERGENCY
:
8695 case ACTION_DEFAULT
:
8696 /* systemctl verbs with no equivalent in the legacy commands.
8697 * These cannot appear in arg_action. Fall through. */
8699 case _ACTION_INVALID
:
8701 assert_not_reached("Unknown action");
8708 ask_password_agent_close();
8709 polkit_agent_close();
8711 strv_free(arg_types
);
8712 strv_free(arg_states
);
8713 strv_free(arg_properties
);
8715 strv_free(arg_wall
);
8718 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8719 return r
< 0 ? EXIT_FAILURE
: r
;