mirror of
https://gitlab.com/procps-ng/procps.git
synced 2024-11-23 18:14:15 +08:00
watch: add precision wait time option -p
A patch from Debian. Bug-Debian: http://bugs.debian.org/183486 Reviewed-by: Craig Small <csmall@debian.org> Backported-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
parent
39a2f5d717
commit
0dbdb862b1
54
watch.1
54
watch.1
@ -4,7 +4,7 @@ watch \- execute a program periodically, showing output fullscreen
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.na
|
.na
|
||||||
.B watch
|
.B watch
|
||||||
.RB [ \-bdehvtx ]
|
.RB [ \-bdehpvtx ]
|
||||||
.RB [ \-n
|
.RB [ \-n
|
||||||
.IR seconds ]
|
.IR seconds ]
|
||||||
.RB [ \-\-beep ]
|
.RB [ \-\-beep ]
|
||||||
@ -15,6 +15,7 @@ watch \- execute a program periodically, showing output fullscreen
|
|||||||
.RB [ \-\-help ]
|
.RB [ \-\-help ]
|
||||||
.RB [ \-\-interval=\fIseconds\fP]
|
.RB [ \-\-interval=\fIseconds\fP]
|
||||||
.RB [ \-\-no\-title ]
|
.RB [ \-\-no\-title ]
|
||||||
|
.RB [ \-\-precise ]
|
||||||
.RB [ \-\-version ]
|
.RB [ \-\-version ]
|
||||||
.I command
|
.I command
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@ -28,7 +29,24 @@ every 2 seconds; use
|
|||||||
.B \-n
|
.B \-n
|
||||||
or
|
or
|
||||||
.B \-\-interval
|
.B \-\-interval
|
||||||
to specify a different interval.
|
to specify a different interval. Normally, this interval is interpreted
|
||||||
|
as the amout of time between the completion of one run of
|
||||||
|
.I command
|
||||||
|
and the beginning of the next run. However, with the
|
||||||
|
.I \-p
|
||||||
|
or
|
||||||
|
.I \-\-precise
|
||||||
|
option, you can make
|
||||||
|
.BR watch
|
||||||
|
attempt to run
|
||||||
|
.I command
|
||||||
|
every
|
||||||
|
.I interval
|
||||||
|
seconds. Try it with
|
||||||
|
.B ntptime
|
||||||
|
and notice how the fractional seconds stays
|
||||||
|
(nearly) the same, as opposed to normal mode where they continuously
|
||||||
|
increase.
|
||||||
.PP
|
.PP
|
||||||
The
|
The
|
||||||
.B \-d
|
.B \-d
|
||||||
@ -102,11 +120,21 @@ watch echo '$$'
|
|||||||
.br
|
.br
|
||||||
watch echo "'"'$$'"'"
|
watch echo "'"'$$'"'"
|
||||||
.PP
|
.PP
|
||||||
|
To see the effect of precision time keeping, try adding
|
||||||
|
.I \-p
|
||||||
|
to
|
||||||
|
.IP
|
||||||
|
watch \-n 10 sleep 1
|
||||||
|
.PP
|
||||||
You can watch for your administrator to install the latest kernel with
|
You can watch for your administrator to install the latest kernel with
|
||||||
.IP
|
.IP
|
||||||
watch uname \-r
|
watch uname \-r
|
||||||
.PP
|
.PP
|
||||||
(Just kidding.)
|
(Note that
|
||||||
|
.I \-p
|
||||||
|
isn't guaranteed to work across reboots, especially in the face of
|
||||||
|
.B ntpdate
|
||||||
|
or other bootup time-changing mechanisms)
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Upon terminal resize, the screen will not be correctly repainted until the
|
Upon terminal resize, the screen will not be correctly repainted until the
|
||||||
next scheduled update. All
|
next scheduled update. All
|
||||||
@ -115,6 +143,22 @@ highlighting is lost on that update as well.
|
|||||||
.PP
|
.PP
|
||||||
Non-printing characters are stripped from program output. Use "cat -v" as
|
Non-printing characters are stripped from program output. Use "cat -v" as
|
||||||
part of the command pipeline if you want to see them.
|
part of the command pipeline if you want to see them.
|
||||||
|
.PP
|
||||||
|
.I \-\-precise
|
||||||
|
mode doesn't yet have advanced temporal distortion technology to
|
||||||
|
compensate for a
|
||||||
|
.I command
|
||||||
|
that takes more than
|
||||||
|
.I interval
|
||||||
|
seconds to execute.
|
||||||
|
.B watch
|
||||||
|
also can get into a state where it rapid-fires as many executions of
|
||||||
|
.I command
|
||||||
|
as it can to catch up from a previous executions running longer than
|
||||||
|
.I interval
|
||||||
|
(for example,
|
||||||
|
.B netstat
|
||||||
|
taking ages on a DNS lookup).
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
The original
|
The original
|
||||||
.B watch
|
.B watch
|
||||||
@ -122,3 +166,7 @@ was written by Tony Rems <rembo@unisoft.com> in 1991, with mods and
|
|||||||
corrections by Francois Pinard. It was reworked and new features added by
|
corrections by Francois Pinard. It was reworked and new features added by
|
||||||
Mike Coleman <mkc@acm.org> in 1999. The beep, exec, and error handling
|
Mike Coleman <mkc@acm.org> in 1999. The beep, exec, and error handling
|
||||||
features were added by Morty Abzug <morty@frakir.org> in 2008.
|
features were added by Morty Abzug <morty@frakir.org> in 2008.
|
||||||
|
On a not so dark and stormy morning
|
||||||
|
in March of 2003, Anthony DeRobertis <asd@suespammers.org> got sick of
|
||||||
|
his watches that should update every minute eventually updating many
|
||||||
|
seconds after the minute started, and added microsecond precision.
|
||||||
|
31
watch.c
31
watch.c
@ -19,6 +19,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
@ -39,13 +40,14 @@ static struct option longopts[] = {
|
|||||||
{"beep", no_argument, 0, 'b'},
|
{"beep", no_argument, 0, 'b'},
|
||||||
{"errexit", no_argument, 0, 'e'},
|
{"errexit", no_argument, 0, 'e'},
|
||||||
{"exec", no_argument, 0, 'x'},
|
{"exec", no_argument, 0, 'x'},
|
||||||
|
{"precise", no_argument, 0, 'p'},
|
||||||
{"no-title", no_argument, 0, 't'},
|
{"no-title", no_argument, 0, 't'},
|
||||||
{"version", no_argument, 0, 'v'},
|
{"version", no_argument, 0, 'v'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static char usage[] =
|
static char usage[] =
|
||||||
"Usage: %s [-bdhntvx] [--beep] [--color] [--differences[=cumulative]] [--exec] [--help] [--interval=<n>] [--no-title] [--version] <command>\n";
|
"Usage: %s [-bdhnptvx] [--beep] [--color] [--differences[=cumulative]] [--exec] [--help] [--interval=<n>] [--no-title] [--version] <command>\n";
|
||||||
|
|
||||||
static char *progname;
|
static char *progname;
|
||||||
|
|
||||||
@ -54,6 +56,7 @@ static int height = 24, width = 80;
|
|||||||
static int screen_size_changed = 0;
|
static int screen_size_changed = 0;
|
||||||
static int first_screen = 1;
|
static int first_screen = 1;
|
||||||
static int show_title = 2; // number of lines used, 2 or 0
|
static int show_title = 2; // number of lines used, 2 or 0
|
||||||
|
static int precise_timekeeping = 0;
|
||||||
|
|
||||||
#define min(x,y) ((x) > (y) ? (y) : (x))
|
#define min(x,y) ((x) > (y) ? (y) : (x))
|
||||||
#define MAX_ANSIBUF 10
|
#define MAX_ANSIBUF 10
|
||||||
@ -206,6 +209,15 @@ get_terminal_size(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get current time in usec */
|
||||||
|
typedef unsigned long long watch_usec_t;
|
||||||
|
#define USECS_PER_SEC (1000000ull)
|
||||||
|
watch_usec_t get_time_usec() {
|
||||||
|
struct timeval now;
|
||||||
|
gettimeofday(&now, NULL);
|
||||||
|
return USECS_PER_SEC*now.tv_sec + now.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -221,6 +233,8 @@ main(int argc, char *argv[])
|
|||||||
char *command;
|
char *command;
|
||||||
char **command_argv;
|
char **command_argv;
|
||||||
int command_length = 0; /* not including final \0 */
|
int command_length = 0; /* not including final \0 */
|
||||||
|
watch_usec_t next_loop; /* next loop time in us, used for precise time
|
||||||
|
keeping only */
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
int status;
|
int status;
|
||||||
pid_t child;
|
pid_t child;
|
||||||
@ -228,7 +242,7 @@ main(int argc, char *argv[])
|
|||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
while ((optc = getopt_long(argc, argv, "+bced::hn:vtx", longopts, (int *) 0))
|
while ((optc = getopt_long(argc, argv, "+bced::hn:pvtx", longopts, (int *) 0))
|
||||||
!= EOF) {
|
!= EOF) {
|
||||||
switch (optc) {
|
switch (optc) {
|
||||||
case 'b':
|
case 'b':
|
||||||
@ -266,6 +280,9 @@ main(int argc, char *argv[])
|
|||||||
interval = ~0u/1000000;
|
interval = ~0u/1000000;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
precise_timekeeping = 1;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
option_version = 1;
|
option_version = 1;
|
||||||
break;
|
break;
|
||||||
@ -289,6 +306,7 @@ main(int argc, char *argv[])
|
|||||||
fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\n", stderr);
|
fputs(" -e, --errexit\t\t\t\texit watch if the command has a non-zero exit\n", stderr);
|
||||||
fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr);
|
fputs(" -h, --help\t\t\t\tprint a summary of the options\n", stderr);
|
||||||
fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr);
|
fputs(" -n, --interval=<seconds>\t\tseconds to wait between updates\n", stderr);
|
||||||
|
fputs(" -p, --precise\t\t\t\tprecise timing, ignore command run time\n", stderr);
|
||||||
fputs(" -v, --version\t\t\t\tprint the version number\n", stderr);
|
fputs(" -v, --version\t\t\t\tprint the version number\n", stderr);
|
||||||
fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr);
|
fputs(" -t, --no-title\t\t\tturns off showing the header\n", stderr);
|
||||||
fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr);
|
fputs(" -x, --exec\t\t\t\tpass command to exec instead of sh\n", stderr);
|
||||||
@ -336,6 +354,9 @@ main(int argc, char *argv[])
|
|||||||
noecho();
|
noecho();
|
||||||
cbreak();
|
cbreak();
|
||||||
|
|
||||||
|
if (precise_timekeeping)
|
||||||
|
next_loop = get_time_usec();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
char *ts = ctime(&t);
|
char *ts = ctime(&t);
|
||||||
@ -486,6 +507,12 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
first_screen = 0;
|
first_screen = 0;
|
||||||
refresh();
|
refresh();
|
||||||
|
if (precise_timekeeping) {
|
||||||
|
watch_usec_t cur_time = get_time_usec();
|
||||||
|
next_loop += USECS_PER_SEC*interval;
|
||||||
|
if (cur_time < next_loop)
|
||||||
|
usleep(next_loop - cur_time);
|
||||||
|
} else
|
||||||
usleep(interval * 1000000);
|
usleep(interval * 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user