]> granicus.if.org Git - procps-ng/commitdiff
watch: add -r to not rexec on terminal resize
authorCraig Small <csmall@dropbear.xyz>
Tue, 17 Jan 2023 09:45:48 +0000 (20:45 +1100)
committerCraig Small <csmall@dropbear.xyz>
Tue, 17 Jan 2023 09:45:48 +0000 (20:45 +1100)
If you have the watched program doing some other thing every time its
run and you resize the window, you might get unexpected results. The
-r option lets you run only when the interval has expired.

References:
 procps-ng/procps!125
 procps-ng/procps#190

NEWS
man/watch.1
src/watch.c

diff --git a/NEWS b/NEWS
index bb664d9a9cf2b5a83cc349d5a433afa4b414c776..c319ad53f5354bdfb4c9d34a2a5f7c9787b72872 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ procps-ng-NEXT
   * vmstat: Referesh memory statistics                     Debian #1027963
   * w: Add --pids option                                   merge #159
   * watch: Pass through beep                               issue #104
+  * watch: -r option to not re-exec on SIGWINCH            merge #125
 
 procps-ng-4.0.2
 ---------------
index d130ef75abd7fe20a0321ddf42eb3053a11349aa..2007e4fd5112687953aab60ace289b335fccdd38 100644 (file)
@@ -1,4 +1,4 @@
-.TH WATCH 1 "2023-01-16" "procps-ng" "User Commands"
+.TH WATCH 1 "2023-01-17" "procps-ng" "User Commands"
 .SH NAME
 watch \- execute a program periodically, showing output fullscreen
 .SH SYNOPSIS
@@ -13,12 +13,26 @@ allows you to watch the program output change over time.  By default,
 \fIcommand\fR is run every 2 seconds and \fBwatch\fR will run until interrupted.
 .SH OPTIONS
 .TP
+\fB\-b\fR, \fB\-\-beep\fR
+Beep if command has a non-zero exit.
+.TP
+\fB\-c\fR, \fB\-\-color\fR
+Interpret ANSI color and style sequences.
+.TP
 \fB\-d\fR, \fB\-\-differences\fR[=\fIpermanent\fR]
 Highlight the differences between successive updates. If the optional
 \fIpermanent\fR argument is specified then
 .B watch
 will show all changes since the first iteration.
 .TP
+\fB\-e\fR, \fB\-\-errexit\fR
+Freeze updates on command error, and exit after a key press.
+.TP
+\fB\-g\fR, \fB\-\-chgexit\fR
+Exit when the output of
+.I command
+changes.
+.TP
 \fB\-n\fR, \fB\-\-interval\fR \fIseconds\fR
 Specify update interval.  The command will not allow quicker than 0.1 second
 interval, in which the smaller values are converted. Both '.' and ',' work
@@ -38,28 +52,21 @@ Try it with
 (if present) and notice how the fractional seconds stays (nearly) the same, as opposed to
 normal mode where they continuously increase.
 .TP
-\fB\-t\fR, \fB\-\-no\-title\fR
-Turn off the header showing the interval, command, and current time at the
-top of the display, as well as the following blank line.
-.TP
-\fB\-b\fR, \fB\-\-beep\fR
-Beep if command has a non-zero exit.
-.TP
-\fB\-e\fR, \fB\-\-errexit\fR
-Freeze updates on command error, and exit after a key press.
-.TP
-\fB\-g\fR, \fB\-\-chgexit\fR
-Exit when the output of
-.I command
-changes.
-.TP
 \fB\-q\fR, \fB\-\-equexit\fR <cycles>
 Exit when output of
 .I command
 does not change for the given number of cycles.
 .TP
-\fB\-c\fR, \fB\-\-color\fR
-Interpret ANSI color and style sequences.
+\fB\-r\fR, \fB\-\-no-rerun\fR
+Do not run the program on terminal resize, the output of the program will re-appear at the next
+regular run time.
+.TP
+\fB\-t\fR, \fB\-\-no\-title\fR
+Turn off the header showing the interval, command, and current time at the
+top of the display, as well as the following blank line.
+.TP
+\fB\-w\fR, \fB\-\-no\-wrap\fR
+Turn off line wrapping. Long lines will be truncated instead of wrapped to the next line.
 .TP
 \fB\-x\fR, \fB\-\-exec\fR
 Pass
@@ -70,9 +77,6 @@ instead of
 .B sh \-c
 which reduces the need to use extra quoting to get the desired effect.
 .TP
