mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-26 10:03:40 +03:00
systemctl: allow globbing in list-<whatever> commands
It is nicer to say 'systemctl list-units ssh\*' then to use grep, because colouring is preserved and it is easier to match just against the unit name.
This commit is contained in:
parent
2b6bf07dd2
commit
d8fba7c6cc
@ -526,22 +526,26 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><command>list-units</command></term>
|
||||
<term><command>list-units <optional><replaceable>PATTERN...</replaceable></optional></command></term>
|
||||
|
||||
<listitem>
|
||||
<para>List known units (subject to limitations specified
|
||||
with <option>-t</option>).</para>
|
||||
with <option>-t</option>). If one or more
|
||||
<replaceable>PATTERN</replaceable>s are specified, only
|
||||
units matching one of them are shown.</para>
|
||||
|
||||
<para>This is the default command.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>list-sockets</command></term>
|
||||
<term><command>list-sockets <optional><replaceable>PATTERN...</replaceable></optional></command></term>
|
||||
|
||||
<listitem>
|
||||
<para>List socket units ordered by the listening address. Produces output
|
||||
similar to
|
||||
<para>List socket units ordered by the listening address.
|
||||
If one or more <replaceable>PATTERN</replaceable>s are
|
||||
specified, only socket units matching one of them are
|
||||
shown. Produces output similar to
|
||||
<programlisting>
|
||||
LISTEN UNIT ACTIVATES
|
||||
/dev/initctl systemd-initctl.socket systemd-initctl.service
|
||||
@ -561,10 +565,13 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>list-timers</command></term>
|
||||
<term><command>list-timers <optional><replaceable>PATTERN...</replaceable></optional></command></term>
|
||||
|
||||
<listitem>
|
||||
<para>List timer units ordered by the time they elapse next.</para>
|
||||
<para>List timer units ordered by the time they elapse
|
||||
next. If one or more <replaceable>PATTERN</replaceable>s
|
||||
are specified, only units matching one of them are shown.
|
||||
</para>
|
||||
|
||||
<para>See also the options <option>--all</option> and
|
||||
<option>--failed</option>.</para>
|
||||
@ -814,10 +821,13 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><command>list-unit-files</command></term>
|
||||
<term><command>list-unit-files <optional><replaceable>PATTERN...</replaceable></optional></command></term>
|
||||
|
||||
<listitem>
|
||||
<para>List installed unit files.</para>
|
||||
<para>List installed unit files. If one or more
|
||||
<replaceable>PATTERN</replaceable>s are specified, only
|
||||
units whose filename (just the last component of the path)
|
||||
matches one of them are shown.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -1013,10 +1023,12 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><command>list-jobs</command></term>
|
||||
<term><command>list-jobs <optional><replaceable>PATTERN...</replaceable></optional></command></term>
|
||||
|
||||
<listitem>
|
||||
<para>List jobs that are in progress.</para>
|
||||
<para>List jobs that are in progress. If one or more
|
||||
<replaceable>PATTERN</replaceable>s are specified, only
|
||||
jobs for units matching one of them are shown.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@ -1036,7 +1048,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><command>snapshot [<replaceable>NAME</replaceable>]</command></term>
|
||||
<term><command>snapshot <optional><replaceable>NAME</replaceable></optional></command></term>
|
||||
|
||||
<listitem>
|
||||
<para>Create a snapshot. If a snapshot name is specified,
|
||||
@ -1281,7 +1293,7 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>switch-root <replaceable>ROOT</replaceable> [<replaceable>INIT</replaceable>]</command></term>
|
||||
<term><command>switch-root <replaceable>ROOT</replaceable> <optional><replaceable>INIT</replaceable></optional></command></term>
|
||||
|
||||
<listitem>
|
||||
<para>Switches to a different root directory and executes a
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <fnmatch.h>
|
||||
|
||||
#include "sd-daemon.h"
|
||||
#include "sd-shutdown.h"
|
||||
@ -140,6 +141,12 @@ static int halt_now(enum action a);
|
||||
|
||||
static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
|
||||
|
||||
static char** strv_skip_first(char **strv) {
|
||||
if (strv_length(strv) > 0)
|
||||
return strv + 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pager_open_if_enabled(void) {
|
||||
|
||||
if (arg_no_pager)
|
||||
@ -280,7 +287,7 @@ static int compare_unit_info(const void *a, const void *b) {
|
||||
return strcasecmp(u->id, v->id);
|
||||
}
|
||||
|
||||
static bool output_show_unit(const UnitInfo *u) {
|
||||
static bool output_show_unit(const UnitInfo *u, char **patterns) {
|
||||
const char *dot;
|
||||
|
||||
if (!strv_isempty(arg_states))
|
||||
@ -289,13 +296,22 @@ static bool output_show_unit(const UnitInfo *u) {
|
||||
strv_contains(arg_states, u->sub_state) ||
|
||||
strv_contains(arg_states, u->active_state);
|
||||
|
||||
if (!strv_isempty(patterns)) {
|
||||
char **pattern;
|
||||
|
||||
STRV_FOREACH(pattern, patterns)
|
||||
if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return (!arg_types || ((dot = strrchr(u->id, '.')) &&
|
||||
strv_find(arg_types, dot+1))) &&
|
||||
(arg_all || !(streq(u->active_state, "inactive")
|
||||
|| u->following[0]) || u->job_id > 0);
|
||||
}
|
||||
|
||||
static void output_units_list(const UnitInfo *unit_infos, unsigned c) {
|
||||
static void output_units_list(const UnitInfo *unit_infos, unsigned c, char** patterns) {
|
||||
unsigned id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
|
||||
const UnitInfo *u;
|
||||
unsigned n_shown = 0;
|
||||
@ -309,7 +325,7 @@ static void output_units_list(const UnitInfo *unit_infos, unsigned c) {
|
||||
desc_len = 0;
|
||||
|
||||
for (u = unit_infos; u < unit_infos + c; u++) {
|
||||
if (!output_show_unit(u))
|
||||
if (!output_show_unit(u, patterns))
|
||||
continue;
|
||||
|
||||
max_id_len = MAX(max_id_len, strlen(u->id));
|
||||
@ -358,7 +374,7 @@ static void output_units_list(const UnitInfo *unit_infos, unsigned c) {
|
||||
const char *on_loaded, *off_loaded, *on = "";
|
||||
const char *on_active, *off_active, *off = "";
|
||||
|
||||
if (!output_show_unit(u))
|
||||
if (!output_show_unit(u, patterns))
|
||||
continue;
|
||||
|
||||
if (!n_shown && !arg_no_legend) {
|
||||
@ -504,7 +520,7 @@ static int list_units(sd_bus *bus, char **args) {
|
||||
return r;
|
||||
|
||||
qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
|
||||
output_units_list(unit_infos, r);
|
||||
output_units_list(unit_infos, r, strv_skip_first(args));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -693,7 +709,7 @@ static int list_sockets(sd_bus *bus, char **args) {
|
||||
_cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
|
||||
int i, c;
|
||||
|
||||
if (!output_show_unit(u))
|
||||
if (!output_show_unit(u, strv_skip_first(args)))
|
||||
continue;
|
||||
|
||||
if (!endswith(u->id, ".socket"))
|
||||
@ -910,7 +926,7 @@ static int list_timers(sd_bus *bus, char **args) {
|
||||
dual_timestamp next;
|
||||
usec_t m;
|
||||
|
||||
if (!output_show_unit(u))
|
||||
if (!output_show_unit(u, strv_skip_first(args)))
|
||||
continue;
|
||||
|
||||
if (!endswith(u->id, ".timer"))
|
||||
@ -983,13 +999,22 @@ static int compare_unit_file_list(const void *a, const void *b) {
|
||||
return strcasecmp(basename(u->path), basename(v->path));
|
||||
}
|
||||
|
||||
static bool output_show_unit_file(const UnitFileList *u) {
|
||||
static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
|
||||
const char *dot;
|
||||
|
||||
if (!strv_isempty(patterns)) {
|
||||
char **pattern;
|
||||
|
||||
STRV_FOREACH(pattern, patterns)
|
||||
if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
|
||||
}
|
||||
|
||||
static void output_unit_file_list(const UnitFileList *units, unsigned c) {
|
||||
static void output_unit_file_list(const UnitFileList *units, unsigned c, char **patterns) {
|
||||
unsigned max_id_len, id_cols, state_cols, n_shown = 0;
|
||||
const UnitFileList *u;
|
||||
|
||||
@ -997,7 +1022,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
|
||||
state_cols = sizeof("STATE")-1;
|
||||
|
||||
for (u = units; u < units + c; u++) {
|
||||
if (!output_show_unit_file(u))
|
||||
if (!output_show_unit_file(u, patterns))
|
||||
continue;
|
||||
|
||||
max_id_len = MAX(max_id_len, strlen(basename(u->path)));
|
||||
@ -1024,7 +1049,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
|
||||
const char *on, *off;
|
||||
const char *id;
|
||||
|
||||
if (!output_show_unit_file(u))
|
||||
if (!output_show_unit_file(u, patterns))
|
||||
continue;
|
||||
|
||||
n_shown++;
|
||||
@ -1137,7 +1162,7 @@ static int list_unit_files(sd_bus *bus, char **args) {
|
||||
|
||||
if (c > 0) {
|
||||
qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
|
||||
output_unit_file_list(units, c);
|
||||
output_unit_file_list(units, c, strv_skip_first(args));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1511,7 +1536,7 @@ struct job_info {
|
||||
const char *name, *type, *state;
|
||||
};
|
||||
|
||||
static void output_jobs_list(const struct job_info* jobs, unsigned n) {
|
||||
static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
|
||||
unsigned id_len, unit_len, type_len, state_len;
|
||||
const struct job_info *j;
|
||||
const char *on, *off;
|
||||
@ -1523,7 +1548,7 @@ static void output_jobs_list(const struct job_info* jobs, unsigned n) {
|
||||
on = ansi_highlight_green();
|
||||
off = ansi_highlight_off();
|
||||
|
||||
printf("%sNo jobs running.%s\n", on, off);
|
||||
printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1581,6 +1606,19 @@ static void output_jobs_list(const struct job_info* jobs, unsigned n) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool output_show_job(struct job_info *job, char **patterns) {
|
||||
if (!strv_isempty(patterns)) {
|
||||
char **pattern;
|
||||
|
||||
STRV_FOREACH(pattern, patterns)
|
||||
if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int list_jobs(sd_bus *bus, char **args) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
|
||||
@ -1590,6 +1628,7 @@ static int list_jobs(sd_bus *bus, char **args) {
|
||||
unsigned c = 0;
|
||||
uint32_t id;
|
||||
int r;
|
||||
bool skipped = false;
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
@ -1610,16 +1649,17 @@ static int list_jobs(sd_bus *bus, char **args) {
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
|
||||
struct job_info job = { id, name, type, state };
|
||||
|
||||
if (!output_show_job(&job, strv_skip_first(args))) {
|
||||
skipped = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(jobs, size, c + 1))
|
||||
return log_oom();
|
||||
|
||||
jobs[c++] = (struct job_info) {
|
||||
id,
|
||||
name,
|
||||
type,
|
||||
state
|
||||
};
|
||||
jobs[c++] = job;
|
||||
}
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
@ -1628,7 +1668,7 @@ static int list_jobs(sd_bus *bus, char **args) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
output_jobs_list(jobs, c);
|
||||
output_jobs_list(jobs, c, skipped);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -3661,7 +3701,7 @@ static int show_all(
|
||||
for (u = unit_infos; u < unit_infos + c; u++) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
if (!output_show_unit(u))
|
||||
if (!output_show_unit(u, NULL))
|
||||
continue;
|
||||
|
||||
p = unit_dbus_path_from_name(u->id);
|
||||
@ -4770,9 +4810,9 @@ static int systemctl_help(void) {
|
||||
" -o --output=STRING Change journal output mode (short, short-monotonic,\n"
|
||||
" verbose, export, json, json-pretty, json-sse, cat)\n\n"
|
||||
"Unit Commands:\n"
|
||||
" list-units List loaded units\n"
|
||||
" list-sockets List loaded sockets ordered by address\n"
|
||||
" list-timers List loaded timers ordered by next elapse\n"
|
||||
" list-units [PATTERN...] List loaded units\n"
|
||||
" list-sockets [PATTERN...] List loaded sockets ordered by address\n"
|
||||
" list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
|
||||
" start [NAME...] Start (activate) one or more units\n"
|
||||
" stop [NAME...] Stop (deactivate) one or more units\n"
|
||||
" reload [NAME...] Reload one or more units\n"
|
||||
@ -4799,7 +4839,7 @@ static int systemctl_help(void) {
|
||||
" or wanted by this unit or by which this\n"
|
||||
" unit is required or wanted\n\n"
|
||||
"Unit File Commands:\n"
|
||||
" list-unit-files List installed unit files\n"
|
||||
" list-unit-files [PATTERN...] List installed unit files\n"
|
||||
" enable [NAME...] Enable one or more unit files\n"
|
||||
" disable [NAME...] Disable one or more unit files\n"
|
||||
" reenable [NAME...] Reenable one or more unit files\n"
|
||||
@ -4813,7 +4853,7 @@ static int systemctl_help(void) {
|
||||
" get-default Get the name of the default target\n"
|
||||
" set-default NAME Set the default target\n\n"
|
||||
"Job Commands:\n"
|
||||
" list-jobs List jobs\n"
|
||||
" list-jobs [PATTERN...] List jobs\n"
|
||||
" cancel [JOB...] Cancel all, one, or more jobs\n\n"
|
||||
"Snapshot Commands:\n"
|
||||
" snapshot [NAME] Create a snapshot\n"
|
||||
@ -5749,11 +5789,11 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
|
||||
const int argc;
|
||||
int (* const dispatch)(sd_bus *bus, char **args);
|
||||
} verbs[] = {
|
||||
{ "list-units", LESS, 1, list_units },
|
||||
{ "list-unit-files", EQUAL, 1, list_unit_files },
|
||||
{ "list-sockets", LESS, 1, list_sockets },
|
||||
{ "list-timers", LESS, 1, list_timers },
|
||||
{ "list-jobs", EQUAL, 1, list_jobs },
|
||||
{ "list-units", MORE, 0, list_units },
|
||||
{ "list-unit-files", MORE, 1, list_unit_files },
|
||||
{ "list-sockets", MORE, 1, list_sockets },
|
||||
{ "list-timers", MORE, 1, list_timers },
|
||||
{ "list-jobs", MORE, 1, list_jobs },
|
||||
{ "clear-jobs", EQUAL, 1, daemon_reload },
|
||||
{ "cancel", MORE, 2, cancel_job },
|
||||
{ "start", MORE, 2, start_unit },
|
||||
|
Loading…
x
Reference in New Issue
Block a user