]> granicus.if.org Git - sysstat/commitdiff
pidstat: Add an option to filter processes by name
authorSebastien GODARD <sysstat@users.noreply.github.com>
Fri, 23 May 2014 12:37:29 +0000 (14:37 +0200)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Fri, 23 May 2014 12:37:29 +0000 (14:37 +0200)
Add "-G <process_name>" option to display only processes whose
name matches <process_name> 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 <cedric.marie@openmailbox.org>
Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
pidstat.c
pidstat.h

index 72f558ec356e8f1b3aae4106d0c39d16289f5d4c..88c2fea130839289fb4879bfc16f156b1e15f0f6 100644 (file)
--- 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 [ <username> ] ] [ -u ]\n"
-                         "[ -V ] [ -v ] [ -w ] [ -C <command> ] [ -p { <pid> [,...] | SELF | ALL } ]\n"
-                         "[ -T { TASK | CHILD | ALL } ]\n"));
+                         "[ -V ] [ -v ] [ -w ] [ -C <command> ] [ -G <process_name> ]\n"
+                         "[ -p { <pid> [,...] | 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(&regex, procstr, REG_EXTENDED | REG_NOSUB) != 0) {
+                               /* Error in preparing regex structure */
+                               show_threads = FALSE;
+                               return -1;
+                       }
+
+                       rc = regexec(&regex, (*pstc)->comm, 0, NULL, 0);
+                       regfree(&regex);
+
+                       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) {
index 14531c1ba734543c1babf60238c598267eab71c7..6ca9473aff97103c9a340b9b3cf14a9d2f8c1b19 100644 (file)
--- 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