author | Olivier Brunel
<jjk@jjacky.com> 2015-07-16 17:07:06 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2015-07-16 17:07:06 UTC |
parent | 4870232a142a50bf32933a6348733f524cda5470 |
doc/aa-status.pod | +81 | -4 |
src/anopa/aa-status.c | +88 | -1 |
diff --git a/doc/aa-status.pod b/doc/aa-status.pod index 6a86329..3e3dd79 100644 --- a/doc/aa-status.pod +++ b/doc/aa-status.pod @@ -4,8 +4,8 @@ aa-status - Show status of services =head1 SYNOPSIS -B<aa-status> [B<-D>] [B<-r> I<repodir>] [B<-a>] [B<-L>] [B<-l> I<listdir>] -[I<service...>] +B<aa-status> [B<-D>] [B<-r> I<repodir>] [B<-a>] [B<-f> I<filter>] [B<-L>] +[B<-l> I<listdir>] [I<service...>] =head1 OPTIONS @@ -23,6 +23,11 @@ stderr for warnings and errors, everything is sent both to stdout and stderr. This is intended to redirect stderr to a log file, so full output can be both shown on console and logged. +=item B<-f, --filter> I<filter> + +Only process services matching I<filter>. See L<B<FILTERING>|/FILTERING> below +for more. + =item B<-h, --help> Show help screen and exit. @@ -62,7 +67,76 @@ For long-run services it will also check for the I<ready> file to determine whether the service is "Up" or "Ready" (using the timestamp from the I<ready> file in the later case). -=head1 POSSIBLE STATUS +=head1 FILTERING + +You can use B<--filter> to filter which services to process amongst those +provided (meaning to filter all enabled services you need to combine it with +B<--all>). + +There are two kinds of filters available, by type and by status. + +=head2 Filter by type + +=over + +=item I<oneshot>; I<os> + +To only process oneshot services. + +=item I<longrun>; I<lr> + +To only process longrun services. + +=back + +=head2 Filter by status + +=over + +=item I<start>; I<started>; I<up> + +To only process services that are up/started. Note that this includes services +that might be in error state, e.g. that failed to be stopped. + +=item I<stop>; I<stopped>; I<down> + +To only process services that are down/stopped. Note that this includes services +that might be in error state, e.g. that failed to be started. + +=item I<fail>; I<failed>; I<error> + +To only process services that are in error state. + +=back + +As noted below, a given service can match more than one filter, e.g. a service +that failed to be started will show up both under I<stopped> and I<failed> + +You can specify more than one B<--filter> option, though it only make sense to +combine filters of different kinds. If more than one filter of the same kind is +given, only the last one is used. + +=head2 Examples + +To list all oneshot services in error state: + + aa-status --list --all --filter oneshot --filter error + +The same could be done using e.g: + + aa-status -Laf fail -f os + +To show statues of all longrun process currently up: + + aa-status -a -f longrun -f started + +This will list all oneshot services (only the last filter is used since they're +both of the same kind) : + + aa-status -Laf longrun --filter os + + +=head1 POSSIBLE STATUSES The different possible statuses are : @@ -70,7 +144,7 @@ The different possible statuses are : =item B<Unknown status> -E.g. if no status file exist. +E.g. if no status file exist. Such services will be filtered as I<stopped>. =item B<Error> @@ -97,6 +171,9 @@ which value was returned, or which signal killed it. The script I<start>/I<stop> is currently running; or the command has been sent to the B<s6-supervise> of the service. +Such services will be filtered according to their current state, e.g. a service +that is starting will be matched via I<stopped>. + =item B<Started> / B<Stopped> (I<one-shot services only.>) diff --git a/src/anopa/aa-status.c b/src/anopa/aa-status.c index 23ef15c..bce9bc8 100644 --- a/src/anopa/aa-status.c +++ b/src/anopa/aa-status.c @@ -66,8 +66,19 @@ struct serv tain_t stamp; }; +enum +{ + FILTER_NONE = 0, + FILTER_UP, + FILTER_DOWN, + FILTER_ERROR +}; + static genalloc ga_serv = GENALLOC_ZERO; +static unsigned int filter_type = AA_TYPE_UNKNOWN; +static unsigned int filter_status = FILTER_NONE; + static int put_s_max (const char *s, int max, int pad); static void @@ -443,6 +454,43 @@ status_service (struct serv *serv, struct config *cfg) first = 0; } +static int +match_status (struct serv *serv, unsigned int filter) +{ + unsigned int current; + + if (serv->is_s6) + current = (serv->st6.pid && !serv->st6.flagfinishing) ? FILTER_UP : FILTER_DOWN; + else + switch (aa_service (serv->si)->st.event) + { + case AA_EVT_STARTED: + case AA_EVT_STOPPING: + current = FILTER_UP; + break; + + case AA_EVT_NONE: + case AA_EVT_STOPPED: + case AA_EVT_STARTING: + current = FILTER_DOWN; + break; + + case AA_EVT_ERROR: /* == ERR_DEPEND */ + case AA_EVT_STARTING_FAILED: + case AA_EVT_START_FAILED: + return filter == FILTER_ERROR || filter == FILTER_DOWN; + + case AA_EVT_STOPPING_FAILED: + case AA_EVT_STOP_FAILED: + return filter == FILTER_ERROR || filter == FILTER_UP; + + case _AA_NB_EVT: /* silence warning */ + break; + } + + return current == filter; +} + static void load_service (const char *name, struct config *cfg) { @@ -475,6 +523,9 @@ load_service (const char *name, struct config *cfg) return; } + if (filter_type != AA_TYPE_UNKNOWN && s->st.type != filter_type) + return; + if (s->st.type == AA_TYPE_LONGRUN) { if (!s6_svstatus_read (name, &serv.st6)) @@ -543,6 +594,9 @@ load_service (const char *name, struct config *cfg) } } + if (filter_status != FILTER_NONE && !match_status (&serv, filter_status)) + return; + if (cfg->mode_list) { int l = strlen (name); @@ -572,6 +626,31 @@ it_listdir (direntry *d, void *data) return 0; } +static int +set_filter (const char *filter) +{ + if (str_equal (filter, "os") || str_equal (filter, "oneshot")) + filter_type = AA_TYPE_ONESHOT; + else if (str_equal (filter, "lr") || str_equal (filter, "longrun")) + filter_type = AA_TYPE_LONGRUN; + else if (str_equal (filter, "up") || str_equal (filter, "start") + || str_equal (filter, "started")) + filter_status = FILTER_UP; + else if (str_equal (filter, "down") || str_equal (filter, "stop") + || str_equal (filter, "stopped")) + filter_status = FILTER_DOWN; + else if (str_equal (filter, "error") || str_equal (filter, "fail") + || str_equal (filter, "failed")) + filter_status = FILTER_ERROR; + else + { + errno = EINVAL; + return 0; + } + + return 1; +} + static void dieusage (int rc) { @@ -580,6 +659,8 @@ dieusage (int rc) " -r, --repodir DIR Use DIR as repository directory\n" " -l, --listdir DIR Use DIR to list services to get status of\n" " -a, --all Show status of all services\n" + " -f, --filter FILTER Only process services matching FILTER, one of:\n" + " oneshot, longrun, up, down, error (see aa-status(1) for more)\n" " -L, --list Show statuses as one-liners list\n" " -h, --help Show this help screen and exit\n" " -V, --version Show version information and exit\n" @@ -603,6 +684,7 @@ main (int argc, char * const argv[]) struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "double-output", no_argument, NULL, 'D' }, + { "filter", required_argument, NULL, 'f' }, { "help", no_argument, NULL, 'h' }, { "listdir", required_argument, NULL, 'l' }, { "list", no_argument, NULL, 'L' }, @@ -612,7 +694,7 @@ main (int argc, char * const argv[]) }; int c; - c = getopt_long (argc, argv, "aDhl:Lr:V", longopts, NULL); + c = getopt_long (argc, argv, "aDf:hl:Lr:V", longopts, NULL); if (c == -1) break; switch (c) @@ -625,6 +707,11 @@ main (int argc, char * const argv[]) mode_both = 1; break; + case 'f': + if (!set_filter (optarg)) + strerr_diefu3sys (1, "set filter '", optarg, "'"); + break; + case 'h': dieusage (0);