-\fB\-w\fR, \fB\-\-no\-wrap\fR
-Turn off line wrapping. Long lines will be truncated instead of wrapped to the next line.
-.TP
 \fB\-h\fR, \fB\-\-help\fR
 Display help text and exit.
 .TP
@@ -134,7 +138,9 @@ itself.
 Upon terminal resize, the screen will not be correctly repainted until the
 next scheduled update.  All
 .B \-\-differences
-highlighting is lost on that update as well.
+highlighting is lost on that update as well. When using the
+.B \-\-no\-rerun
+option, no output of will be visible.
 
 Non-printing characters are stripped from program output.  Use \fBcat -v\fR as
 part of the command pipeline if you want to see them.
index c65f69b801f1332ef2a9f4db60264cc770a709a3..b7ad005a7c77e3dcdb7a45e5baafacb524b1b063 100644 (file)
@@ -72,6 +72,7 @@ static int flags;
 #define WATCH_ERREXIT  (1 << 6)
 #define WATCH_CHGEXIT  (1 << 7)
 #define WATCH_EQUEXIT  (1 << 8)
+#define WATCH_NORERUN  (1 << 9)
 
 static int curses_started = 0;
 static long height = 24, width = 80;
@@ -101,6 +102,7 @@ static void __attribute__ ((__noreturn__))
                                "                         exit when output from command does not change\n"), out);
        fputs(_("  -n, --interval <secs>  seconds to wait between updates\n"), out);
        fputs(_("  -p, --precise          attempt run command in precise intervals\n"), out);
+       fputs(_("  -r, --no-rerun         do not rerun program on window resize\n"), out);
        fputs(_("  -t, --no-title         turn off header\n"), out);
        fputs(_("  -w, --no-wrap          turn off line wrapping\n"), out);
        fputs(_("  -x, --exec             pass command to exec instead of \"sh -c\"\n"), out);
@@ -814,6 +816,7 @@ int main(int argc, char *argv[])
        char *command;
        char **command_argv;
        int command_length = 0; /* not including final \0 */
+       watch_usec_t last_run = 0;
        watch_usec_t next_loop; /* next loop time in us, used for precise time
                                 * keeping only */
 #ifdef WITH_WATCH8BIT
@@ -832,6 +835,7 @@ int main(int argc, char *argv[])
                {"equexit", required_argument, 0, 'q'},
                {"exec", no_argument, 0, 'x'},
                {"precise", no_argument, 0, 'p'},
+                {"no-rerun", no_argument, 0, 'r'},
                {"no-title", no_argument, 0, 't'},
                {"no-wrap", no_argument, 0, 'w'},
                {"version", no_argument, 0, 'v'},
@@ -851,7 +855,7 @@ int main(int argc, char *argv[])
                interval = strtod_nol_or_err(interval_string, _("Could not parse interval from WATCH_INTERVAL"));
 
        while ((optc =
-               getopt_long(argc, argv, "+bced::ghq:n:pvtwx", longopts, (int *)0))
+               getopt_long(argc, argv, "+bced::ghq:n:prtwvx", longopts, (int *)0))
               != EOF) {
                switch (optc) {
                case 'b':
@@ -875,6 +879,9 @@ int main(int argc, char *argv[])
                        flags |= WATCH_EQUEXIT;
                        max_cycles = strtod_nol_or_err(optarg, _("failed to parse argument"));
                        break;
+                case 'r':
+                        flags |= WATCH_NORERUN;
+                        break;
                case 't':
                        show_title = 0;
                        break;
@@ -990,18 +997,25 @@ int main(int argc, char *argv[])
                        output_header(command, interval);
 #endif /* WITH_WATCH8BIT */
 
-               int exit = run_command(command, command_argv);
-               if (flags & WATCH_EQUEXIT) {
-                       if (cycle_count == max_cycles && exit) {
-                               break;
-                       } else if (exit) {
-                               cycle_count++;
-                       } else {
-                               cycle_count = 0;
-                       }
-               } else if (exit) {
-                       break;
-               }
+                if (!(flags & WATCH_NORERUN) ||
+                        get_time_usec() - last_run > interval * USECS_PER_SEC) {
+                    last_run = get_time_usec();
+                    int exit = run_command(command, command_argv);
+
+                   if (flags & WATCH_EQUEXIT) {
+                           if (cycle_count == max_cycles && exit) {
+                                   break;
+                           } else if (exit) {
+                                   cycle_count++;
+                           } else {
+                                   cycle_count = 0;
+                           }
+                   } else if (exit) {
+                           break;
+                   }
+                } else {
+                    refresh();
+                }
 
                if (precise_timekeeping) {
                        watch_usec_t cur_time = get_time_usec();