net-mgmt/nstat: create port
nstat is a replacement for the most frequently used parts of vmstat, netstat (bw), and pmc-memory.x The advantage of using nstat is that it can run all in a single session, rather than having to use 3 terminal sessions to monitor a machine. Submitted by: gallatin (private email)
This commit is contained in:
parent
d394b033f4
commit
e3e6a21819
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=449848
6 changed files with 522 additions and 0 deletions
|
@ -203,6 +203,7 @@
|
|||
SUBDIR += nsca-ng-client
|
||||
SUBDIR += nsca27
|
||||
SUBDIR += nsca27-client
|
||||
SUBDIR += nstat
|
||||
SUBDIR += nstreams
|
||||
SUBDIR += observium
|
||||
SUBDIR += ocsinventory-agent
|
||||
|
|
32
net-mgmt/nstat/Makefile
Normal file
32
net-mgmt/nstat/Makefile
Normal file
|
@ -0,0 +1,32 @@
|
|||
# $FreeBSD$
|
||||
|
||||
PORTNAME= nstat
|
||||
PORTVERSION= 1.0
|
||||
CATEGORIES= net-mgmt
|
||||
MASTER_SITES= # empty
|
||||
DISTFILES= # empty
|
||||
|
||||
MAINTAINER= swills@FreeBSD.org
|
||||
COMMENT= Replacement for bw/netstat/vmstat/pcm-memory.x
|
||||
|
||||
NO_FETCH= yes
|
||||
|
||||
PLIST_FILES= bin/nstat \
|
||||
man/man1/nstat.1.gz
|
||||
|
||||
do-extract:
|
||||
@${MKDIR} ${WRKSRC}
|
||||
@(cd ${FILESDIR} && ${CP} -R . ${WRKSRC})
|
||||
|
||||
do-install:
|
||||
${MKDIR} ${STAGEDIR}${PREFIX}/bin
|
||||
${INSTALL_PROGRAM} ${WRKSRC}/nstat ${STAGEDIR}${PREFIX}/bin
|
||||
${INSTALL_MAN} ${WRKSRC}/nstat.1.gz ${STAGEDIR}${PREFIX}/man/man1
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
.if ${OPSYS} == FreeBSD && ${OSVERSION} <= 1200027
|
||||
BROKEN= Does not build without clock_nanosleep
|
||||
.endif
|
||||
|
||||
.include <bsd.port.post.mk>
|
4
net-mgmt/nstat/files/Makefile
Normal file
4
net-mgmt/nstat/files/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
PROG= nstat
|
||||
WARNS= 2
|
||||
|
||||
.include <bsd.prog.mk>
|
58
net-mgmt/nstat/files/nstat.1
Normal file
58
net-mgmt/nstat/files/nstat.1
Normal file
|
@ -0,0 +1,58 @@
|
|||
.\" Copyright (c) 2017
|
||||
.\" Netflix Inc.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 22, 2017
|
||||
.Dt NSTAT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm nstat
|
||||
.Nd Display various stats.
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl m
|
||||
.Op wait
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility will display system stats similar to netstat and vmstat.
|
||||
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.Fl m
|
||||
run pcm-memory.x and report memory bandwidth statistics
|
||||
.Pp
|
||||
.Sh EXAMPLES
|
||||
The command:
|
||||
.Dl netstat -m 10
|
||||
will print what the system is doing every 10
|
||||
seconds, including reporting memory bandwith.
|
||||
|
||||
.Sh SEE ALSO
|
||||
.Xr netstat 1 ,
|
||||
.Xr vmstat 8 ,
|
||||
.Xr pcm-memory.x 1
|
||||
|
423
net-mgmt/nstat/files/nstat.c
Normal file
423
net-mgmt/nstat/files/nstat.c
Normal file
|
@ -0,0 +1,423 @@
|
|||
/*-
|
||||
* Copyright (c) 2017
|
||||
* Netflix Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_mib.h>
|
||||
|
||||
#include <netinet/tcp_fsm.h>
|
||||
|
||||
#include <sys/resource.h>
|
||||
#include <sys/ttycom.h>
|
||||
#include <sys/vmmeter.h>
|
||||
|
||||
|
||||
/* why is this only defined in the kernel */
|
||||
#define timespecadd(vvp, uvp) \
|
||||
do { \
|
||||
(vvp)->tv_sec += (uvp)->tv_sec; \
|
||||
(vvp)->tv_nsec += (uvp)->tv_nsec; \
|
||||
if ((vvp)->tv_nsec >= 1000000000) { \
|
||||
(vvp)->tv_sec++; \
|
||||
(vvp)->tv_nsec -= 1000000000; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define SWAP_CPU() { cpu_tmp = cpu; cpu = cpu_prev; cpu_prev = cpu_tmp; }
|
||||
double
|
||||
get_cpu(void)
|
||||
{
|
||||
static long cpu_time[CPUSTATES];
|
||||
static long cpu_time_too[CPUSTATES];
|
||||
static long *cpu = cpu_time, *cpu_prev = cpu_time_too, *cpu_tmp;
|
||||
long busy, idle;
|
||||
size_t len;
|
||||
int i, status;
|
||||
|
||||
SWAP_CPU();
|
||||
len = sizeof(cpu_time);
|
||||
status = sysctlbyname("kern.cp_time", cpu, &len, NULL, 0);
|
||||
if (status) {
|
||||
err(EX_OSERR, "Cant get CPU time");
|
||||
}
|
||||
for (busy = 0, i = 0; i < CPUSTATES; i++) {
|
||||
if (i != CP_IDLE)
|
||||
busy += cpu[i] - cpu_prev[i];
|
||||
}
|
||||
idle = cpu[CP_IDLE] - cpu_prev[CP_IDLE];
|
||||
|
||||
return ((double)busy / (double)(busy + idle) * 100.0);
|
||||
}
|
||||
|
||||
#define SWAP_VM() { vmm_tmp = vmm; vmm = vmm_prev; vmm_prev = vmm_tmp; }
|
||||
struct my_vmmeter {
|
||||
uint64_t v_syscall;
|
||||
uint64_t v_swtch;
|
||||
uint64_t v_intr;
|
||||
uint64_t v_free_count;
|
||||
};
|
||||
|
||||
void
|
||||
get_vmm(u_int *syscall, u_int *csw, u_int *irq, double *free)
|
||||
{
|
||||
static struct my_vmmeter vmm_arr[2];
|
||||
static struct my_vmmeter *vmm = &vmm_arr[0], *vmm_prev = &vmm_arr[1],
|
||||
*vmm_tmp;
|
||||
size_t len;
|
||||
int status;
|
||||
|
||||
SWAP_VM();
|
||||
len = sizeof(vmm->v_syscall);
|
||||
status = sysctlbyname("vm.stats.sys.v_syscall",
|
||||
&vmm->v_syscall, &len, NULL, 0);
|
||||
status |= sysctlbyname("vm.stats.sys.v_swtch",
|
||||
&vmm->v_swtch, &len, NULL, 0);
|
||||
status |= sysctlbyname("vm.stats.sys.v_intr",
|
||||
&vmm->v_intr, &len, NULL, 0);
|
||||
status |= sysctlbyname("vm.stats.vm.v_free_count",
|
||||
&vmm->v_free_count, &len, NULL, 0);
|
||||
if (status) {
|
||||
err(EX_OSERR, "Cant get CPU time");
|
||||
}
|
||||
*syscall = vmm->v_syscall - vmm_prev->v_syscall;
|
||||
*csw = vmm->v_swtch - vmm_prev->v_swtch;
|
||||
*irq = vmm->v_intr - vmm_prev->v_intr;
|
||||
*free = ((double)vmm->v_free_count * 4096.0) /
|
||||
(1024.0 * 1024.0 * 1024.0);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
find_if(char *wanted)
|
||||
{
|
||||
size_t len;
|
||||
int if_maxidx, i;
|
||||
int name[6];
|
||||
char ifn[128];
|
||||
|
||||
name[0] = CTL_NET;
|
||||
name[1] = PF_LINK;
|
||||
name[2] = NETLINK_GENERIC;
|
||||
name[3] = IFMIB_SYSTEM;
|
||||
name[4] = IFMIB_IFCOUNT;
|
||||
|
||||
len = sizeof(if_maxidx);
|
||||
if (sysctl(name, 5, &if_maxidx, &len, 0, 0) < 0)
|
||||
err(EX_OSERR, "can't get ifcnt");
|
||||
|
||||
|
||||
for (i = 0; i <= if_maxidx; i++) {
|
||||
name[3] = IFMIB_IFDATA;
|
||||
name[4] = i;
|
||||
name[5] = IFDATA_DRIVERNAME;
|
||||
len = sizeof(ifn);
|
||||
if (sysctl(name, 6, ifn, &len, 0, 0) < 0) {
|
||||
if (errno == ENOENT)
|
||||
continue;
|
||||
err(EX_OSERR, "can't get ifname");
|
||||
}
|
||||
if (0 == strncmp(wanted, ifn, len))
|
||||
return (i);
|
||||
}
|
||||
printf("Could not find %s\n", wanted);
|
||||
exit(ENOENT);
|
||||
}
|
||||
|
||||
static void
|
||||
get_nic_stats(int if_idx, struct ifmibdata *ifm)
|
||||
{
|
||||
size_t len;
|
||||
int name[6];
|
||||
|
||||
name[0] = CTL_NET;
|
||||
name[1] = PF_LINK;
|
||||
name[2] = NETLINK_GENERIC;
|
||||
name[3] = IFMIB_IFDATA;
|
||||
name[4] = if_idx;
|
||||
name[5] = IFDATA_GENERAL;
|
||||
len = sizeof(*ifm);
|
||||
if (sysctl(name, 6, ifm, &len, 0, 0) < 0)
|
||||
err(EX_OSERR, "could not get nic stats");
|
||||
}
|
||||
|
||||
static char *
|
||||
find_ifname(void)
|
||||
{
|
||||
static char ifbuf[80];
|
||||
FILE *pipe;
|
||||
char *p;
|
||||
|
||||
|
||||
pipe = popen("netstat -4rn | grep default", "r");
|
||||
if (pipe == NULL)
|
||||
err(EX_OSERR, "could not run netsat");
|
||||
(void)fread(ifbuf, sizeof(ifbuf) - 1, 1, pipe);
|
||||
pclose(pipe);
|
||||
p = &ifbuf[sizeof(ifbuf) - 1];
|
||||
while (*p != ' ') {
|
||||
if (*p == '\n')
|
||||
*p = '\0';
|
||||
p--;
|
||||
if (p == ifbuf)
|
||||
err(EX_DATAERR, "can't read def rt");
|
||||
}
|
||||
/* we are point to a space, point to 1st ifname char */
|
||||
return (p + 1);
|
||||
}
|
||||
|
||||
static int
|
||||
find_rows(void)
|
||||
{
|
||||
struct winsize sz;
|
||||
int rows;
|
||||
|
||||
rows = 24;
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
if (0 == ioctl(STDOUT_FILENO, TIOCGWINSZ, &sz))
|
||||
rows = sz.ws_row;
|
||||
}
|
||||
return (rows);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pcm_mem(double interval, double *r, double *w, double *rw)
|
||||
{
|
||||
static FILE * pipe = NULL;
|
||||
static int pipe_fd;
|
||||
char *open_str;
|
||||
char buf[256];
|
||||
char *p;
|
||||
int sem_cnt, ret_found;
|
||||
ssize_t bytes;
|
||||
|
||||
if (pipe == NULL) {
|
||||
open_str = alloca(80);
|
||||
snprintf(open_str, 80,
|
||||
"pcm-memory.x -csv %f 2>/dev/null", interval * 0.99);
|
||||
pipe = popen(open_str, "r");
|
||||
if (pipe == NULL)
|
||||
err(EX_OSERR, "pipe");
|
||||
/* read one-time CSV hdrs */
|
||||
(void)fread(buf, sizeof(buf) - 1, 1, pipe);
|
||||
pipe_fd = fileno(pipe);
|
||||
fcntl(pipe_fd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
bzero(buf, sizeof(buf));
|
||||
bytes = read(pipe_fd, buf, sizeof(buf));
|
||||
if (bytes == 0)
|
||||
err(EX_OSERR,
|
||||
"pcm-memory.x exited - kldload cpuctl?");
|
||||
|
||||
if (bytes == -1) {
|
||||
if (errno == EAGAIN)
|
||||
return;
|
||||
err(EX_OSERR, "read from pcm-memory.x failed");
|
||||
}
|
||||
|
||||
p = &buf[bytes];
|
||||
/*
|
||||
* the CSV is formatted as: ...; ....; readbw; writebw; rwbw\n
|
||||
*
|
||||
* So we start at the end of the buffer, and look backwards for a
|
||||
* return. Once found, we then count back 3 semi-colons, and then
|
||||
* pass it to sscanf
|
||||
*/
|
||||
|
||||
ret_found = 0;
|
||||
sem_cnt = 0;
|
||||
while (p != buf && sem_cnt < 3) {
|
||||
p--;
|
||||
if (!ret_found && *p != '\n')
|
||||
continue;
|
||||
ret_found = 1;
|
||||
if (*p == ';')
|
||||
sem_cnt++;
|
||||
}
|
||||
if (sem_cnt == 3) {
|
||||
p++;
|
||||
sscanf(p, "%lf; %lf; %lf", r, w, rw);
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
get_tcp_est()
|
||||
{
|
||||
uint64_t tcps[TCP_NSTATES];
|
||||
size_t len = sizeof(tcps);
|
||||
int status;
|
||||
|
||||
status = sysctlbyname("net.inet.tcp.states", tcps, &len, NULL, 0);
|
||||
if (status != 0)
|
||||
err(EX_OSERR, "could not fetch tcp states");
|
||||
|
||||
return ((long)tcps[TCPS_ESTABLISHED]);
|
||||
}
|
||||
|
||||
#define SWAP_IFM() { ifm_tmp = ifm; ifm = ifm_prev; ifm_prev = ifm_tmp; }
|
||||
|
||||
|
||||
static void
|
||||
print_hdr(int do_pcm_mem)
|
||||
{
|
||||
printf(" InMpps OMpps InGbs OGbs err TCP Est %%CPU syscalls csw irq GBfree");
|
||||
if (do_pcm_mem)
|
||||
printf(" MemRd MemWr MemRW");
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
usage(char *name)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: %s [-m] [-I interface] [wait]\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct ifmibdata ifmd[2];
|
||||
struct ifmibdata *ifm, *ifm_prev, *ifm_tmp;
|
||||
char *ifname = NULL;
|
||||
int c, if_idx;
|
||||
double o_gbps, i_gbps, o_mpps, i_mpps;
|
||||
long errs, est;
|
||||
double interval = 1.0;
|
||||
int rows = find_rows() - 1;
|
||||
int row = 0;
|
||||
int do_pcm_mem = 0;
|
||||
u_int syscalls, csw, irq;
|
||||
double free_mem;
|
||||
double mem_rd = 0.0, mem_wr = 0.0, mem_rw = 0.0;
|
||||
struct timespec interval_ts, deadline_ts;
|
||||
|
||||
|
||||
while ((c = getopt(argc, argv, "mI:")) != -1) {
|
||||
switch (c) {
|
||||
case 'm':
|
||||
do_pcm_mem = 1;
|
||||
break;
|
||||
case 'I':
|
||||
ifname = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (*argv)
|
||||
interval = atof(*argv);
|
||||
|
||||
interval_ts.tv_sec = (time_t)interval;
|
||||
interval_ts.tv_nsec = (interval - (time_t)interval) * 1000000000;
|
||||
|
||||
if (ifname == NULL)
|
||||
ifname = find_ifname();
|
||||
|
||||
if_idx = find_if(ifname);
|
||||
ifm = &ifmd[0];
|
||||
ifm_prev = &ifmd[1];
|
||||
|
||||
/*
|
||||
* preload all the counters so 1st interval looks reasonable
|
||||
*/
|
||||
|
||||
if (do_pcm_mem)
|
||||
get_pcm_mem(interval, &mem_rd, &mem_wr, &mem_rw);
|
||||
get_nic_stats(if_idx, ifm);
|
||||
est = get_tcp_est();
|
||||
get_vmm(&syscalls, &csw, &irq, &free_mem);
|
||||
(void)get_cpu();
|
||||
usleep(interval * 1000 * 1000);
|
||||
clock_gettime(CLOCK_UPTIME, &deadline_ts);
|
||||
while (1) {
|
||||
if (row == 0)
|
||||
print_hdr(do_pcm_mem);
|
||||
SWAP_IFM();
|
||||
get_nic_stats(if_idx, ifm);
|
||||
i_gbps = ifm->ifmd_data.ifi_ibytes -
|
||||
ifm_prev->ifmd_data.ifi_ibytes;
|
||||
i_gbps = (8.0 * i_gbps) / (1000.0 * 1000.0 * 1000.0 * interval);
|
||||
o_gbps = ifm->ifmd_data.ifi_obytes -
|
||||
ifm_prev->ifmd_data.ifi_obytes;
|
||||
o_gbps = (8.0 * o_gbps) / (1000.0 * 1000.0 * 1000.0 * interval);
|
||||
i_mpps = ifm->ifmd_data.ifi_ipackets -
|
||||
ifm_prev->ifmd_data.ifi_ipackets;
|
||||
i_mpps = i_mpps / (1000 * 1000 * interval);
|
||||
o_mpps = ifm->ifmd_data.ifi_opackets -
|
||||
ifm_prev->ifmd_data.ifi_opackets;
|
||||
o_mpps = o_mpps / (1000 * 1000 * interval);
|
||||
|
||||
/* all errs .. should be rare, don't clutter output */
|
||||
errs = ifm->ifmd_data.ifi_oerrors -
|
||||
ifm_prev->ifmd_data.ifi_oerrors;
|
||||
errs += ifm->ifmd_data.ifi_ierrors -
|
||||
ifm_prev->ifmd_data.ifi_ierrors;
|
||||
errs += ifm->ifmd_data.ifi_oqdrops -
|
||||
ifm_prev->ifmd_data.ifi_oqdrops;
|
||||
errs += ifm->ifmd_data.ifi_iqdrops -
|
||||
ifm_prev->ifmd_data.ifi_iqdrops;
|
||||
|
||||
est = get_tcp_est();
|
||||
get_vmm(&syscalls, &csw, &irq, &free_mem);
|
||||
printf("%6.2lf %6.2lf %6.2lf %6.2lf %2ld %6ld %4.2lf %6.0f %6.0f %6.0f %5.2lf",
|
||||
i_mpps, o_mpps, i_gbps, o_gbps, errs, est, get_cpu(),
|
||||
syscalls / interval, csw / interval, irq / interval,
|
||||
free_mem);
|
||||
|
||||
if (do_pcm_mem) {
|
||||
get_pcm_mem(interval, &mem_rd, &mem_wr, &mem_rw);
|
||||
printf(" %8.2f %8.2f %8.2f", mem_rd, mem_wr, mem_rw);
|
||||
}
|
||||
printf("\n");
|
||||
if (++row == rows)
|
||||
row = 0;
|
||||
|
||||
timespecadd(&deadline_ts, &interval_ts);
|
||||
clock_nanosleep(CLOCK_UPTIME, TIMER_ABSTIME, &deadline_ts, NULL);
|
||||
}
|
||||
}
|
4
net-mgmt/nstat/pkg-descr
Normal file
4
net-mgmt/nstat/pkg-descr
Normal file
|
@ -0,0 +1,4 @@
|
|||
nstat is a replacement for the most frequently used parts of vmstat, netstat
|
||||
(bw), and pmc-memory.x The advantage of using nstat is that it can run all in a
|
||||
single session, rather than having to use 3 terminal sessions to monitor a
|
||||
machine.
|
Loading…
Reference in a new issue