top: add -p option and p command to only show a single process
Allow to show only a single process specified by PID. This could be done either by running top like 'top -p PID' or using the 'p' command inside top. Reviewed by: eadler Approved by: eadler Obtained from: OpenBSD Differential Revision: https://reviews.freebsd.org/D15501
This commit is contained in:
parent
107463a1fd
commit
f2fe0a1957
@ -92,6 +92,7 @@ o - specify sort order (pri, size, res, cpu, time, threads, jid, pid)\n",
|
||||
o - specify sort order (vcsw, ivcsw, read, write, fault, total, jid, pid)\n",
|
||||
stdout);
|
||||
fputs("\
|
||||
p - display one process (+ selects all processes)\n\
|
||||
P - toggle the displaying of per-CPU statistics\n\
|
||||
r - renice a process\n\
|
||||
s - change number of seconds to delay between updates\n\
|
||||
|
@ -764,6 +764,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
|
||||
int show_self;
|
||||
int show_system;
|
||||
int show_uid;
|
||||
int show_pid;
|
||||
int show_kidle;
|
||||
|
||||
/*
|
||||
@ -783,7 +784,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
|
||||
previous_pref = malloc(nproc * sizeof(*previous_pref));
|
||||
if (previous_procs == NULL || previous_pref == NULL) {
|
||||
(void) fprintf(stderr, "top: Out of memory.\n");
|
||||
quit(23);
|
||||
quit(TOP_EX_SYS_ERROR);
|
||||
}
|
||||
previous_proc_count_max = nproc;
|
||||
}
|
||||
@ -822,7 +823,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
|
||||
}
|
||||
if (pref == NULL || pbase == NULL || pcpu == NULL) {
|
||||
(void) fprintf(stderr, "top: Out of memory.\n");
|
||||
quit(23);
|
||||
quit(TOP_EX_SYS_ERROR);
|
||||
}
|
||||
/* get a pointer to the states summary array */
|
||||
si->procstates = process_states;
|
||||
@ -833,6 +834,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
|
||||
show_self = sel->self == -1;
|
||||
show_system = sel->system;
|
||||
show_uid = sel->uid[0] != -1;
|
||||
show_pid = sel->pid != -1;
|
||||
show_kidle = sel->kidle;
|
||||
|
||||
/* count up process states and get pointers to interesting procs */
|
||||
@ -894,6 +896,9 @@ get_process_info(struct system_info *si, struct process_select *sel,
|
||||
/* skip proc. that don't belong to the selected UID */
|
||||
continue;
|
||||
|
||||
if (show_pid && pp->ki_pid != sel->pid)
|
||||
continue;
|
||||
|
||||
*prefp++ = pp;
|
||||
active_procs++;
|
||||
}
|
||||
@ -1177,12 +1182,12 @@ getsysctl(const char *name, void *ptr, size_t len)
|
||||
if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
|
||||
fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name,
|
||||
strerror(errno));
|
||||
quit(23);
|
||||
quit(TOP_EX_SYS_ERROR);
|
||||
}
|
||||
if (nlen != len) {
|
||||
fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n",
|
||||
name, (unsigned long)len, (unsigned long)nlen);
|
||||
quit(23);
|
||||
quit(TOP_EX_SYS_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,7 @@ struct process_select
|
||||
int jail; /* show jail ID */
|
||||
int swap; /* show swap usage */
|
||||
int kidle; /* show per-CPU idle threads */
|
||||
pid_t pid; /* only this pid (unless pid == -1) */
|
||||
char *command; /* only this command (unless == NULL) */
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,11 @@ top \- display and update information about the top cpu processes
|
||||
.BI \-m io | cpu
|
||||
] [
|
||||
.BI \-o field
|
||||
]
|
||||
.br
|
||||
.ti +4
|
||||
[
|
||||
.BI \-p pid
|
||||
] [
|
||||
.BI \-s time
|
||||
] [
|
||||
@ -178,6 +183,10 @@ is the name of the column as seen in the output, but in lower case:
|
||||
\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
|
||||
\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
|
||||
.TP
|
||||
.BI \-p pid
|
||||
Show only the process
|
||||
.IR pid .
|
||||
.TP
|
||||
.BI \-J jail
|
||||
Show only those processes owned by
|
||||
.IR jail .
|
||||
@ -320,6 +329,10 @@ available on all systems. The sort key names vary from system to system
|
||||
but usually include: \*(lqcpu\*(rq, \*(lqres\*(rq, \*(lqsize\*(rq,
|
||||
\*(lqtime\*(rq. The default is cpu.
|
||||
.TP
|
||||
.B p
|
||||
Display a specific process (prompt for pid).
|
||||
If the pid specified is simply \*(lq+\*(rq, then show all processes.
|
||||
.TP
|
||||
.B e
|
||||
Display a list of system errors (if any) generated by the last
|
||||
.BR k ill
|
||||
|
@ -226,8 +226,9 @@ main(int argc, char *argv[])
|
||||
char *order_name = NULL;
|
||||
int order_index = 0;
|
||||
fd_set readfds;
|
||||
char old_system = false;
|
||||
|
||||
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
|
||||
static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwop";
|
||||
/* these defines enumerate the "strchr"s of the commands in command_chars */
|
||||
#define CMD_redraw 0
|
||||
#define CMD_update 1
|
||||
@ -256,7 +257,8 @@ main(int argc, char *argv[])
|
||||
#define CMD_pcputog 23
|
||||
#define CMD_jail 24
|
||||
#define CMD_swaptog 25
|
||||
#define CMD_order 26
|
||||
#define CMD_order 26
|
||||
#define CMD_pid 27
|
||||
|
||||
/* set the buffer for stdout */
|
||||
#ifdef DEBUG
|
||||
@ -291,6 +293,7 @@ main(int argc, char *argv[])
|
||||
ps.jail = false;
|
||||
ps.swap = false;
|
||||
ps.kidle = true;
|
||||
ps.pid = -1;
|
||||
ps.command = NULL;
|
||||
|
||||
/* get preset options from the environment */
|
||||
@ -316,7 +319,7 @@ main(int argc, char *argv[])
|
||||
optind = 1;
|
||||
}
|
||||
|
||||
while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
|
||||
while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:p:tw")) != EOF)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
@ -338,7 +341,8 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'S': /* show system processes */
|
||||
ps.system = !ps.system;
|
||||
ps.system = true;
|
||||
old_system = true;
|
||||
break;
|
||||
|
||||
case 'I': /* show idle processes */
|
||||
@ -371,6 +375,19 @@ main(int argc, char *argv[])
|
||||
displays = i;
|
||||
}
|
||||
break;
|
||||
case 'p': {
|
||||
unsigned long long num;
|
||||
const char *errstr;
|
||||
|
||||
num = strtonum(optarg, 0, INT_MAX, &errstr);
|
||||
if (errstr != NULL || !find_pid(num)) {
|
||||
fprintf(stderr, "%s: unknown pid\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
ps.pid = (pid_t)num;
|
||||
ps.system = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
if ((delay = atoi(optarg)) < 0 || (delay == 0 && getuid() != 0))
|
||||
@ -456,8 +473,8 @@ main(int argc, char *argv[])
|
||||
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"Usage: %s [-abCHIijnPqStuvwz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
|
||||
" [-J jail] [-U username] [number]\n",
|
||||
"Usage: %s [-abCHIijnPqStuvwz] [-d count] [-m io | cpu] [-o field] [-p pid]\n"
|
||||
" [-s time] [-J jail] [-U username] [number]\n",
|
||||
myname);
|
||||
exit(1);
|
||||
}
|
||||
@ -1018,6 +1035,7 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case CMD_viewsys:
|
||||
ps.system = !ps.system;
|
||||
old_system = ps.system;
|
||||
break;
|
||||
case CMD_showargs:
|
||||
fmt_flags ^= FMT_SHOWARGS;
|
||||
@ -1117,6 +1135,36 @@ main(int argc, char *argv[])
|
||||
reset_display();
|
||||
putchar('\r');
|
||||
break;
|
||||
case CMD_pid:
|
||||
new_message(MT_standout,
|
||||
"Process id to show (+ for all): ");
|
||||
if (readline(tempbuf2, sizeof(tempbuf2), false) > 0) {
|
||||
if (tempbuf2[0] == '+' &&
|
||||
tempbuf2[1] == '\0') {
|
||||
ps.pid = (pid_t)-1;
|
||||
ps.system = old_system;
|
||||
} else {
|
||||
unsigned long long num;
|
||||
const char *errstr;
|
||||
|
||||
num = strtonum(tempbuf2, 0, INT_MAX,
|
||||
&errstr);
|
||||
if (errstr != NULL || !find_pid(num)) {
|
||||
new_message(MT_standout,
|
||||
" %s: unknown pid",
|
||||
tempbuf2);
|
||||
no_command = true;
|
||||
} else {
|
||||
if (ps.system == false)
|
||||
old_system = false;
|
||||
ps.pid = (pid_t)num;
|
||||
ps.system = true;
|
||||
}
|
||||
}
|
||||
putchar('\r');
|
||||
} else
|
||||
clear_message();
|
||||
break;
|
||||
default:
|
||||
new_message(MT_standout, " BAD CASE IN SWITCH!");
|
||||
putchar('\r');
|
||||
|
@ -34,6 +34,9 @@ extern int Header_lines; /* 7 */
|
||||
|
||||
#define NUM_AVERAGES 3
|
||||
|
||||
/* Exit code for system errors */
|
||||
#define TOP_EX_SYS_ERROR 23
|
||||
|
||||
enum displaymodes { DISP_CPU = 0, DISP_IO, DISP_MAX };
|
||||
|
||||
/*
|
||||
|
@ -15,9 +15,18 @@
|
||||
#include "top.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <kvm.h>
|
||||
|
||||
void quit(int);
|
||||
|
||||
int
|
||||
atoiwi(const char *str)
|
||||
@ -417,3 +426,31 @@ format_k2(unsigned long long amt)
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int
|
||||
find_pid(pid_t pid)
|
||||
{
|
||||
kvm_t *kd = NULL;
|
||||
struct kinfo_proc *pbase = NULL;
|
||||
int nproc;
|
||||
int ret = 0;
|
||||
|
||||
kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL);
|
||||
if (kd == NULL) {
|
||||
fprintf(stderr, "top: kvm_open() failed.\n");
|
||||
quit(TOP_EX_SYS_ERROR);
|
||||
}
|
||||
|
||||
pbase = kvm_getprocs(kd, KERN_PROC_PID, pid, &nproc);
|
||||
if (pbase == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((nproc == 1) && (pbase->ki_pid == pid)) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
done:
|
||||
kvm_close(kd);
|
||||
return ret;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
* Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int atoiwi(const char *);
|
||||
char *itoa(unsigned int);
|
||||
char *itoa7(unsigned int);
|
||||
@ -20,4 +22,5 @@ char *format_time(long);
|
||||
char *format_k(int);
|
||||
char *format_k2(unsigned long long);
|
||||
int string_index(const char *string, char *array[]);
|
||||
int find_pid(pid_t pid);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user