diff --git a/NEWS b/NEWS index a43935bd..77f0732e 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ better (?) RPM generation XConsole and top.desktop removed old build system removed code cleanup +pgrep and pkill get "-o" (oldest matching process) procps-3.0.3 --> procps-3.0.4 diff --git a/TODO b/TODO index fcfc1715..b0f584dc 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,7 @@ -------------------------- general ------------------------ Implement /usr/proc/bin tools like Solaris has. +The prstat command is interesting, like top in batch mode. Don't these really belong in the procps package? killall pstree fuser lsof who diff --git a/pgrep.1 b/pgrep.1 index 346c5d08..70e8ce2e 100644 --- a/pgrep.1 +++ b/pgrep.1 @@ -7,13 +7,13 @@ pgrep, pkill \- look up or signal processes based on name and other attributes .SH SYNOPSIS -pgrep [\-flnvx] [\-d \fIdelimiter\fP] [\-P \fIppid\fP,...] [\-g \fIpgrp\fP,...] +pgrep [\-flvx] [\-d \fIdelimiter\fP] [\-n|\-o] [\-P \fIppid\fP,...] [\-g \fIpgrp\fP,...] .br [\-s \fIsid\fP,...] [\-u \fIeuid\fP,...] [\-U \fIuid\fP,...] [\-G \fIgid\fP,...] .br [\-t \fIterm\fP,...] [\fIpattern\fP] -pkill [\-\fIsignal\fP] [\-fnvx] [\-P \fIppid\fP,...] [\-g \fIpgrp\fP,...] +pkill [\-\fIsignal\fP] [\-fvx] [\-n|\-o] [\-P \fIppid\fP,...] [\-g \fIpgrp\fP,...] .br [\-s \fIsid\fP,...] [\-u \fIeuid\fP,...] [\-U \fIuid\fP,...] [\-G \fIgid\fP,...] .br @@ -61,6 +61,10 @@ List the process name as well as the process ID. (\fBpgrep\fP only.) Select only the newest (most recently started) of the matching processes. .TP +\-o +Select only the oldest (least recently started) of the matching +processes. +.TP \-P \fIppid\fP,... Only match processes whose parent process ID is listed. .TP @@ -137,8 +141,8 @@ The running \fBpgrep\fP or \fBpkill\fP process will never report itself as a match. .SH BUGS -The options \-n and \-v can not be combined. Let me know if you need -to do this. +The options \-n and \-o and \-v can not be combined. Let me know if +you need to do this. Defunct processes are reported. diff --git a/pgrep.c b/pgrep.c index 36ecc9af..5f3657d7 100644 --- a/pgrep.c +++ b/pgrep.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ union el { static int opt_full = 0; static int opt_long = 0; +static int opt_oldest = 0; static int opt_newest = 0; static int opt_negate = 0; static int opt_exact = 0; @@ -72,10 +74,10 @@ static int usage (int opt) { if (i_am_pkill) - fprintf (stderr, "Usage: pkill [-SIGNAL] [-fnvx] "); + fprintf (stderr, "Usage: pkill [-SIGNAL] [-fvx] "); else - fprintf (stderr, "Usage: pgrep [-flnvx] [-d DELIM] "); - fprintf (stderr, "[-P PPIDLIST] [-g PGRPLIST] [-s SIDLIST]\n" + fprintf (stderr, "Usage: pgrep [-flvx] [-d DELIM] "); + fprintf (stderr, "[-n|-o] [-P PPIDLIST] [-g PGRPLIST] [-s SIDLIST]\n" "\t[-u EUIDLIST] [-U UIDLIST] [-G GIDLIST] [-t TERMLIST] " "[PATTERN]\n"); exit (opt == '?' ? 0 : 2); @@ -111,7 +113,7 @@ parse_opts (int argc, char **argv) strcat (opts, "ld:"); } - strcat (opts, "fnvxP:g:s:u:U:G:t:?V"); + strcat (opts, "fnovxP:g:s:u:U:G:t:?V"); while ((opt = getopt (argc, argv, opts)) != -1) { switch (opt) { @@ -122,10 +124,20 @@ parse_opts (int argc, char **argv) opt_long = 1; break; case 'n': + if (opt_oldest|opt_negate|opt_newest) + usage (opt); opt_newest = 1; ++criteria_count; break; + case 'o': + if (opt_oldest|opt_negate|opt_newest) + usage (opt); + opt_oldest = 1; + ++criteria_count; + break; case 'v': + if (opt_oldest|opt_negate|opt_newest) + usage (opt); opt_negate = 1; break; case 'x': @@ -478,8 +490,8 @@ select_procs (void) { PROCTAB *ptp; proc_t task; - unsigned long long newest_start_time = 0; - pid_t newest_pid = 0; + unsigned long long saved_start_time; // for new/old support + pid_t saved_pid = 0; // for new/old support int matches = 0; int size = 32; regex_t *preg; @@ -493,6 +505,11 @@ select_procs (void) ptp = do_openproc (); preg = do_regcomp (); + + if (opt_newest) saved_start_time = 0ULL; + if (opt_oldest) saved_start_time = ~0ULL; + if (opt_newest) saved_pid = 0; + if (opt_oldest) saved_pid = INT_MAX; memset (&task, 0, sizeof (task)); while (readproc (ptp, &task)) { @@ -500,7 +517,9 @@ select_procs (void) if (task.pid == myself) continue; - else if (opt_newest && task.start_time < newest_start_time) + else if (opt_newest && task.start_time < saved_start_time) + match = 0; + else if (opt_oldest && task.start_time > saved_start_time) match = 0; else if (opt_ppid && ! match_numlist (task.ppid, opt_ppid)) match = 0; @@ -553,11 +572,19 @@ select_procs (void) if (match ^ opt_negate) { /* Exclusive OR is neat */ if (opt_newest) { - if (newest_start_time == task.start_time && - newest_pid > task.pid) + if (saved_start_time == task.start_time && + saved_pid > task.pid) continue; - newest_start_time = task.start_time; - newest_pid = task.pid; + saved_start_time = task.start_time; + saved_pid = task.pid; + matches = 0; + } + if (opt_oldest) { + if (saved_start_time == task.start_time && + saved_pid < task.pid) + continue; + saved_start_time = task.start_time; + saved_pid = task.pid; matches = 0; } if (opt_long) {