From: Sebastien GODARD Date: Fri, 23 May 2014 12:37:29 +0000 (+0200) Subject: pidstat: Add an option to filter processes by name X-Git-Tag: v11.0.0~15 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1bf83b1c76f48f987f1ee7526e936096abdaca82;p=sysstat pidstat: Add an option to filter processes by name Add "-G " option to display only processes whose name matches regular expression. While -C option filters both process and thread names, -G option filters only process names, and displays all threads of matching processes. Signed-off-by: Cedric Marie Signed-off-by: Sebastien GODARD --- diff --git a/pidstat.c b/pidstat.c index 72f558e..88c2fea 100644 --- a/pidstat.c +++ b/pidstat.c @@ -57,6 +57,8 @@ struct pid_stats st_pid_null; struct tm ps_tstamp[3]; char commstr[MAX_COMM_LEN]; char userstr[MAX_USER_LEN]; +char procstr[MAX_COMM_LEN]; +int show_threads = FALSE; unsigned int pid_nr = 0; /* Nb of PID to display */ unsigned int pid_array_nr = 0; @@ -86,8 +88,8 @@ void usage(char *progname) fprintf(stderr, _("Options are:\n" "[ -d ] [ -h ] [ -I ] [ -l ] [ -r ] [ -s ] [ -t ] [ -U [ ] ] [ -u ]\n" - "[ -V ] [ -v ] [ -w ] [ -C ] [ -p { [,...] | SELF | ALL } ]\n" - "[ -T { TASK | CHILD | ALL } ]\n")); + "[ -V ] [ -v ] [ -w ] [ -C ] [ -G ]\n" + "[ -p { [,...] | SELF | ALL } ] [ -T { TASK | CHILD | ALL } ]\n")); exit(1); } @@ -968,7 +970,10 @@ void read_stats(int curr) * Get current PID to display. * First, check that PID exists. *Then* check that it's an active process * and/or that the string (entered on the command line with option -C) - * is found in command name. + * is found in command name, or that the process string (entered on the + * command line with option -G) is found either in its command name (in case + * PID is a process) or in command name of its thread leader (in case + * PID is a thread). * * IN: * @prev Index in array where stats used as reference are. @@ -1149,6 +1154,37 @@ int get_pid_to_display(int prev, int curr, int p, unsigned int activity, return -1; } + if (PROCESS_STRING(pidflag)) { + if (!(*pstc)->tgid) { + /* This PID is a process ("thread group leader") */ + if (regcomp(®ex, procstr, REG_EXTENDED | REG_NOSUB) != 0) { + /* Error in preparing regex structure */ + show_threads = FALSE; + return -1; + } + + rc = regexec(®ex, (*pstc)->comm, 0, NULL, 0); + regfree(®ex); + + if (rc) { + /* regex pattern not found in command name */ + show_threads = FALSE; + return -1; + } + + /* + * This process and all its threads will be displayed. + * No need to save PID value: For every process read by pidstat, + * pidstat then immediately reads all its threads. + */ + show_threads = TRUE; + } + else if (!show_threads) { + /* This pid is a thread and is not part of a process to display */ + return -1; + } + } + if (USER_STRING(pidflag)) { if ((pwdent = getpwuid((*pstc)->uid)) != NULL) { if (strcmp(pwdent->pw_name, userstr)) @@ -2053,6 +2089,11 @@ int write_stats_core(int prev, int curr, int dis, int disp_avg, itv = g_itv; } + if (PROCESS_STRING(pidflag)) { + /* Reset "show threads" flag */ + show_threads = FALSE; + } + if (DISPLAY_ONELINE(pidflag)) { if (DISPLAY_TASK_STATS(tskflag)) { again += write_pid_task_all_stats(prev, curr, dis, @@ -2371,6 +2412,20 @@ int main(int argc, char **argv) } } + else if (!strcmp(argv[opt], "-G")) { + if (argv[++opt]) { + strncpy(procstr, argv[opt++], MAX_COMM_LEN); + procstr[MAX_COMM_LEN - 1] = '\0'; + pidflag |= P_F_PROCSTR; + if (!strlen(procstr)) { + usage(argv[0]); + } + } + else { + usage(argv[0]); + } + } + else if (!strcmp(argv[opt], "-T")) { if (argv[++opt]) { if (tskflag) { diff --git a/pidstat.h b/pidstat.h index 14531c1..6ca9473 100644 --- a/pidstat.h +++ b/pidstat.h @@ -52,6 +52,7 @@ #define P_D_CMDLINE 0x080 #define P_D_USERNAME 0x100 #define P_F_USERSTR 0x200 +#define P_F_PROCSTR 0x400 #define DISPLAY_PID(m) (((m) & P_D_PID) == P_D_PID) #define DISPLAY_ALL_PID(m) (((m) & P_D_ALL_PID) == P_D_ALL_PID) @@ -63,6 +64,7 @@ #define DISPLAY_CMDLINE(m) (((m) & P_D_CMDLINE) == P_D_CMDLINE) #define DISPLAY_USERNAME(m) (((m) & P_D_USERNAME) == P_D_USERNAME) #define USER_STRING(m) (((m) & P_F_USERSTR) == P_F_USERSTR) +#define PROCESS_STRING(m) (((m) & P_F_PROCSTR) == P_F_PROCSTR) /* Per-process flags */ #define F_NO_PID_IO 0x01